Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
tcp/http/httprequest.c@61:aad055f1b0d1, 2018-01-11 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Jan 11 17:38:21 2018 +0000
- Revision:
- 61:aad055f1b0d1
- Parent:
- tcp/http/httprequest.cpp@54:84ef2b29cf7e
- Child:
- 110:67c96c143c2a
Removed dependence on Mbed OS
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| andrewboyson | 61:aad055f1b0d1 | 1 | #include <stdbool.h> |
| andrewboyson | 61:aad055f1b0d1 | 2 | #include <stdio.h> |
| andrewboyson | 61:aad055f1b0d1 | 3 | #include <string.h> |
| andrewboyson | 54:84ef2b29cf7e | 4 | |
| andrewboyson | 54:84ef2b29cf7e | 5 | char* HttpGetNextLine(char* p, char* pE) //Terminates this line and returns the start of the next line or NULL if none |
| andrewboyson | 54:84ef2b29cf7e | 6 | { |
| andrewboyson | 54:84ef2b29cf7e | 7 | while (true) |
| andrewboyson | 54:84ef2b29cf7e | 8 | { |
| andrewboyson | 54:84ef2b29cf7e | 9 | if (p == pE) //There are no more lines |
| andrewboyson | 54:84ef2b29cf7e | 10 | { |
| andrewboyson | 54:84ef2b29cf7e | 11 | *p = 0; //terminate the line |
| andrewboyson | 54:84ef2b29cf7e | 12 | return NULL; |
| andrewboyson | 54:84ef2b29cf7e | 13 | } |
| andrewboyson | 54:84ef2b29cf7e | 14 | if (*p == 0) return NULL;//There are no more lines |
| andrewboyson | 54:84ef2b29cf7e | 15 | if (*p == '\n') |
| andrewboyson | 54:84ef2b29cf7e | 16 | { |
| andrewboyson | 54:84ef2b29cf7e | 17 | *p = 0; //make the line a c string |
| andrewboyson | 54:84ef2b29cf7e | 18 | return p + 1; //return the start of the next line |
| andrewboyson | 54:84ef2b29cf7e | 19 | } |
| andrewboyson | 54:84ef2b29cf7e | 20 | if (*p < ' ') *p = 0; //terminate the line at any invalid characters |
| andrewboyson | 54:84ef2b29cf7e | 21 | if (*p >= 0x7f) *p = 0; //terminate the line at any invalid characters |
| andrewboyson | 54:84ef2b29cf7e | 22 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 23 | } |
| andrewboyson | 54:84ef2b29cf7e | 24 | } |
| andrewboyson | 54:84ef2b29cf7e | 25 | |
| andrewboyson | 54:84ef2b29cf7e | 26 | void HttpSplitRequest(char* p, char** ppMethod, char** ppPath, char** ppQuery) |
| andrewboyson | 54:84ef2b29cf7e | 27 | { |
| andrewboyson | 54:84ef2b29cf7e | 28 | *ppMethod = NULL; |
| andrewboyson | 54:84ef2b29cf7e | 29 | *ppPath = NULL; |
| andrewboyson | 54:84ef2b29cf7e | 30 | *ppQuery = NULL; |
| andrewboyson | 54:84ef2b29cf7e | 31 | |
| andrewboyson | 54:84ef2b29cf7e | 32 | while (*p == ' ') //Move past any leading spaces |
| andrewboyson | 54:84ef2b29cf7e | 33 | { |
| andrewboyson | 54:84ef2b29cf7e | 34 | if (*p == 0) return; |
| andrewboyson | 54:84ef2b29cf7e | 35 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 36 | } |
| andrewboyson | 54:84ef2b29cf7e | 37 | *ppMethod = p; //Record the start of the method (GET or POST) |
| andrewboyson | 54:84ef2b29cf7e | 38 | |
| andrewboyson | 54:84ef2b29cf7e | 39 | while (*p != ' ') //Move past the method |
| andrewboyson | 54:84ef2b29cf7e | 40 | { |
| andrewboyson | 54:84ef2b29cf7e | 41 | if (*p == 0) return; |
| andrewboyson | 54:84ef2b29cf7e | 42 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 43 | } |
| andrewboyson | 54:84ef2b29cf7e | 44 | *p = 0; //Terminate the method |
| andrewboyson | 54:84ef2b29cf7e | 45 | p++; //Start at next character |
| andrewboyson | 54:84ef2b29cf7e | 46 | |
| andrewboyson | 54:84ef2b29cf7e | 47 | while (*p == ' ') //Move past any spaces |
| andrewboyson | 54:84ef2b29cf7e | 48 | { |
| andrewboyson | 54:84ef2b29cf7e | 49 | if (*p == 0) return; |
| andrewboyson | 54:84ef2b29cf7e | 50 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 51 | } |
| andrewboyson | 54:84ef2b29cf7e | 52 | *ppPath = p; //Record the start of the path |
| andrewboyson | 54:84ef2b29cf7e | 53 | |
| andrewboyson | 54:84ef2b29cf7e | 54 | while (*p != ' ') //Move past the path and query |
| andrewboyson | 54:84ef2b29cf7e | 55 | { |
| andrewboyson | 54:84ef2b29cf7e | 56 | if (*p == 0) return; |
| andrewboyson | 54:84ef2b29cf7e | 57 | if (*p == '?') |
| andrewboyson | 54:84ef2b29cf7e | 58 | { |
| andrewboyson | 54:84ef2b29cf7e | 59 | *p = 0; //Terminate the path |
| andrewboyson | 54:84ef2b29cf7e | 60 | *ppQuery = p + 1; //Record the start of the query |
| andrewboyson | 54:84ef2b29cf7e | 61 | } |
| andrewboyson | 54:84ef2b29cf7e | 62 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 63 | } |
| andrewboyson | 54:84ef2b29cf7e | 64 | *p = 0; //Terminate the path or query |
| andrewboyson | 54:84ef2b29cf7e | 65 | } |
| andrewboyson | 54:84ef2b29cf7e | 66 | void HttpSplitHeader(char* p, char** ppName, char** ppValue) |
| andrewboyson | 54:84ef2b29cf7e | 67 | { |
| andrewboyson | 54:84ef2b29cf7e | 68 | *ppName = p; //Record the start of the name |
| andrewboyson | 54:84ef2b29cf7e | 69 | *ppValue = NULL; |
| andrewboyson | 54:84ef2b29cf7e | 70 | |
| andrewboyson | 54:84ef2b29cf7e | 71 | while (*p != ':') //Loop to an ':' |
| andrewboyson | 54:84ef2b29cf7e | 72 | { |
| andrewboyson | 54:84ef2b29cf7e | 73 | if (!*p) return; |
| andrewboyson | 54:84ef2b29cf7e | 74 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 75 | } |
| andrewboyson | 54:84ef2b29cf7e | 76 | *p = 0; //Terminate the name by replacing the ':' with a NUL char |
| andrewboyson | 54:84ef2b29cf7e | 77 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 78 | while (*p == ' ') //Move past any spaces |
| andrewboyson | 54:84ef2b29cf7e | 79 | { |
| andrewboyson | 54:84ef2b29cf7e | 80 | if (*p == 0) return; |
| andrewboyson | 54:84ef2b29cf7e | 81 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 82 | } |
| andrewboyson | 54:84ef2b29cf7e | 83 | *ppValue = p; //Record the start of the value |
| andrewboyson | 54:84ef2b29cf7e | 84 | } |
| andrewboyson | 54:84ef2b29cf7e | 85 | |
| andrewboyson | 54:84ef2b29cf7e | 86 | char* HttpSplitQuery(char* p, char** ppName, char** ppValue) //returns the start of the next name value pair |
| andrewboyson | 54:84ef2b29cf7e | 87 | { |
| andrewboyson | 54:84ef2b29cf7e | 88 | *ppName = p; //Record the start of the name |
| andrewboyson | 54:84ef2b29cf7e | 89 | *ppValue = NULL; |
| andrewboyson | 54:84ef2b29cf7e | 90 | |
| andrewboyson | 54:84ef2b29cf7e | 91 | while (*p != '=') //Loop to an '=' |
| andrewboyson | 54:84ef2b29cf7e | 92 | { |
| andrewboyson | 54:84ef2b29cf7e | 93 | if (*p == 0) return 0; |
| andrewboyson | 54:84ef2b29cf7e | 94 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 95 | } |
| andrewboyson | 54:84ef2b29cf7e | 96 | *p = 0; //Terminate the name by replacing the '=' with a NUL char |
| andrewboyson | 54:84ef2b29cf7e | 97 | p++; //Move on to the start of the value |
| andrewboyson | 54:84ef2b29cf7e | 98 | *ppValue = p; //Record the start of the value |
| andrewboyson | 54:84ef2b29cf7e | 99 | while (*p != '&') //Loop to a '&' |
| andrewboyson | 54:84ef2b29cf7e | 100 | { |
| andrewboyson | 54:84ef2b29cf7e | 101 | if (*p == 0) return 0; |
| andrewboyson | 54:84ef2b29cf7e | 102 | p++; |
| andrewboyson | 54:84ef2b29cf7e | 103 | } |
| andrewboyson | 54:84ef2b29cf7e | 104 | *p = 0; //Terminate the value by replacing the '&' with a NULL |
| andrewboyson | 54:84ef2b29cf7e | 105 | return p + 1; |
| andrewboyson | 54:84ef2b29cf7e | 106 | } |
| andrewboyson | 54:84ef2b29cf7e | 107 | static int hexToInt(char c) |
| andrewboyson | 54:84ef2b29cf7e | 108 | { |
| andrewboyson | 54:84ef2b29cf7e | 109 | int nibble; |
| andrewboyson | 54:84ef2b29cf7e | 110 | if (c >= '0' && c <= '9') nibble = c - '0'; |
| andrewboyson | 54:84ef2b29cf7e | 111 | if (c >= 'A' && c <= 'F') nibble = c - 'A' + 0xA; |
| andrewboyson | 54:84ef2b29cf7e | 112 | if (c >= 'a' && c <= 'f') nibble = c - 'a' + 0xA; |
| andrewboyson | 54:84ef2b29cf7e | 113 | return nibble; |
| andrewboyson | 54:84ef2b29cf7e | 114 | } |
| andrewboyson | 54:84ef2b29cf7e | 115 | void HttpDecodeValue(char* value) |
| andrewboyson | 54:84ef2b29cf7e | 116 | { |
| andrewboyson | 54:84ef2b29cf7e | 117 | char* pDst = value; |
| andrewboyson | 61:aad055f1b0d1 | 118 | int a; |
| andrewboyson | 54:84ef2b29cf7e | 119 | for (char* pSrc = value; *pSrc; pSrc++) |
| andrewboyson | 54:84ef2b29cf7e | 120 | { |
| andrewboyson | 54:84ef2b29cf7e | 121 | char c = *pSrc; |
| andrewboyson | 54:84ef2b29cf7e | 122 | switch (c) |
| andrewboyson | 54:84ef2b29cf7e | 123 | { |
| andrewboyson | 54:84ef2b29cf7e | 124 | case '+': |
| andrewboyson | 54:84ef2b29cf7e | 125 | c = ' '; |
| andrewboyson | 54:84ef2b29cf7e | 126 | break; |
| andrewboyson | 54:84ef2b29cf7e | 127 | case '%': |
| andrewboyson | 54:84ef2b29cf7e | 128 | c = *++pSrc; |
| andrewboyson | 54:84ef2b29cf7e | 129 | if (c == 0) break; |
| andrewboyson | 54:84ef2b29cf7e | 130 | a = hexToInt(c); |
| andrewboyson | 54:84ef2b29cf7e | 131 | a <<= 4; |
| andrewboyson | 54:84ef2b29cf7e | 132 | c = *++pSrc; |
| andrewboyson | 54:84ef2b29cf7e | 133 | if (c == 0) break; |
| andrewboyson | 54:84ef2b29cf7e | 134 | a += hexToInt(c); |
| andrewboyson | 54:84ef2b29cf7e | 135 | c = a; |
| andrewboyson | 54:84ef2b29cf7e | 136 | break; |
| andrewboyson | 54:84ef2b29cf7e | 137 | default: |
| andrewboyson | 54:84ef2b29cf7e | 138 | c = *pSrc; |
| andrewboyson | 54:84ef2b29cf7e | 139 | break; |
| andrewboyson | 54:84ef2b29cf7e | 140 | } |
| andrewboyson | 54:84ef2b29cf7e | 141 | *pDst++ = c; |
| andrewboyson | 54:84ef2b29cf7e | 142 | } |
| andrewboyson | 54:84ef2b29cf7e | 143 | *pDst = 0; |
| andrewboyson | 54:84ef2b29cf7e | 144 | } |
| andrewboyson | 54:84ef2b29cf7e | 145 | |
| andrewboyson | 54:84ef2b29cf7e | 146 | void HttpReadRequest(char *pData, int len, char** ppMethod, char** ppPath, char** ppQuery, char** ppLastModified) |
| andrewboyson | 54:84ef2b29cf7e | 147 | { |
| andrewboyson | 54:84ef2b29cf7e | 148 | char* pEnd = pData + len; |
| andrewboyson | 54:84ef2b29cf7e | 149 | char* pThis = pData; |
| andrewboyson | 54:84ef2b29cf7e | 150 | char* pNext = HttpGetNextLine(pThis, pEnd); |
| andrewboyson | 54:84ef2b29cf7e | 151 | HttpSplitRequest(pThis, ppMethod, ppPath, ppQuery); |
| andrewboyson | 54:84ef2b29cf7e | 152 | |
| andrewboyson | 54:84ef2b29cf7e | 153 | while(pNext) |
| andrewboyson | 54:84ef2b29cf7e | 154 | { |
| andrewboyson | 54:84ef2b29cf7e | 155 | pThis = pNext; |
| andrewboyson | 54:84ef2b29cf7e | 156 | pNext = HttpGetNextLine(pThis, pEnd); |
| andrewboyson | 54:84ef2b29cf7e | 157 | if (*pThis == 0) break; //This line is empty ie no more headers |
| andrewboyson | 54:84ef2b29cf7e | 158 | char* pName; |
| andrewboyson | 54:84ef2b29cf7e | 159 | char* pValue; |
| andrewboyson | 54:84ef2b29cf7e | 160 | HttpSplitHeader(pThis, &pName, &pValue); |
| andrewboyson | 54:84ef2b29cf7e | 161 | if (strcmp(pName, "If-Modified-Since") == 0) *ppLastModified = pValue; |
| andrewboyson | 54:84ef2b29cf7e | 162 | } |
| andrewboyson | 54:84ef2b29cf7e | 163 | } |