A simple web server that can be bound to either the EthernetInterface or the WiflyInterface.

Dependents:   Smart-WiFly-WebServer WattEye X10Svr SSDP_Server

Revision:
13:8975d7928678
Parent:
12:109bf1558300
Child:
14:19c5f6151319
--- a/SW_HTTPServer.cpp	Sun Aug 11 15:49:51 2013 +0000
+++ b/SW_HTTPServer.cpp	Mon Aug 12 11:26:59 2013 +0000
@@ -77,7 +77,8 @@
     Wifly * _wf,
     int port,
     const char * _webroot,
-    int _maxparams,
+    int maxheaderParams,
+    int _maxqueryParams,
     int _maxdynamicpages,
     PC * _pc,
     int _allocforheader,
@@ -86,21 +87,22 @@
     wifly = _wf;
     webroot = (char *)malloc(strlen(_webroot)+1);
     strcpy(webroot, _webroot);
-    maxparams = _maxparams;
+    maxqueryParams = _maxqueryParams;
     maxdynamicpages = _maxdynamicpages;
-    params = (namevalue *)malloc(maxparams * sizeof(namevalue));
+    headerParams = (namevalue *)malloc(maxheaderParams * sizeof(namevalue));
+    queryParams = (namevalue *)malloc(maxqueryParams * sizeof(namevalue));
     handlers = (handler *)malloc(maxdynamicpages * sizeof(handler));
     headerbuffersize = _allocforheader;
     headerbuffer = (char *)malloc(headerbuffersize);
     pc = _pc;
     queryType = NULL;
     queryString = NULL;
-    hostString = NULL;
-    contentLength = NULL;
-    contentType = NULL;
-    authorization = NULL;
+//    hostString = NULL;
+//    contentLength = NULL;
+//    contentType = NULL;
+//    authorization = NULL;
     postQueryString = NULL;
-    paramcount = 0;
+    queryParamCount = 0;
     handlercount = 0;
     maxheaderbytes = 0;
     server = new TCPSocketServer();
@@ -121,7 +123,7 @@
         myfree(handlers[i].path);
     myfree(headerbuffer);
     myfree(handlers);
-    myfree(params);
+    myfree(queryParams);
     myfree(webroot);
     webroot = NULL;
 }
@@ -322,9 +324,9 @@
 
 const char * HTTPServer::GetParameter(const char * name)
 {
-    for (int i=0; i<paramcount; i++) {
-        if (strcmp(params[i].name, name) == 0) {
-            return params[i].value;
+    for (int i=0; i<queryParamCount; i++) {
+        if (strcmp(queryParams[i].name, name) == 0) {
+            return queryParams[i].value;
         }
     }
     return NULL;
@@ -337,32 +339,32 @@
     char * pVal;
     char * pNextName;
 
-    // Parse params
+    // Parse queryParams
     pVal = strchr(pName, '#');      // If there is a '#fragment_id', we can ignore it
     if (pVal)
         *pVal = '\0';
     do {
         //pc->printf("Parse(%s)\r\n", pName);
         //*pName++ = '\0';   // already '\0' on the first entry
-        params[paramcount].name = pName;
+        queryParams[queryParamCount].name = pName;
         pVal = strchr(pName, '=');
         pNextName = strchr(pName,'&');
         if (pVal) {
             if (pNextName == NULL || (pNextName && pNextName > pVal)) {
                 *pVal++ = '\0';
-                params[paramcount].value = pVal;
+                queryParams[queryParamCount].value = pVal;
                 pName = pVal;
             }
         }
-        //pc->printf("  [%s]=[%s]\r\n", params[paramcount].name, params[paramcount].value);
-        paramcount++;
+        //pc->printf("  [%s]=[%s]\r\n", queryParams[queryParamCount].name, queryParams[queryParamCount].value);
+        queryParamCount++;
         if (pNextName) {
             pName = pNextName;
             *pName++ = '\0';
         } else {
             pName = NULL;
         }
-    } while (pName && paramcount < maxparams);
+    } while (pName && queryParamCount < maxqueryParams);
 }
 
 
@@ -493,7 +495,7 @@
     // If this queryString is in the list of registered handlers, call that
     for (int i=0; i<handlercount; i++) {
         if (strcmp(handlers[i].path, queryString) == 0) {
-            (*handlers[i].callback)(this, SEND_PAGE, queryString, params, paramcount);
+            (*handlers[i].callback)(this, SEND_PAGE, queryString, queryParams, queryParamCount);
             regHandled = true;
             break;      // we only execute the first one
         }
@@ -544,22 +546,22 @@
         myfree(queryString);
         queryString = NULL;
     }
-    if (hostString) {
-        myfree(hostString);
-        hostString = NULL;
-    }
-    if (contentLength) {
-        myfree(contentLength);
-        contentLength = NULL;
-    }
-    if (contentType) {
-        myfree(contentType);
-        contentType = NULL;
-    }
-    if (authorization) {
-        myfree(authorization);
-        authorization = NULL;
-    }
+//    if (hostString) {
+//        myfree(hostString);
+//        hostString = NULL;
+//    }
+//    if (contentLength) {
+//        myfree(contentLength);
+//        contentLength = NULL;
+//    }
+//    if (contentType) {
+//        myfree(contentType);
+//        contentType = NULL;
+//    }
+//    if (authorization) {
+//        myfree(authorization);
+//        authorization = NULL;
+//    }
     if (postQueryString) {
         myfree(postQueryString);
         postQueryString = NULL;
@@ -573,7 +575,7 @@
     int bytecount;
 
     // Buffer could have partial, but the double \r\n is the key
-    //      GET /QueryString HTTP/1.1\r\n
+    //      GET /QueryString?this=that&sky=blue HTTP/1.1\r\n
     //      GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Con
     //      GET /QueryString HTTP/1.1\r\nHost: 192.168.1.140\r\nCache-Control: max-age=0\r\n\r\n
     dblCR = strstr(buffer,"\r\n\r\n");
@@ -582,8 +584,9 @@
         pc->printf("==\r\n%s==\r\n", buffer);
 #endif
         char * soRec = buffer;                  // start of the next record of text
-        char * eoRec = strchr(soRec, '\n');     // search for end of a record
+        char * eoRec = strchr(soRec, '\n');     // search for end of the current record
 
+        headerParamCount = 0;
         bytecount = strlen(buffer);
         if (bytecount > maxheaderbytes)
             maxheaderbytes = bytecount;
@@ -611,10 +614,28 @@
                 }
                 //printf("POST: %s\r\n", queryString);
             }
