Update the fastcgi test code
authorJeremy Tan <[email protected]>
Thu, 15 Aug 2013 13:08:38 +0000 (21:08 +0800)
committerJeremy Tan <[email protected]>
Thu, 15 Aug 2013 13:08:38 +0000 (21:08 +0800)
testing/fastcgi-approach/fastcgi.c [new file with mode: 0644]
testing/fastcgi-approach/fastcgi_test.c [deleted file]
testing/fastcgi-approach/nginx_server_config.txt

diff --git a/testing/fastcgi-approach/fastcgi.c b/testing/fastcgi-approach/fastcgi.c
new file mode 100644 (file)
index 0000000..e4b5adb
--- /dev/null
@@ -0,0 +1,138 @@
+/**
+ * @file fastcgi.c
+ * @purpose Runs the FCGI request loop to handle web interface requests.
+ * 
+ * <stdio.h> should not be included, because these functions are handled by
+ * fcgi_stdio.h. If included, it must be included after fcgi_stdio.h.
+ */
+#include <fcgi_stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+/*
+       But the suggestion was: FunctionName, variable_name (local or member),
+    Structure, ENUMVALUE, Extern_FunctionName, g_global
+*/
+
+//Replace with whatever holds the 'data'
+typedef struct Data Data;
+enum {RESPONSE_OK = 200, RESPONSE_BADREQUEST = 400,
+         RESPONSE_UNAUTHORIZED = 401};
+
+typedef void (*ModuleHandler) (Data *data, char *params);
+
+/**
+ * Extracts a key/value pair from a request string.
+ * Note that the input is modified by this function.
+ * @param in The string from which to extract the pair
+ * @param key A pointer to a variable to hold the key string
+ * @param value A pointer to a variable to hold the value string
+ * @return A pointer to the start of the next search location, or NULL if
+ *         the EOL is reached.
+ */
+static char *KeyPair(char *in, const char **key, const char **value) {
+       char *next, *split;
+       if (!in || !*in) { //Invalid input or string is EOL
+               return NULL;
+       }
+
+       *key = in;
+       //Must be first so value will be empty if it's not specified
+       if ((next = strchr(in, '&'))) {
+               *next++ = 0;
+       } else { //Don't return NULL as current pair needs to be returned
+               next = "";
+       }
+       if ((split = strchr(in, '='))) {
+               *split++ = 0;
+               *value = split; 
+               return next;
+       }
+       //Split was not found, set to default value
+       *value = "";
+       return next ? next : "";
+}
+
+static void BeginResponse(int response_code, const char *module) {
+       switch (response_code) {
+               case RESPONSE_OK:
+                       break;
+               case RESPONSE_UNAUTHORIZED:
+                       printf("Status: 401 Unauthorized\r\n");
+                       break;
+               default:
+                       printf("Status: 400 Bad Request\r\n");
+       }
+       printf("Content-type: application/json; charset=utf-8\r\n\r\n");
+       printf("{\r\n");
+       printf("\t\"module\" : \"%s\"", module);
+}
+
+static void BuildResponse(const char *key, const char *value) {
+       printf(",\r\n\t\"%s\" : \"%s\"", key, value);
+}
+
+static void EndResponse() {
+       printf("\r\n}\r\n");
+}
+
+static void SensorsHandler(Data *data, char *params) {
+       const char *key, *value;
+       BeginResponse(RESPONSE_OK, "sensors");
+       while ((params = KeyPair(params, &key, &value))) {
+               BuildResponse(key, value);
+       }
+       EndResponse();
+       
+}
+
+void FCGI_RequestLoop (Data *data)
+{
+       int count = 0;
+       while (FCGI_Accept() >= 0)   {
+               ModuleHandler module_handler = NULL;
+               char module[BUFSIZ], params[BUFSIZ];
+               
+               //strncpy doesn't zero-truncate properly
+               snprintf(module, BUFSIZ, "%s", getenv("DOCUMENT_URI_LOCAL"));
+               snprintf(params, BUFSIZ, "%s", getenv("QUERY_STRING"));
+               
+               //Remove trailing slashes (if present) from module query
+               size_t lastchar = strlen(module) - 1;
+               if (lastchar > 0 && module[lastchar] == '/')
+                       module[lastchar] = '\0';
+               
+
+               if (!strcmp("sensors", module)) {
+                       module_handler = SensorsHandler;
+               } else if (!strcmp("admin", module)) {
+                       //module_handler = AdminHandlerReplace with pointer to admin handler
+               }
+
+               if (module_handler) {
+                       module_handler(data, params);
+               } else {
+                       char buf[BUFSIZ];
+                       
+                       BeginResponse(400, module);
+                       BuildResponse("description", "400 Invalid response");
+                       snprintf(buf, BUFSIZ, "%d", count);
+                       BuildResponse("request-number", buf);
+                       BuildResponse("params", params);
+                       BuildResponse("host", getenv("SERVER_HOSTNAME"));
+                       EndResponse();
+               }
+
+               count++;
+               //Debgging:
+               //printf("Module: %s, Params: %s<br>\n", module, params);
+               //printf("Request number %d, host <i>%s</i>\n",
+               //      count++, getenv("SERVER_HOSTNAME"));
+       }
+}
+
+int main(int argc, char *argv[]) {
+       FCGI_RequestLoop(NULL);
+}
diff --git a/testing/fastcgi-approach/fastcgi_test.c b/testing/fastcgi-approach/fastcgi_test.c
deleted file mode 100644 (file)
index 40543c6..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "fcgi_stdio.h" /* fcgi library; put it first*/
-#include <stdlib.h>
-
-/*
-       But the suggestion was: FunctionName, variable_name (local or member),
-    Structure, ENUMVALUE, Extern_FunctionName, g_global
-*/
-
-typedef struct Data Data;
-
-typedef void (*ModuleHandler) (Data *data, const char *params);
-
-static void SensorsHandler(Data *data, const char *params) {
-    printf("Sensors module!<br>");
-}
-
-/*
-   API Schema:
-   Sensors:
-   /cgi/sensors?get=x
-   *get=x is optional. Retrieves info for sensor with id x
-   Devices:
-   /cgi/devices?status=x&power=y&id=z
-   *status and power is optional
-   *status retrieves whether device with id x is operational
-   *power tells whether or not to power on/off the device with id z
-   
-   Response format:
-   200 OK if request was ok
-   400 bad request for malformed request
-      
-*/
-int main (int argc, char *argv[])
-{
-  Data *data = NULL;
-  int count = 0;
-
-  //FCGI Accept loop
-  while (FCGI_Accept() >= 0)   {
-    ModuleHandler module_handler = NULL;
-    const char *module = getenv("DOCUMENT_URI_LOCAL");
-    const char *params = getenv("QUERY_STRING");
-
-    if (!strcmp("sensors", module)) {
-        module_handler = SensorsHandler; //Replace with pointer to sensors handler
-    } else if (!strcmp("admin"), module) {
-        module_handler = NULL; //Replace with pointer to admin handler
-        printf("Admin module selected!\n");
-    }
-    
-    if (module_handler) {
-        printf("Content-type: text/html\r\n\r\n"); //Replace with actual type
-        module_handler(data, params);
-    } else {
-        printf("Status: 400 Bad Request\r\n"
-               "Content-type: text/html\r\n\r\n"
-               "<title>400 Bad Request</title>\n"
-               "Unknown module '%s' selected.<br>\n",
-               module);   
-    }
-    
-    //Debgging:
-    printf("Module: %s, Params: %s<br>\n", module, params);
-    printf("Request number %d, host <i>%s</i>\n",
-        count++, getenv("SERVER_HOSTNAME"));
-  }
-}
index c76a4e5..76be0f0 100644 (file)
@@ -1,5 +1,5 @@
         #Custom cgi
-        location ~ ^/cgi/([^?]*) {
+        location ~ ^/api/?([^?]*) {
                 fastcgi_pass 127.0.0.1:9005;
                 fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
                 fastcgi_param  SERVER_HOSTNAME    mctxsoft;

UCC git Repository :: git.ucc.asn.au