Morgan Du
/
http-webserver-example
Webserver example for Nuvoton NuMaker boards and mbed OS 5.15 - HTTP 1.1 and multi-threaded.
Embed:
(wiki syntax)
Show/hide line numbers
http_response_builder.h
00001 /* 00002 * PackageLicenseDeclared: Apache-2.0 00003 * Copyright (c) 2017 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 #ifndef _MBED_HTTP_RESPONSE_BUILDER_ 00019 #define _MBED_HTTP_RESPONSE_BUILDER_ 00020 00021 #include <string> 00022 #include <map> 00023 #include "http_parser.h" 00024 #include "http_parsed_url.h" 00025 00026 static const char* get_http_status_string(uint16_t status_code) { 00027 switch (status_code) { 00028 case 100: return "Continue"; 00029 case 101: return "Switching Protocols"; 00030 case 102: return "Processing"; 00031 case 200: return "OK"; 00032 case 201: return "Created"; 00033 case 202: return "Accepted"; 00034 case 203: return "Non-Authoritative Information"; 00035 case 204: return "No Content"; 00036 case 205: return "Reset Content"; 00037 case 206: return "Partial Content"; 00038 case 207: return "Multi-Status"; 00039 case 208: return "Already Reported"; 00040 case 226: return "IM Used"; 00041 case 300: return "Multiple Choices"; 00042 case 301: return "Moved Permanently"; 00043 case 302: return "Found"; 00044 case 303: return "See Other"; 00045 case 304: return "Not Modified"; 00046 case 305: return "Use Proxy"; 00047 case 307: return "Temporary Redirect"; 00048 case 308: return "Permanent Redirect"; 00049 case 400: return "Bad Request"; 00050 case 401: return "Unauthorized"; 00051 case 402: return "Payment Required"; 00052 case 403: return "Forbidden"; 00053 case 404: return "Not Found"; 00054 case 405: return "Method Not Allowed"; 00055 case 406: return "Not Acceptable"; 00056 case 407: return "Proxy Authentication Required"; 00057 case 408: return "Request Timeout"; 00058 case 409: return "Conflict"; 00059 case 410: return "Gone"; 00060 case 411: return "Length Required"; 00061 case 412: return "Precondition Failed"; 00062 case 413: return "Payload Too Large"; 00063 case 414: return "URI Too Long"; 00064 case 415: return "Unsupported Media Type"; 00065 case 416: return "Range Not Satisfiable"; 00066 case 417: return "Expectation Failed"; 00067 case 421: return "Misdirected Request"; 00068 case 422: return "Unprocessable Entity"; 00069 case 423: return "Locked"; 00070 case 424: return "Failed Dependency"; 00071 case 426: return "Upgrade Required"; 00072 case 428: return "Precondition Required"; 00073 case 429: return "Too Many Requests"; 00074 case 431: return "Request Header Fields Too Large"; 00075 case 451: return "Unavailable For Legal Reasons"; 00076 case 500: return "Internal Server Error"; 00077 case 501: return "Not Implemented"; 00078 case 502: return "Bad Gateway"; 00079 case 503: return "Service Unavailable"; 00080 case 504: return "Gateway Timeout"; 00081 case 505: return "HTTP Version Not Supported"; 00082 case 506: return "Variant Also Negotiates"; 00083 case 507: return "Insufficient Storage"; 00084 case 508: return "Loop Detected"; 00085 case 510: return "Not Extended"; 00086 case 511: return "Network Authentication Required"; 00087 default : return "Unknown"; 00088 } 00089 } 00090 00091 class HttpResponseBuilder { 00092 public: 00093 HttpResponseBuilder(uint16_t a_status_code) 00094 : status_code(a_status_code), status_message(get_http_status_string(a_status_code)) 00095 { 00096 } 00097 00098 /** 00099 * Set a header for the request 00100 * If the key already exists, it will be overwritten... 00101 */ 00102 void set_header(string key, string value) { 00103 map<string, string>::iterator it = headers.find(key); 00104 00105 if (it != headers.end()) { 00106 it->second = value; 00107 } 00108 else { 00109 headers.insert(headers.end(), pair<string, string>(key, value)); 00110 } 00111 } 00112 00113 char* build(const void* body, size_t body_size, size_t* size) { 00114 char buffer[10]; 00115 snprintf(buffer, sizeof(buffer), "%d", body_size); 00116 set_header("Content-Length", string(buffer)); 00117 00118 char status_code_buffer[5]; 00119 snprintf(status_code_buffer, sizeof(status_code_buffer), "%d", status_code /* max 5 digits */); 00120 00121 *size = 0; 00122 00123 // first line is HTTP/1.1 200 OK\r\n 00124 *size += 8 + 1 + strlen(status_code_buffer) + 1 + strlen(status_message) + 2; 00125 00126 // after that we'll do the headers 00127 typedef map<string, string>::iterator it_type; 00128 for(it_type it = headers.begin(); it != headers.end(); it++) { 00129 // line is KEY: VALUE\r\n 00130 *size += it->first.length() + 1 + 1 + it->second.length() + 2; 00131 } 00132 00133 // then the body, first an extra newline 00134 *size += 2; 00135 00136 // body 00137 *size += body_size; 00138 00139 // Now let's print it 00140 char* res = (char*)calloc(*size + 1, 1); 00141 char* originalRes = res; 00142 00143 res += sprintf(res, "HTTP/1.1 %s %s\r\n", status_code_buffer, status_message); 00144 00145 typedef map<string, string>::iterator it_type; 00146 for(it_type it = headers.begin(); it != headers.end(); it++) { 00147 // line is KEY: VALUE\r\n 00148 res += sprintf(res, "%s: %s\r\n", it->first.c_str(), it->second.c_str()); 00149 } 00150 00151 res += sprintf(res, "\r\n"); 00152 00153 if (body_size > 0) { 00154 memcpy(res, body, body_size); 00155 } 00156 res += body_size; 00157 00158 // Uncomment to debug... 00159 // printf("----- BEGIN RESPONSE -----\n"); 00160 // printf("%s", originalRes); 00161 // printf("----- END RESPONSE -----\n"); 00162 00163 return originalRes; 00164 } 00165 00166 nsapi_error_t send(TCPSocket* socket, const void* body, size_t body_size) { 00167 if (!socket) return NSAPI_ERROR_NO_SOCKET; 00168 00169 size_t res_size; 00170 char* response = build(body, body_size, &res_size); 00171 00172 nsapi_error_t r = socket->send(response, res_size); 00173 00174 free(response); 00175 00176 return r; 00177 } 00178 00179 private: 00180 uint16_t status_code; 00181 const char* status_message; 00182 map<string, string> headers; 00183 }; 00184 00185 #endif // _MBED_HTTP_RESPONSE_BUILDER_
Generated on Tue Jul 19 2022 01:00:46 by 1.7.2