-            Extract(soRec, "Host: ", &hostString);
-            Extract(soRec, "Content-Length: ", &contentLength);
-            Extract(soRec, "Content-Type: ", &contentType);
-            Extract(soRec, "Authorization: ", &authorization);
+
+            // if there is a ": " delimiter, we have a header item to parse into name,value pair
+            // "Connection: keep-alive" becomes "Connection" "keep-alive"
+            char *delim = strstr(soRec, ": ");
+            char *chkSpace = strchr(soRec, ' ');        // a field-name has no space ahead of the ":"
+            if (delim 
+            && (!chkSpace || (chkSpace && delim < chkSpace))
+            && headerParamCount < maxheaderParams) {
+                *delim++ = '\0';
+                *delim++ = '\0';
+                headerParams[headerParamCount].name = soRec;
+                headerParams[headerParamCount].value = delim;
+#ifdef DEBUG
+                pc->printf("%d: headerParams[%s] = {%s}\r\n", headerParamCount,
+                           headerParams[headerParamCount].name, headerParams[headerParamCount].value);
+#endif
+                headerParamCount++;
+            }
+//            Extract(soRec, "Host: ", &hostString);
+//            Extract(soRec, "Content-Length: ", &contentLength);
+//            Extract(soRec, "Content-Type: ", &contentType);
+//            Extract(soRec, "Authorization: ", &authorization);
             soRec = eoRec + 1;
             eoRec = strchr(soRec, '\n');
         }
@@ -623,18 +644,18 @@
 #ifdef DEBUG
             pc->printf("create reply queryType{%s}, queryString{%s}\r\n", "GET", queryString);
 #endif
-            // parse params - if any
+            // parse queryParams - if any
             // /file.htm?name1=value1&name2=value2...
             // /file.htm?name1&name2=value2...
-            paramcount = 0;
+            queryParamCount = 0;
             char * paramDelim = strchr(queryString, '?');
             if (paramDelim) {
                 *paramDelim++ = '\0';
                 UnescapeString(paramDelim);   // everything after the '?'
-                ParseParameters(paramDelim);    // pointing at the NULL, but there are params beyond
+                ParseParameters(paramDelim);    // pointing at the NULL, but there are queryParams beyond
             }
-            //for (int i=0; i<paramcount; i++)
-            //    pc->printf("param %d '%s'='%s'\r\n", i, params[i].name, params[i].value);
+            //for (int i=0; i<queryParamCount; i++)
+            //    pc->printf("param %d '%s'='%s'\r\n", i, queryParams[i].name, queryParams[i].value);
         } else {
             pc->printf("ERROR: queryString not found in (%s)\r\n", soRec);
         }
@@ -648,7 +669,7 @@
         // the requested 'Content-Length' amount of memory.
         // Should we check the 'Content-Type' to see if it is
         //   'application/x-www-form-urlencoded'?
-        int postBytes = atoi(contentLength);
+        int postBytes = atoi(GetHeaderValue("Content-Length"));
         bool acceptIt = false;
         //pc->printf("Content-Length = %d\r\n", postBytes);
         if (strcmp(queryType, "POST") == 0 && postBytes > 0 ) {
@@ -658,7 +679,7 @@
                 // Callback and ask if they want to accept this data
                 for (int i=0; i<handlercount; i++) {
                     if (strcmp(handlers[i].path, queryString) == 0) {
-                        acceptIt = (*handlers[i].callback)(this, CONTENT_LENGTH_REQUEST, queryString, params, paramcount);
+                        acceptIt = (*handlers[i].callback)(this, CONTENT_LENGTH_REQUEST, queryString, queryParams, queryParamCount);
                         regHandled = true;
                         break;      // we only execute the first one
                     }
@@ -709,6 +730,18 @@
     return advanceState;
 }
 
+const char * HTTPServer::GetHeaderValue(const char * hdr)
+{
+    int i;
+    
+    for (i=0; i<headerParamCount; i++)
+        {
+        if (strcmp(hdr, headerParams[i].name) == 0)
+            return headerParams[i].value;
+        }
+    return NULL;
+}
+
 
 void HTTPServer::GetPerformanceData(SW_PerformanceData * p)
 {