From 904ea65380ba858ab899b6d04a6a9f5e3aaeccbb Mon Sep 17 00:00:00 2001 From: Jeremy Tan Date: Thu, 15 Aug 2013 21:08:38 +0800 Subject: [PATCH] Update the fastcgi test code --- testing/fastcgi-approach/fastcgi.c | 138 ++++++++++++++++++ testing/fastcgi-approach/fastcgi_test.c | 67 --------- .../fastcgi-approach/nginx_server_config.txt | 2 +- 3 files changed, 139 insertions(+), 68 deletions(-) create mode 100644 testing/fastcgi-approach/fastcgi.c delete mode 100644 testing/fastcgi-approach/fastcgi_test.c diff --git a/testing/fastcgi-approach/fastcgi.c b/testing/fastcgi-approach/fastcgi.c new file mode 100644 index 0000000..e4b5adb --- /dev/null +++ b/testing/fastcgi-approach/fastcgi.c @@ -0,0 +1,138 @@ +/** + * @file fastcgi.c + * @purpose Runs the FCGI request loop to handle web interface requests. + * + * should not be included, because these functions are handled by + * fcgi_stdio.h. If included, it must be included after fcgi_stdio.h. + */ + +#include +#include +#include + +/* + 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
\n", module, params); + //printf("Request number %d, host %s\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 index 40543c6..0000000 --- a/testing/fastcgi-approach/fastcgi_test.c +++ /dev/null @@ -1,67 +0,0 @@ -#include "fcgi_stdio.h" /* fcgi library; put it first*/ -#include - -/* - 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!
"); -} - -/* - 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" - "400 Bad Request\n" - "Unknown module '%s' selected.
\n", - module); - } - - //Debgging: - printf("Module: %s, Params: %s
\n", module, params); - printf("Request number %d, host %s\n", - count++, getenv("SERVER_HOSTNAME")); - } -} diff --git a/testing/fastcgi-approach/nginx_server_config.txt b/testing/fastcgi-approach/nginx_server_config.txt index c76a4e5..76be0f0 100644 --- a/testing/fastcgi-approach/nginx_server_config.txt +++ b/testing/fastcgi-approach/nginx_server_config.txt @@ -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; -- 2.20.1