A simple web server that can be bound to either the EthernetInterface or the WiflyInterface.
Dependents: Smart-WiFly-WebServer WattEye X10Svr SSDP_Server
Diff: SW_HTTPServer.cpp
- Revision:
- 39:0427544a5c08
- Parent:
- 38:c8fa31e6fe02
- Child:
- 40:02c49fadbb94
--- a/SW_HTTPServer.cpp Sat Jul 26 19:49:13 2014 +0000 +++ b/SW_HTTPServer.cpp Mon Sep 01 20:53:19 2014 +0000 @@ -35,7 +35,7 @@ const char * DEFAULT_FILENAME = "index.htm"; // Header information to always send (must be \r\n terminated) -const char hdr_httpver[] = "HTTP/1.0"; // Wifly may not be able to support HTTP/1.1 protocol +const char hdr_httpver[] = "HTTP/1.0"; // supported HTTP/1.1 protocol const char hdr_age[] = "Max-age: 0\r\n"; // expires right away const char hdr_server[] = "Server: Smart_Server v0.1\r\n"; // Server const char hdr_close[] = "Connection: close\r\n"; // tell the client the server closes the connection immediately @@ -92,7 +92,6 @@ #endif HTTPServer::HTTPServer( - void * _wf, int port, const char * _webroot, int maxheaderParams, @@ -102,15 +101,21 @@ int _allocforheader, int _allocforfile) { - (void)_wf; webroot = (char *)malloc(strlen(_webroot)+1); strcpy(webroot, _webroot); if (strlen(webroot)>1 && webroot[strlen(webroot)-1] == '/') // remove trailing '/' webroot[strlen(webroot)-1] = '\0'; - maxqueryParams = _maxqueryParams; maxdynamicpages = _maxdynamicpages; headerParams = (namevalue *)malloc(maxheaderParams * sizeof(namevalue)); + + maxqueryParams = _maxqueryParams; queryParams = (namevalue *)malloc(maxqueryParams * sizeof(namevalue)); + queryParamCount = 0; + + maxPostParams = _maxqueryParams; // Same as Query params, but for post method + postParams = (namevalue *)malloc(maxPostParams * sizeof(namevalue)); + postParamCount = 0; + handlers = (handler *)malloc(maxdynamicpages * sizeof(handler)); headerbuffersize = _allocforheader; headerbuffer = (char *)malloc(headerbuffersize); @@ -118,7 +123,6 @@ queryType = NULL; queryString = NULL; postQueryString = NULL; - queryParamCount = 0; handlercount = 0; maxheaderbytes = 0; server = new TCPSocketServer(); @@ -336,6 +340,7 @@ return 16 * HexCharToInt(*p) + HexCharToInt(*(p+1)); } +// modifies in-place void HTTPServer::UnescapeString(char * encoded) { char *p; @@ -377,10 +382,38 @@ return NULL; } +HTTPServer::namevalue * HTTPServer::GetParameter(int index) +{ + if (index < queryParamCount) + return &queryParams[index]; + else + return NULL; +} + +const char * HTTPServer::GetPostParameter(const char * name) +{ + INFO("GetPostParameter(%s)", name); + for (int i=0; i<postParamCount; i++) { + INFO(" %d: %s = %s", i, postParams[i].name, postParams[i].value); + if (strcmp(postParams[i].name, name) == 0) { + INFO(" value {%s}", postParams[i].value); + return postParams[i].value; + } + } + return NULL; +} + +HTTPServer::namevalue * HTTPServer::GetPostParameter(int index) +{ + if (index < postParamCount) + return &postParams[index]; + else + return NULL; +} // this=that&who=what&more=stuff... // ^ ^ ^ -int HTTPServer::ParseParameters(char * pName) +int HTTPServer::ParseParameters(namevalue * qP, int * qpCount, int maxP, char * pName) { char * pVal; char * pNextName; @@ -390,14 +423,14 @@ if (pVal) *pVal = '\0'; do { - INFO("ParseParameters(%s)", pName); - queryParams[queryParamCount].name = pName; + INFO("ParseParameters(%s), qP:{%s}, qpCount: %d", pName, qP->name, *qpCount); + qP->name = pName; pVal = strchr(pName, '='); pNextName = strchr(pName,'&'); if (pVal) { if (pNextName == NULL || (pNextName && pNextName > pVal)) { *pVal++ = '\0'; - queryParams[queryParamCount].value = pVal; + qP->value = pVal; pName = pVal; } } @@ -407,11 +440,12 @@ } else { pName = NULL; } - INFO(" param{%s}={%s}", queryParams[queryParamCount].name, queryParams[queryParamCount].value); - queryParamCount++; - } while (pName && queryParamCount < maxqueryParams); - INFO(" count %d", queryParamCount); - return queryParamCount; + INFO(" param{%s}={%s}", qP->name, qP->value); + *qpCount += 1; + qP++; + } while (pName && *qpCount < maxP); + INFO(" count %d", *qpCount); + return *qpCount; } @@ -522,6 +556,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) { + INFO("CheckDynamicHandlers - SEND_PAGE"); (*handlers[i].callback)(this, SEND_PAGE, queryString, queryParams, queryParamCount); regHandled = true; break; // we only execute the first one @@ -586,7 +621,7 @@ // 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 - // POST /dyn2 HTTP/1.2\r\nAccept: text/html, application/xhtml+xml, */*\r\n\r\nle + // POST /dyn2 HTTP/1.2\r\nAccept: text/html, application/xhtml+xml, */*\r\n\r\n dblCR = strstr(buffer,"\r\n\r\n"); if (dblCR) { // Have to scan from the beginning in case split on \r INFO("\r\n==\r\n%s==", buffer); @@ -611,7 +646,7 @@ strcpy(queryType, "GET"); } } else if (strstr(soRec, "POST ") == soRec) { - Extract(soRec, "POST", &queryString); + Extract(soRec, "POST", &queryString); if (queryString) { queryType = (char *)mymalloc(strlen("POST")+1); strcpy(queryType, "POST"); @@ -648,7 +683,7 @@ if (paramDelim) { *paramDelim++ = '\0'; UnescapeString(paramDelim); // everything after the '?' - ParseParameters(paramDelim); // pointing past the NULL, and there are queryParams here + ParseParameters(queryParams, &queryParamCount, maxqueryParams, paramDelim); // pointing past the NULL, and there are queryParams here } } else { ERR("queryString not found in (%s) [this should never happen]", soRec); @@ -704,12 +739,12 @@ strcpy(postQueryString, dblCR); INFO(" {%s}", postQueryString); while (ttlCount <= postBytes && !escape) { - INFO("ttlCount: %d < postBytes: %d, of chunk %d", ttlCount, postBytes, CHUNK_SIZE); + INFO("ttlCount: %d <= postBytes: %d, of chunk %d", ttlCount, postBytes, CHUNK_SIZE); len = client.receive_all(postQueryString + ttlCount, CHUNK_SIZE - ttlCount); if (len > 0) { - INFO(" len: %d, ttlCount: %d < postBytes %d, {%s}", len, ttlCount, postBytes, postQueryString); + INFO(" len: %d, ttlCount: %d < postBytes %d, {%s}", len, ttlCount, postBytes, postQueryString + ttlCount); ttlCount += len; - postQueryString[len] = '\0'; // Whether binary or ASCII, this is ok as it's after the data + postQueryString[ttlCount] = '\0'; // Whether binary or ASCII, this is ok as it's after the data INFO(" postBytes %d: [%s], [%d]", postBytes, postQueryString, ndxHandler); escapePlan.reset(); } else if (len < 0) { @@ -723,10 +758,12 @@ WARN("Escape plan activated."); } } - acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, postQueryString, NULL, 0); + postParamCount = 0; + INFO("post: %s", postQueryString); + ParseParameters(postParams, &postParamCount, maxPostParams, postQueryString); + acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER, queryString, queryParams, queryParamCount); INFO("..processing exit"); acceptIt = (*handlers[ndxHandler].callback)(this, DATA_TRANSFER_END, NULL, NULL, 0); - myfree(postQueryString); } else { ERR("attempt to allocate %d failed.", CHUNK_SIZE); }