Renamed the HttpParserStatus enum members for the sake of consistency, added the 414 http error : URI too long, reworked the parsing of http resource queries, removedd the use of lastIndexOf, replaced useless strstr with strchr where needed
This commit is contained in:
parent
5d05bdb144
commit
ec7c608dfe
@ -13,7 +13,15 @@ template <typename T>
|
|||||||
class WEBServer : public TCPServer<T>, public HttpConstants
|
class WEBServer : public TCPServer<T>, public HttpConstants
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum HttpParserStatus {HTTP_VERB, HTTP_RESSOURCE, HTTP_VERSION, HTTP_PARAMS, POST_DATA, HEADER_PARAMS};
|
enum HttpParserStatus
|
||||||
|
{
|
||||||
|
PARSE_HTTP_VERB,
|
||||||
|
PARSE_HTTP_RESOURCE,
|
||||||
|
PARSE_HTTP_VERSION,
|
||||||
|
PARSE_HTTP_RESOURCE_QUERY,
|
||||||
|
PARSE_HTTP_POST_DATA,
|
||||||
|
PARSE_HTTP_HEADER_PARAMS
|
||||||
|
};
|
||||||
enum WEBClientState {ACCEPTED, PARSING, QUERY_PARSED, RESPONSE_SENT, DONE};
|
enum WEBClientState {ACCEPTED, PARSING, QUERY_PARSED, RESPONSE_SENT, DONE};
|
||||||
|
|
||||||
struct HttpRequestData
|
struct HttpRequestData
|
||||||
@ -23,7 +31,6 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
HttpMIMEType HMT;
|
HttpMIMEType HMT;
|
||||||
|
|
||||||
Dictionary<DictionaryHelper::StringEntity> getParams;
|
Dictionary<DictionaryHelper::StringEntity> getParams;
|
||||||
char *getParamsDataPointer; //Used in the getParams algorithm
|
|
||||||
Dictionary<DictionaryHelper::StringEntity> postParams;
|
Dictionary<DictionaryHelper::StringEntity> postParams;
|
||||||
char *postParamsDataPointer; //Used in the postParams algorithm
|
char *postParamsDataPointer; //Used in the postParams algorithm
|
||||||
|
|
||||||
@ -33,7 +40,7 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
uint16_t maxBodyBuffer;
|
uint16_t maxBodyBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
WEBServer(uint16_t port = 80, SDClass *sdClass = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 255) : TCPServer<T>(port, maxClient, clientDataBufferSize), _sdClass(sdClass) {}
|
WEBServer(uint16_t port = 80, SDClass *sdClass = NULL, uint8_t maxClient = MAX_CLIENT, uint16_t clientDataBufferSize = 256) : TCPServer<T>(port, maxClient, clientDataBufferSize), _sdClass(sdClass) {}
|
||||||
|
|
||||||
boolean addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*), void *pData, HttpRequestMethod HRM = UNDEFINED)
|
boolean addApiRoutine(const char *uri, boolean (*apiRoutine)(HttpRequestData&, WiFiClient*, void*), void *pData, HttpRequestMethod HRM = UNDEFINED)
|
||||||
{
|
{
|
||||||
@ -112,13 +119,13 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
{
|
{
|
||||||
switch(client->_httpParserState)
|
switch(client->_httpParserState)
|
||||||
{
|
{
|
||||||
case HttpParserStatus::HTTP_VERB:
|
case HttpParserStatus::PARSE_HTTP_VERB:
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_WEBS
|
#ifdef DEBUG_WEBS
|
||||||
Serial.println((char *)client->_data);
|
Serial.println((char *)client->_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *pVerb = strstr((char *)client->_data, " ");
|
char *pVerb(strchr((char *)client->_data, ' '));
|
||||||
|
|
||||||
if(pVerb != NULL)
|
if(pVerb != NULL)
|
||||||
{
|
{
|
||||||
@ -138,7 +145,7 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
Serial.println((char *)client->_data);
|
Serial.println((char *)client->_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
client->_httpParserState = HttpParserStatus::HTTP_RESSOURCE;
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_RESOURCE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -147,24 +154,46 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HttpParserStatus::HTTP_RESSOURCE:
|
case HttpParserStatus::PARSE_HTTP_RESOURCE:
|
||||||
{
|
{
|
||||||
char *pRsrc = strstr((char *)client->_data, " ");
|
char *pRsrc(strchr((char *)client->_data, ' ')), *pRsrcQuery(strchr((char *)client->_data, '?'));
|
||||||
|
//The case where we have the resource complete or not complete with query parameters like : GET /some/path/resource.rsrc?param1=one¶m2 HTTP/1.1
|
||||||
if(pRsrc != NULL)
|
if(pRsrc || pRsrcQuery)
|
||||||
{
|
{
|
||||||
*pRsrc = '\0';
|
uint16_t rawLengthOfResource(0);
|
||||||
uint16_t safeLength = pRsrc - (char *)client->_data <= client->_httpRequestData.maxResourceBuffer ? pRsrc - (char *)client->_data : client->_httpRequestData.maxResourceBuffer;
|
if(pRsrcQuery)
|
||||||
|
|
||||||
#ifdef DEBUG_WEBS
|
|
||||||
Serial.print("Resrc length : ");Serial.println(safeLength);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
client->_httpRequestData.httpResource = (char *) malloc(sizeof(char) * (safeLength+1) ); //for \0
|
|
||||||
if(client->_httpRequestData.httpResource != NULL)
|
|
||||||
{
|
{
|
||||||
strncpy(client->_httpRequestData.httpResource, (char *)client->_data, safeLength);
|
*pRsrcQuery = '\0'; // The ? is the end of the resource string
|
||||||
client->_httpRequestData.httpResource[safeLength] = '\0';
|
rawLengthOfResource = pRsrcQuery - (char *)client->_data;
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("Resource w/ query\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*pRsrc = '\0';
|
||||||
|
rawLengthOfResource = pRsrc - (char *)client->_data;
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("Resource w/o query\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if(rawLengthOfResource >= client->_httpRequestData.maxResourceBuffer) //Then we cannot handle the full resource and there is no point of truncating it
|
||||||
|
//better tell the client about it ...
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("Resource too long\nResource raw length is : %u (\\0 included)\nMax length is : %u (\\0 included)\nclient->_data : #%s#\n", rawLengthOfResource + 1, client->_httpRequestData.maxResourceBuffer, (char *)client->_data);
|
||||||
|
#endif
|
||||||
|
sendInfoResponse(HTTP_CODE::HTTP_CODE_URI_TOO_LONG, client, "Resource too long");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
client->_httpRequestData.httpResource = (char *) malloc(sizeof(char) * (rawLengthOfResource + 1)); // +1 for the \0
|
||||||
|
if(client->_httpRequestData.httpResource != nullptr)
|
||||||
|
{
|
||||||
|
strncpy(client->_httpRequestData.httpResource, (char *)client->_data, rawLengthOfResource);
|
||||||
|
client->_httpRequestData.httpResource[rawLengthOfResource] = '\0';
|
||||||
}
|
}
|
||||||
else //Error 500
|
else //Error 500
|
||||||
{
|
{
|
||||||
@ -173,38 +202,38 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->freeDataBuffer(safeLength + 1);
|
client->freeDataBuffer(rawLengthOfResource + 1); //+1 to go past the \0, only the query parameters left in the buffer '?' excluded
|
||||||
|
|
||||||
#ifdef DEBUG_WEBS
|
#ifdef DEBUG_WEBS
|
||||||
Serial.print("Resrc : ");Serial.println(client->_httpRequestData.httpResource);
|
Serial.printf("Resource length : %u\nRsrc : %s\nclient->_data : #%s#\n",
|
||||||
Serial.println((char *)client->_data);
|
rawLengthOfResource,
|
||||||
|
client->_httpRequestData.httpResource,
|
||||||
|
(char *)client->_data);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
else //Resource is probably too long, so we truncate it
|
|
||||||
{
|
|
||||||
client->_httpRequestData.httpResource = (char *) malloc(sizeof(char) * (client->_httpRequestData.maxResourceBuffer+1) ); //for \0
|
|
||||||
if(client->_httpRequestData.httpResource != NULL)
|
|
||||||
{
|
|
||||||
strncpy(client->_httpRequestData.httpResource, (char *)client->_data, client->_httpRequestData.maxResourceBuffer);
|
|
||||||
client->_httpRequestData.httpResource[client->_httpRequestData.maxResourceBuffer] = '\0';
|
|
||||||
}
|
|
||||||
else //Error 500
|
|
||||||
{
|
|
||||||
sendInfoResponse(HTTP_CODE::HTTP_CODE_INTERNAL_SERVER_ERROR, client, "Failed to allocate memory for resources");
|
|
||||||
client->_clientState = TCPClient::ClientState::DISCARDED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
client->freeDataBuffer(client->_httpRequestData.maxResourceBuffer + 1);
|
if(pRsrcQuery)
|
||||||
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_RESOURCE_QUERY;
|
||||||
|
else
|
||||||
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_VERSION;
|
||||||
|
}
|
||||||
|
else //The URL is too long to fit in the buffer, we dont know it's length nor we now if it has query parameters.
|
||||||
|
//TODO : Maybe the query is incomplete and the client will send more data, case to handle.
|
||||||
|
{
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("Could not find ' ' or '?' delimiter\nclient->_data : #%s#\n",
|
||||||
|
(char *)client->_data);
|
||||||
|
#endif
|
||||||
|
sendInfoResponse(HTTP_CODE::HTTP_CODE_URI_TOO_LONG, client, "Resource too long");
|
||||||
|
client->_clientState = TCPClient::ClientState::DISCARDED;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
client->_httpParserState = HttpParserStatus::HTTP_PARAMS;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HttpParserStatus::HTTP_VERSION:
|
case HttpParserStatus::PARSE_HTTP_VERSION:
|
||||||
{
|
{
|
||||||
char *pEndline = strstr((char *)client->_data, "\r\n");
|
char *pEndline = strstr((char *)client->_data, "\r\n");
|
||||||
|
|
||||||
if(pEndline == NULL) pEndline = strstr((char *)client->_data, "\n");
|
if(pEndline == NULL) pEndline = strchr((char *)client->_data, '\n');
|
||||||
|
|
||||||
char *pVers = strstr((char *)client->_data, "HTTP/");
|
char *pVers = strstr((char *)client->_data, "HTTP/");
|
||||||
|
|
||||||
@ -224,25 +253,29 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
Serial.println((char *)client->_data);
|
Serial.println((char *)client->_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
client->_httpParserState = HttpParserStatus::HEADER_PARAMS;
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_HEADER_PARAMS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HttpParserStatus::HTTP_PARAMS: //index.htm?var1=1&var2=2...
|
|
||||||
|
//index.htm?var1=1&var2=2...
|
||||||
|
//----------^^^^^^^^^^^^^^
|
||||||
|
case HttpParserStatus::PARSE_HTTP_RESOURCE_QUERY:
|
||||||
|
//If we are here, it means we are sure that there is at least one parameter
|
||||||
if(!httpRsrcParamParser(client))
|
if(!httpRsrcParamParser(client))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_WEBS
|
#ifdef DEBUG_WEBS
|
||||||
Serial.print("Resrc : ");Serial.println(client->_httpRequestData.httpResource);
|
|
||||||
Serial.println("Get params :");
|
Serial.println("Get params :");
|
||||||
for(int i = 0; i < client->_httpRequestData.getParams.count(); i++)
|
for(unsigned int i = 0; i < client->_httpRequestData.getParams.count(); i++)
|
||||||
{
|
{
|
||||||
Serial.print(client->_httpRequestData.getParams.getParameter(i));Serial.print(" : ");Serial.println(client->_httpRequestData.getParams.getAt(i)->getString());
|
Serial.printf("%s : %s\n", client->_httpRequestData.getParams.getParameter(i), client->_httpRequestData.getParams.getAt(i)->getString());
|
||||||
}
|
}
|
||||||
|
Serial.printf("client->_data : #%s#\n", client->_data);
|
||||||
#endif
|
#endif
|
||||||
client->_httpParserState = HttpParserStatus::HTTP_VERSION;
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_VERSION;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HttpParserStatus::HEADER_PARAMS: //Here we parse the different header params until we arrive to \r\n\r\n
|
case HttpParserStatus::PARSE_HTTP_HEADER_PARAMS: //Here we parse the different header params until we arrive to \r\n\r\n
|
||||||
{
|
{
|
||||||
char *pEndLine = strstr((char *)client->_data, "\r\n");
|
char *pEndLine = strstr((char *)client->_data, "\r\n");
|
||||||
|
|
||||||
@ -254,7 +287,7 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
|
|
||||||
if(*(pEndLine+2) == '\r') //We got \r\n\r\n -> so we go to the post data section
|
if(*(pEndLine+2) == '\r') //We got \r\n\r\n -> so we go to the post data section
|
||||||
{
|
{
|
||||||
client->_httpParserState = HttpParserStatus::POST_DATA;
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_POST_DATA;
|
||||||
client->freeDataBuffer((pEndLine - (char *)client->_data) +3); //client->_data must not be empty...
|
client->freeDataBuffer((pEndLine - (char *)client->_data) +3); //client->_data must not be empty...
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -265,11 +298,11 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
}
|
}
|
||||||
else //Error : indeed, we should at least have : \r\n. We go to the next step anyway
|
else //Error : indeed, we should at least have : \r\n. We go to the next step anyway
|
||||||
{
|
{
|
||||||
client->_httpParserState = HttpParserStatus::POST_DATA;
|
client->_httpParserState = HttpParserStatus::PARSE_HTTP_POST_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case HttpParserStatus::POST_DATA:
|
case HttpParserStatus::PARSE_HTTP_POST_DATA:
|
||||||
|
|
||||||
switch(client->_httpRequestData.HMT)
|
switch(client->_httpRequestData.HMT)
|
||||||
{
|
{
|
||||||
@ -391,65 +424,59 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function is here to parse resources parameters
|
* This function is here to parse resources query parameters
|
||||||
*/
|
*/
|
||||||
boolean httpRsrcParamParser(T *client)
|
boolean httpRsrcParamParser(T *client)
|
||||||
{
|
{
|
||||||
char *pGetParam = strchr((char *)client->_httpRequestData.httpResource, '?');
|
char *end(strchr((char *)client->_data, ' '));
|
||||||
|
|
||||||
|
//If we find the end we mark it, this is needed for subsequent strchr
|
||||||
|
if(end)*end = '\0';
|
||||||
|
|
||||||
if(pGetParam != NULL) //There are some params to be parsed
|
char *key(strchr((char *)client->_data, '=')), *value(strchr((char *)client->_data, '&'));
|
||||||
{
|
|
||||||
if(client->_httpRequestData.getParamsDataPointer == NULL)
|
if(key == nullptr && value == nullptr) //Only the key is present
|
||||||
{
|
|
||||||
client->_httpRequestData.getParamsDataPointer = pGetParam +1;//We save the starting position of the string to parse
|
|
||||||
}
|
|
||||||
|
|
||||||
char *key = strchr(client->_httpRequestData.getParamsDataPointer, '=');
|
|
||||||
char *value = strchr(client->_httpRequestData.getParamsDataPointer, '&');
|
|
||||||
|
|
||||||
if(key == NULL && value == NULL) //Only the key is present
|
|
||||||
{
|
|
||||||
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(NULL));
|
|
||||||
*pGetParam = '\0';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if(key != NULL && value != NULL)
|
|
||||||
{
|
|
||||||
if(key < value)*key = '\0';
|
|
||||||
*value = '\0';
|
|
||||||
|
|
||||||
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(key > value ? NULL : key + 1));
|
|
||||||
memmove(client->_httpRequestData.getParamsDataPointer, value+1, strlen(value+1)+1);
|
|
||||||
|
|
||||||
#ifdef DEBUG_WEBS
|
|
||||||
Serial.print("Params pointer : ");Serial.println(client->_httpRequestData.getParamsDataPointer);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if(key != NULL && value == NULL) //Only one key/value pair present
|
|
||||||
{
|
|
||||||
*key = '\0';
|
|
||||||
|
|
||||||
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(key+1));
|
|
||||||
*pGetParam = '\0';
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else if(key == NULL && value != NULL)
|
|
||||||
{
|
|
||||||
*value = '\0';
|
|
||||||
|
|
||||||
client->_httpRequestData.getParams.add(client->_httpRequestData.getParamsDataPointer, new DictionaryHelper::StringEntity(NULL));
|
|
||||||
memmove(client->_httpRequestData.getParamsDataPointer, value+1, strlen(value+1)+1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //nothing to parse or done
|
|
||||||
{
|
{
|
||||||
|
client->_httpRequestData.getParams.add((char *)client->_data, new DictionaryHelper::StringEntity(NULL));
|
||||||
|
client->freeDataBuffer(strlen((char *)client->_data) + 1);
|
||||||
#ifdef DEBUG_WEBS
|
#ifdef DEBUG_WEBS
|
||||||
Serial.println("Nothing to parse or done");
|
Serial.printf("client->_data : #%s#\n", client->_data);
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else if(key != nullptr && value != nullptr)
|
||||||
|
{
|
||||||
|
if(key < value)*key = '\0';
|
||||||
|
*value = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add((char *)client->_data, new DictionaryHelper::StringEntity(key > value ? NULL : key + 1));
|
||||||
|
client->freeDataBuffer((value - (char *)client->_data) + 1);
|
||||||
|
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("client->_data : #%s#\n", client->_data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if(key != nullptr && value == nullptr) //Only one key/value pair present
|
||||||
|
{
|
||||||
|
*key = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add((char *)client->_data, new DictionaryHelper::StringEntity(key+1));
|
||||||
|
client->freeDataBuffer((key - (char *)client->_data) + strlen(key+1) + 2);
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("client->_data : #%s#\n", client->_data);
|
||||||
|
#endif
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if(key == nullptr && value != nullptr)
|
||||||
|
{
|
||||||
|
*value = '\0';
|
||||||
|
|
||||||
|
client->_httpRequestData.getParams.add((char *)client->_data, new DictionaryHelper::StringEntity(NULL));
|
||||||
|
client->freeDataBuffer((value - (char *)client->_data) + 1);
|
||||||
|
#ifdef DEBUG_WEBS
|
||||||
|
Serial.printf("client->_data : #%s#\n", client->_data);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -674,15 +701,18 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
case HTTP_CODE_BAD_REQUEST:
|
case HTTP_CODE_BAD_REQUEST:
|
||||||
strcpy_P(codeLiteral,PSTR("Bad Request"));
|
strcpy_P(codeLiteral,PSTR("Bad Request"));
|
||||||
break;
|
break;
|
||||||
case HTTP_CODE_NOT_FOUND:
|
|
||||||
strcpy_P(codeLiteral,PSTR("Not Found"));
|
|
||||||
break;
|
|
||||||
case HTTP_CODE_FORBIDDEN:
|
case HTTP_CODE_FORBIDDEN:
|
||||||
strcpy_P(codeLiteral,PSTR("Forbidden"));
|
strcpy_P(codeLiteral,PSTR("Forbidden"));
|
||||||
break;
|
break;
|
||||||
|
case HTTP_CODE_NOT_FOUND:
|
||||||
|
strcpy_P(codeLiteral,PSTR("Not Found"));
|
||||||
|
break;
|
||||||
case HTTP_CODE_METHOD_NOT_ALLOWED:
|
case HTTP_CODE_METHOD_NOT_ALLOWED:
|
||||||
strcpy_P(codeLiteral,PSTR("Method Not Allowed"));
|
strcpy_P(codeLiteral,PSTR("Method Not Allowed"));
|
||||||
break;
|
break;
|
||||||
|
case HTTP_CODE_URI_TOO_LONG:
|
||||||
|
strcpy_P(codeLiteral,PSTR("URI Too Long"));
|
||||||
|
break;
|
||||||
case HTTP_CODE_INTERNAL_SERVER_ERROR:
|
case HTTP_CODE_INTERNAL_SERVER_ERROR:
|
||||||
strcpy_P(codeLiteral,PSTR("Internal Server Error"));
|
strcpy_P(codeLiteral,PSTR("Internal Server Error"));
|
||||||
break;
|
break;
|
||||||
@ -745,8 +775,7 @@ class WEBServer : public TCPServer<T>, public HttpConstants
|
|||||||
|
|
||||||
static char *getFileExtension(char *name)
|
static char *getFileExtension(char *name)
|
||||||
{
|
{
|
||||||
char *p(lastIndexOf(name, '.'));
|
char *p(strrchr(name, '.'));
|
||||||
|
|
||||||
return p != NULL ? p+1 : NULL;
|
return p != NULL ? p+1 : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user