Hiroaki Okoshi / Mbed OS http-webserver-example-mbed-os-5-odin-w2
Committer:
Hiroaki_Okoshi
Date:
Sat Oct 09 14:23:23 2021 +0000
Revision:
0:a21b8a29df03
Sample web server via WiFi program. for mbed os 5.15

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Hiroaki_Okoshi 0:a21b8a29df03 1 /*
Hiroaki_Okoshi 0:a21b8a29df03 2 * PackageLicenseDeclared: Apache-2.0
Hiroaki_Okoshi 0:a21b8a29df03 3 * Copyright (c) 2017 ARM Limited
Hiroaki_Okoshi 0:a21b8a29df03 4 *
Hiroaki_Okoshi 0:a21b8a29df03 5 * Licensed under the Apache License, Version 2.0 (the "License");
Hiroaki_Okoshi 0:a21b8a29df03 6 * you may not use this file except in compliance with the License.
Hiroaki_Okoshi 0:a21b8a29df03 7 * You may obtain a copy of the License at
Hiroaki_Okoshi 0:a21b8a29df03 8 *
Hiroaki_Okoshi 0:a21b8a29df03 9 * http://www.apache.org/licenses/LICENSE-2.0
Hiroaki_Okoshi 0:a21b8a29df03 10 *
Hiroaki_Okoshi 0:a21b8a29df03 11 * Unless required by applicable law or agreed to in writing, software
Hiroaki_Okoshi 0:a21b8a29df03 12 * distributed under the License is distributed on an "AS IS" BASIS,
Hiroaki_Okoshi 0:a21b8a29df03 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Hiroaki_Okoshi 0:a21b8a29df03 14 * See the License for the specific language governing permissions and
Hiroaki_Okoshi 0:a21b8a29df03 15 * limitations under the License.
Hiroaki_Okoshi 0:a21b8a29df03 16 */
Hiroaki_Okoshi 0:a21b8a29df03 17
Hiroaki_Okoshi 0:a21b8a29df03 18 #ifndef _MBED_HTTP_HTTP_RESPONSE
Hiroaki_Okoshi 0:a21b8a29df03 19 #define _MBED_HTTP_HTTP_RESPONSE
Hiroaki_Okoshi 0:a21b8a29df03 20 #include <string>
Hiroaki_Okoshi 0:a21b8a29df03 21 #include <vector>
Hiroaki_Okoshi 0:a21b8a29df03 22 #include "http_parser.h"
Hiroaki_Okoshi 0:a21b8a29df03 23
Hiroaki_Okoshi 0:a21b8a29df03 24 using namespace std;
Hiroaki_Okoshi 0:a21b8a29df03 25
Hiroaki_Okoshi 0:a21b8a29df03 26 class HttpResponse {
Hiroaki_Okoshi 0:a21b8a29df03 27 public:
Hiroaki_Okoshi 0:a21b8a29df03 28 HttpResponse() {
Hiroaki_Okoshi 0:a21b8a29df03 29 status_code = 0;
Hiroaki_Okoshi 0:a21b8a29df03 30 concat_header_field = false;
Hiroaki_Okoshi 0:a21b8a29df03 31 concat_header_value = false;
Hiroaki_Okoshi 0:a21b8a29df03 32 expected_content_length = 0;
Hiroaki_Okoshi 0:a21b8a29df03 33 is_chunked = false;
Hiroaki_Okoshi 0:a21b8a29df03 34 is_message_completed = false;
Hiroaki_Okoshi 0:a21b8a29df03 35 body_length = 0;
Hiroaki_Okoshi 0:a21b8a29df03 36 body_offset = 0;
Hiroaki_Okoshi 0:a21b8a29df03 37 body = NULL;
Hiroaki_Okoshi 0:a21b8a29df03 38 }
Hiroaki_Okoshi 0:a21b8a29df03 39
Hiroaki_Okoshi 0:a21b8a29df03 40 ~HttpResponse() {
Hiroaki_Okoshi 0:a21b8a29df03 41 if (body != NULL) {
Hiroaki_Okoshi 0:a21b8a29df03 42 free(body);
Hiroaki_Okoshi 0:a21b8a29df03 43 }
Hiroaki_Okoshi 0:a21b8a29df03 44
Hiroaki_Okoshi 0:a21b8a29df03 45 for (size_t ix = 0; ix < header_fields.size(); ix++) {
Hiroaki_Okoshi 0:a21b8a29df03 46 delete header_fields[ix];
Hiroaki_Okoshi 0:a21b8a29df03 47 delete header_values[ix];
Hiroaki_Okoshi 0:a21b8a29df03 48 }
Hiroaki_Okoshi 0:a21b8a29df03 49 }
Hiroaki_Okoshi 0:a21b8a29df03 50
Hiroaki_Okoshi 0:a21b8a29df03 51 void set_status(int a_status_code, string a_status_message) {
Hiroaki_Okoshi 0:a21b8a29df03 52 status_code = a_status_code;
Hiroaki_Okoshi 0:a21b8a29df03 53 status_message = a_status_message;
Hiroaki_Okoshi 0:a21b8a29df03 54 }
Hiroaki_Okoshi 0:a21b8a29df03 55
Hiroaki_Okoshi 0:a21b8a29df03 56 int get_status_code() {
Hiroaki_Okoshi 0:a21b8a29df03 57 return status_code;
Hiroaki_Okoshi 0:a21b8a29df03 58 }
Hiroaki_Okoshi 0:a21b8a29df03 59
Hiroaki_Okoshi 0:a21b8a29df03 60 string get_status_message() {
Hiroaki_Okoshi 0:a21b8a29df03 61 return status_message;
Hiroaki_Okoshi 0:a21b8a29df03 62 }
Hiroaki_Okoshi 0:a21b8a29df03 63
Hiroaki_Okoshi 0:a21b8a29df03 64 void set_url(string a_url) {
Hiroaki_Okoshi 0:a21b8a29df03 65 url = a_url;
Hiroaki_Okoshi 0:a21b8a29df03 66 }
Hiroaki_Okoshi 0:a21b8a29df03 67
Hiroaki_Okoshi 0:a21b8a29df03 68 string get_url() {
Hiroaki_Okoshi 0:a21b8a29df03 69 return url;
Hiroaki_Okoshi 0:a21b8a29df03 70 }
Hiroaki_Okoshi 0:a21b8a29df03 71
Hiroaki_Okoshi 0:a21b8a29df03 72 void set_method(http_method a_method) {
Hiroaki_Okoshi 0:a21b8a29df03 73 method = a_method;
Hiroaki_Okoshi 0:a21b8a29df03 74 }
Hiroaki_Okoshi 0:a21b8a29df03 75
Hiroaki_Okoshi 0:a21b8a29df03 76 http_method get_method() {
Hiroaki_Okoshi 0:a21b8a29df03 77 return method;
Hiroaki_Okoshi 0:a21b8a29df03 78 }
Hiroaki_Okoshi 0:a21b8a29df03 79
Hiroaki_Okoshi 0:a21b8a29df03 80 void set_header_field(string field) {
Hiroaki_Okoshi 0:a21b8a29df03 81 concat_header_value = false;
Hiroaki_Okoshi 0:a21b8a29df03 82
Hiroaki_Okoshi 0:a21b8a29df03 83 // headers can be chunked
Hiroaki_Okoshi 0:a21b8a29df03 84 if (concat_header_field) {
Hiroaki_Okoshi 0:a21b8a29df03 85 *header_fields[header_fields.size() - 1] = (*header_fields[header_fields.size() - 1]) + field;
Hiroaki_Okoshi 0:a21b8a29df03 86 }
Hiroaki_Okoshi 0:a21b8a29df03 87 else {
Hiroaki_Okoshi 0:a21b8a29df03 88 header_fields.push_back(new string(field));
Hiroaki_Okoshi 0:a21b8a29df03 89 }
Hiroaki_Okoshi 0:a21b8a29df03 90
Hiroaki_Okoshi 0:a21b8a29df03 91 concat_header_field = true;
Hiroaki_Okoshi 0:a21b8a29df03 92 }
Hiroaki_Okoshi 0:a21b8a29df03 93
Hiroaki_Okoshi 0:a21b8a29df03 94 void set_header_value(string value) {
Hiroaki_Okoshi 0:a21b8a29df03 95 concat_header_field = false;
Hiroaki_Okoshi 0:a21b8a29df03 96
Hiroaki_Okoshi 0:a21b8a29df03 97 // headers can be chunked
Hiroaki_Okoshi 0:a21b8a29df03 98 if (concat_header_value) {
Hiroaki_Okoshi 0:a21b8a29df03 99 *header_values[header_values.size() - 1] = (*header_values[header_values.size() - 1]) + value;
Hiroaki_Okoshi 0:a21b8a29df03 100 }
Hiroaki_Okoshi 0:a21b8a29df03 101 else {
Hiroaki_Okoshi 0:a21b8a29df03 102 header_values.push_back(new string(value));
Hiroaki_Okoshi 0:a21b8a29df03 103 }
Hiroaki_Okoshi 0:a21b8a29df03 104
Hiroaki_Okoshi 0:a21b8a29df03 105 concat_header_value = true;
Hiroaki_Okoshi 0:a21b8a29df03 106 }
Hiroaki_Okoshi 0:a21b8a29df03 107
Hiroaki_Okoshi 0:a21b8a29df03 108 void set_headers_complete() {
Hiroaki_Okoshi 0:a21b8a29df03 109 for (size_t ix = 0; ix < header_fields.size(); ix++) {
Hiroaki_Okoshi 0:a21b8a29df03 110 if (strcicmp(header_fields[ix]->c_str(), "content-length") == 0) {
Hiroaki_Okoshi 0:a21b8a29df03 111 expected_content_length = (size_t)atoi(header_values[ix]->c_str());
Hiroaki_Okoshi 0:a21b8a29df03 112 break;
Hiroaki_Okoshi 0:a21b8a29df03 113 }
Hiroaki_Okoshi 0:a21b8a29df03 114 }
Hiroaki_Okoshi 0:a21b8a29df03 115 }
Hiroaki_Okoshi 0:a21b8a29df03 116
Hiroaki_Okoshi 0:a21b8a29df03 117 size_t get_headers_length() {
Hiroaki_Okoshi 0:a21b8a29df03 118 return header_fields.size();
Hiroaki_Okoshi 0:a21b8a29df03 119 }
Hiroaki_Okoshi 0:a21b8a29df03 120
Hiroaki_Okoshi 0:a21b8a29df03 121 vector<string*> get_headers_fields() {
Hiroaki_Okoshi 0:a21b8a29df03 122 return header_fields;
Hiroaki_Okoshi 0:a21b8a29df03 123 }
Hiroaki_Okoshi 0:a21b8a29df03 124
Hiroaki_Okoshi 0:a21b8a29df03 125 vector<string*> get_headers_values() {
Hiroaki_Okoshi 0:a21b8a29df03 126 return header_values;
Hiroaki_Okoshi 0:a21b8a29df03 127 }
Hiroaki_Okoshi 0:a21b8a29df03 128
Hiroaki_Okoshi 0:a21b8a29df03 129 void set_body(const char *at, size_t length) {
Hiroaki_Okoshi 0:a21b8a29df03 130 // Connection: close, could not specify Content-Length, nor chunked... So do it like this:
Hiroaki_Okoshi 0:a21b8a29df03 131 if (expected_content_length == 0 && length > 0) {
Hiroaki_Okoshi 0:a21b8a29df03 132 is_chunked = true;
Hiroaki_Okoshi 0:a21b8a29df03 133 }
Hiroaki_Okoshi 0:a21b8a29df03 134
Hiroaki_Okoshi 0:a21b8a29df03 135 // only malloc when this fn is called, so we don't alloc when body callback's are enabled
Hiroaki_Okoshi 0:a21b8a29df03 136 if (body == NULL && !is_chunked) {
Hiroaki_Okoshi 0:a21b8a29df03 137 body = (char*)malloc(expected_content_length);
Hiroaki_Okoshi 0:a21b8a29df03 138 }
Hiroaki_Okoshi 0:a21b8a29df03 139
Hiroaki_Okoshi 0:a21b8a29df03 140 if (is_chunked) {
Hiroaki_Okoshi 0:a21b8a29df03 141 if (body == NULL) {
Hiroaki_Okoshi 0:a21b8a29df03 142 body = (char*)malloc(length);
Hiroaki_Okoshi 0:a21b8a29df03 143 }
Hiroaki_Okoshi 0:a21b8a29df03 144 else {
Hiroaki_Okoshi 0:a21b8a29df03 145 body = (char*)realloc(body, body_offset + length);
Hiroaki_Okoshi 0:a21b8a29df03 146 }
Hiroaki_Okoshi 0:a21b8a29df03 147 }
Hiroaki_Okoshi 0:a21b8a29df03 148
Hiroaki_Okoshi 0:a21b8a29df03 149 memcpy(body + body_offset, at, length);
Hiroaki_Okoshi 0:a21b8a29df03 150
Hiroaki_Okoshi 0:a21b8a29df03 151 body_offset += length;
Hiroaki_Okoshi 0:a21b8a29df03 152 }
Hiroaki_Okoshi 0:a21b8a29df03 153
Hiroaki_Okoshi 0:a21b8a29df03 154 void* get_body() {
Hiroaki_Okoshi 0:a21b8a29df03 155 return (void*)body;
Hiroaki_Okoshi 0:a21b8a29df03 156 }
Hiroaki_Okoshi 0:a21b8a29df03 157
Hiroaki_Okoshi 0:a21b8a29df03 158 string get_body_as_string() {
Hiroaki_Okoshi 0:a21b8a29df03 159 string s(body, body_offset);
Hiroaki_Okoshi 0:a21b8a29df03 160 return s;
Hiroaki_Okoshi 0:a21b8a29df03 161 }
Hiroaki_Okoshi 0:a21b8a29df03 162
Hiroaki_Okoshi 0:a21b8a29df03 163 void increase_body_length(size_t length) {
Hiroaki_Okoshi 0:a21b8a29df03 164 body_length += length;
Hiroaki_Okoshi 0:a21b8a29df03 165 }
Hiroaki_Okoshi 0:a21b8a29df03 166
Hiroaki_Okoshi 0:a21b8a29df03 167 size_t get_body_length() {
Hiroaki_Okoshi 0:a21b8a29df03 168 return body_offset;
Hiroaki_Okoshi 0:a21b8a29df03 169 }
Hiroaki_Okoshi 0:a21b8a29df03 170
Hiroaki_Okoshi 0:a21b8a29df03 171 bool is_message_complete() {
Hiroaki_Okoshi 0:a21b8a29df03 172 return is_message_completed;
Hiroaki_Okoshi 0:a21b8a29df03 173 }
Hiroaki_Okoshi 0:a21b8a29df03 174
Hiroaki_Okoshi 0:a21b8a29df03 175 void set_chunked() {
Hiroaki_Okoshi 0:a21b8a29df03 176 is_chunked = true;
Hiroaki_Okoshi 0:a21b8a29df03 177 }
Hiroaki_Okoshi 0:a21b8a29df03 178
Hiroaki_Okoshi 0:a21b8a29df03 179 void set_message_complete() {
Hiroaki_Okoshi 0:a21b8a29df03 180 is_message_completed = true;
Hiroaki_Okoshi 0:a21b8a29df03 181 }
Hiroaki_Okoshi 0:a21b8a29df03 182
Hiroaki_Okoshi 0:a21b8a29df03 183 private:
Hiroaki_Okoshi 0:a21b8a29df03 184 // from http://stackoverflow.com/questions/5820810/case-insensitive-string-comp-in-c
Hiroaki_Okoshi 0:a21b8a29df03 185 int strcicmp(char const *a, char const *b) {
Hiroaki_Okoshi 0:a21b8a29df03 186 for (;; a++, b++) {
Hiroaki_Okoshi 0:a21b8a29df03 187 int d = tolower(*a) - tolower(*b);
Hiroaki_Okoshi 0:a21b8a29df03 188 if (d != 0 || !*a) {
Hiroaki_Okoshi 0:a21b8a29df03 189 return d;
Hiroaki_Okoshi 0:a21b8a29df03 190 }
Hiroaki_Okoshi 0:a21b8a29df03 191 }
Hiroaki_Okoshi 0:a21b8a29df03 192 }
Hiroaki_Okoshi 0:a21b8a29df03 193
Hiroaki_Okoshi 0:a21b8a29df03 194 char tolower(char c) {
Hiroaki_Okoshi 0:a21b8a29df03 195 if(('A' <= c) && (c <= 'Z')) {
Hiroaki_Okoshi 0:a21b8a29df03 196 return 'a' + (c - 'A');
Hiroaki_Okoshi 0:a21b8a29df03 197 }
Hiroaki_Okoshi 0:a21b8a29df03 198
Hiroaki_Okoshi 0:a21b8a29df03 199 return c;
Hiroaki_Okoshi 0:a21b8a29df03 200 }
Hiroaki_Okoshi 0:a21b8a29df03 201
Hiroaki_Okoshi 0:a21b8a29df03 202 int status_code;
Hiroaki_Okoshi 0:a21b8a29df03 203 string status_message;
Hiroaki_Okoshi 0:a21b8a29df03 204 string url;
Hiroaki_Okoshi 0:a21b8a29df03 205 http_method method;
Hiroaki_Okoshi 0:a21b8a29df03 206
Hiroaki_Okoshi 0:a21b8a29df03 207 vector<string*> header_fields;
Hiroaki_Okoshi 0:a21b8a29df03 208 vector<string*> header_values;
Hiroaki_Okoshi 0:a21b8a29df03 209
Hiroaki_Okoshi 0:a21b8a29df03 210 bool concat_header_field;
Hiroaki_Okoshi 0:a21b8a29df03 211 bool concat_header_value;
Hiroaki_Okoshi 0:a21b8a29df03 212
Hiroaki_Okoshi 0:a21b8a29df03 213 size_t expected_content_length;
Hiroaki_Okoshi 0:a21b8a29df03 214
Hiroaki_Okoshi 0:a21b8a29df03 215 bool is_chunked;
Hiroaki_Okoshi 0:a21b8a29df03 216
Hiroaki_Okoshi 0:a21b8a29df03 217 bool is_message_completed;
Hiroaki_Okoshi 0:a21b8a29df03 218
Hiroaki_Okoshi 0:a21b8a29df03 219 char * body;
Hiroaki_Okoshi 0:a21b8a29df03 220 size_t body_length;
Hiroaki_Okoshi 0:a21b8a29df03 221 size_t body_offset;
Hiroaki_Okoshi 0:a21b8a29df03 222 };
Hiroaki_Okoshi 0:a21b8a29df03 223
Hiroaki_Okoshi 0:a21b8a29df03 224 #endif