fix redundant code, add makefile and example webpage
[matches/MCTX3420.git] / testing / fastcgi-approach / fastcgi.c
1 /**
2  * @file fastcgi.c
3  * @purpose Runs the FCGI request loop to handle web interface requests.
4  * 
5  * <stdio.h> should not be included, because these functions are handled by
6  * fcgi_stdio.h. If included, it must be included after fcgi_stdio.h.
7  */
8  
9 #include <fcgi_stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12
13 /*
14         But the suggestion was: FunctionName, variable_name (local or member),
15     Structure, ENUMVALUE, Extern_FunctionName, g_global
16 */
17
18 //Replace with whatever holds the 'data'
19 typedef struct Data Data;
20 enum {RESPONSE_OK = 200, RESPONSE_BADREQUEST = 400,
21           RESPONSE_UNAUTHORIZED = 401};
22
23 typedef void (*ModuleHandler) (Data *data, char *params);
24
25 /**
26  * Extracts a key/value pair from a request string.
27  * Note that the input is modified by this function.
28  * @param in The string from which to extract the pair
29  * @param key A pointer to a variable to hold the key string
30  * @param value A pointer to a variable to hold the value string
31  * @return A pointer to the start of the next search location, or NULL if
32  *         the EOL is reached.
33  */
34 static char *KeyPair(char *in, const char **key, const char **value) {
35         char *next, *split;
36         if (!in || !*in) { //Invalid input or string is EOL
37                 return NULL;
38         }
39
40         *key = in;
41         //Must be first so value will be empty if it's not specified
42         if ((next = strchr(in, '&'))) {
43                 *next++ = 0;
44         } else { //Don't return NULL as current pair needs to be returned
45                 next = "";
46         }
47         if ((split = strchr(in, '='))) {
48                 *split++ = 0;
49                 *value = split; 
50                 return next;
51         }
52         //Split was not found, set to default value
53         *value = "";
54         return next;
55 }
56
57 static void BeginResponse(int response_code, const char *module) {
58         switch (response_code) {
59                 case RESPONSE_OK:
60                         break;
61                 case RESPONSE_UNAUTHORIZED:
62                         printf("Status: 401 Unauthorized\r\n");
63                         break;
64                 default:
65                         printf("Status: 400 Bad Request\r\n");
66         }
67         printf("Content-type: application/json; charset=utf-8\r\n\r\n");
68         printf("{\r\n");
69         printf("\t\"module\" : \"%s\"", module);
70 }
71
72 static void BuildResponse(const char *key, const char *value) {
73         printf(",\r\n\t\"%s\" : \"%s\"", key, value);
74 }
75
76 static void EndResponse() {
77         printf("\r\n}\r\n");
78 }
79
80 static void SensorsHandler(Data *data, char *params) {
81         const char *key, *value;
82         BeginResponse(RESPONSE_OK, "sensors");
83  
84         while ((params = KeyPair(params, &key, &value))) {
85                 BuildResponse(key, value);
86         }
87         EndResponse();
88         
89 }
90
91 void FCGI_RequestLoop (Data *data)
92 {
93         int count = 0;
94         while (FCGI_Accept() >= 0)   {
95                 ModuleHandler module_handler = NULL;
96                 char module[BUFSIZ], params[BUFSIZ];
97                 
98                 //strncpy doesn't zero-truncate properly
99                 snprintf(module, BUFSIZ, "%s", getenv("DOCUMENT_URI_LOCAL"));
100                 snprintf(params, BUFSIZ, "%s", getenv("QUERY_STRING"));
101                 
102                 //Remove trailing slashes (if present) from module query
103                 size_t lastchar = strlen(module) - 1;
104                 if (lastchar > 0 && module[lastchar] == '/')
105                         module[lastchar] = '\0';
106                 
107
108                 if (!strcmp("sensors", module)) {
109                         module_handler = SensorsHandler;
110                 } else if (!strcmp("admin", module)) {
111                         //module_handler = AdminHandlerReplace with pointer to admin handler
112                 }
113
114                 if (module_handler) {
115                         module_handler(data, params);
116                 } else {
117                         char buf[BUFSIZ];
118                         
119                         BeginResponse(400, module);
120                         BuildResponse("description", "400 Invalid response");
121                         snprintf(buf, BUFSIZ, "%d", count);
122                         BuildResponse("request-number", buf);
123                         BuildResponse("params", params);
124                         BuildResponse("host", getenv("SERVER_HOSTNAME"));
125                         EndResponse();
126                 }
127
128                 count++;
129                 //Debgging:
130                 //printf("Module: %s, Params: %s<br>\n", module, params);
131                 //printf("Request number %d, host <i>%s</i>\n",
132                 //      count++, getenv("SERVER_HOSTNAME"));
133         }
134 }
135
136 int main(int argc, char *argv[]) {
137         FCGI_RequestLoop(NULL);
138 }

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