Library for Firebase, PUT, PATCH, POST, GET, DELETE operations supported, (others are available, todo). Based on Mbed's https-example. Tested on STM32F767 using ETHERNET and ESP8266 WIFI interfaces and STM32F446 using ESP8266 WIFI interface.

Dependents:   Firebase-Example

Committer:
star297
Date:
Thu Jan 23 22:18:11 2020 +0000
Revision:
0:768ae9838086
Initial version.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
star297 0:768ae9838086 1 /*
star297 0:768ae9838086 2 * PackageLicenseDeclared: Apache-2.0
star297 0:768ae9838086 3 * Copyright (c) 2017 ARM Limited
star297 0:768ae9838086 4 *
star297 0:768ae9838086 5 * Licensed under the Apache License, Version 2.0 (the "License");
star297 0:768ae9838086 6 * you may not use this file except in compliance with the License.
star297 0:768ae9838086 7 * You may obtain a copy of the License at
star297 0:768ae9838086 8 *
star297 0:768ae9838086 9 * http://www.apache.org/licenses/LICENSE-2.0
star297 0:768ae9838086 10 *
star297 0:768ae9838086 11 * Unless required by applicable law or agreed to in writing, software
star297 0:768ae9838086 12 * distributed under the License is distributed on an "AS IS" BASIS,
star297 0:768ae9838086 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
star297 0:768ae9838086 14 * See the License for the specific language governing permissions and
star297 0:768ae9838086 15 * limitations under the License.
star297 0:768ae9838086 16 */
star297 0:768ae9838086 17
star297 0:768ae9838086 18 #ifndef _MBED_HTTP_REQUEST_BUILDER_H_
star297 0:768ae9838086 19 #define _MBED_HTTP_REQUEST_BUILDER_H_
star297 0:768ae9838086 20
star297 0:768ae9838086 21 #include <string>
star297 0:768ae9838086 22 #include <map>
star297 0:768ae9838086 23 #include "http_parser.h"
star297 0:768ae9838086 24 #include "http_parsed_url.h"
star297 0:768ae9838086 25
star297 0:768ae9838086 26 class HttpRequestBuilder {
star297 0:768ae9838086 27 public:
star297 0:768ae9838086 28 HttpRequestBuilder(http_method a_method, ParsedUrl* a_parsed_url)
star297 0:768ae9838086 29 : method(a_method), parsed_url(a_parsed_url)
star297 0:768ae9838086 30 {
star297 0:768ae9838086 31 string host(parsed_url->host());
star297 0:768ae9838086 32
star297 0:768ae9838086 33 char port_str[10];
star297 0:768ae9838086 34 sprintf(port_str, ":%d", parsed_url->port());
star297 0:768ae9838086 35
star297 0:768ae9838086 36 if (strcmp(parsed_url->schema(), "http") == 0 && parsed_url->port() != 80) {
star297 0:768ae9838086 37 host += string(port_str);
star297 0:768ae9838086 38 }
star297 0:768ae9838086 39 else if (strcmp(parsed_url->schema(), "https") == 0 && parsed_url->port() != 443) {
star297 0:768ae9838086 40 host += string(port_str);
star297 0:768ae9838086 41 }
star297 0:768ae9838086 42 else if (strcmp(parsed_url->schema(), "ws") == 0 && parsed_url->port() != 80) {
star297 0:768ae9838086 43 host += string(port_str);
star297 0:768ae9838086 44 }
star297 0:768ae9838086 45 else if (strcmp(parsed_url->schema(), "wss") == 0 && parsed_url->port() != 443) {
star297 0:768ae9838086 46 host += string(port_str);
star297 0:768ae9838086 47 }
star297 0:768ae9838086 48
star297 0:768ae9838086 49 set_header("Host", host);
star297 0:768ae9838086 50 }
star297 0:768ae9838086 51
star297 0:768ae9838086 52 /**
star297 0:768ae9838086 53 * Set a header for the request
star297 0:768ae9838086 54 * If the key already exists, it will be overwritten...
star297 0:768ae9838086 55 */
star297 0:768ae9838086 56 void set_header(string key, string value) {
star297 0:768ae9838086 57 map<string, string>::iterator it = headers.find(key);
star297 0:768ae9838086 58
star297 0:768ae9838086 59 if (it != headers.end()) {
star297 0:768ae9838086 60 it->second = value;
star297 0:768ae9838086 61 }
star297 0:768ae9838086 62 else {
star297 0:768ae9838086 63 headers.insert(headers.end(), pair<string, string>(key, value));
star297 0:768ae9838086 64 }
star297 0:768ae9838086 65 }
star297 0:768ae9838086 66
star297 0:768ae9838086 67 char* build(const void* body, unsigned long body_size, uint32_t &size, bool skip_content_length = false) {
star297 0:768ae9838086 68 const char* method_str = http_method_str(method);
star297 0:768ae9838086 69
star297 0:768ae9838086 70 bool is_chunked = has_header("Transfer-Encoding", "chunked");
star297 0:768ae9838086 71
star297 0:768ae9838086 72 if (!is_chunked && (method == HTTP_POST || method == HTTP_PUT || method == HTTP_DELETE || body_size > 0)) {
star297 0:768ae9838086 73 char buffer[10];
star297 0:768ae9838086 74 snprintf(buffer, 10, "%lu", body_size);
star297 0:768ae9838086 75 set_header("Content-Length", string(buffer));
star297 0:768ae9838086 76 }
star297 0:768ae9838086 77
star297 0:768ae9838086 78 size = 0;
star297 0:768ae9838086 79
star297 0:768ae9838086 80 // first line is METHOD PATH+QUERY HTTP/1.1\r\n
star297 0:768ae9838086 81 size += strlen(method_str) + 1 + strlen(parsed_url->path()) + (strlen(parsed_url->query()) ? strlen(parsed_url->query()) + 1 : 0) + 1 + 8 + 2;
star297 0:768ae9838086 82
star297 0:768ae9838086 83 // after that we'll do the headers
star297 0:768ae9838086 84 typedef map<string, string>::iterator it_type;
star297 0:768ae9838086 85 for(it_type it = headers.begin(); it != headers.end(); it++) {
star297 0:768ae9838086 86 // line is KEY: VALUE\r\n
star297 0:768ae9838086 87 size += it->first.length() + 1 + 1 + it->second.length() + 2;
star297 0:768ae9838086 88 }
star297 0:768ae9838086 89
star297 0:768ae9838086 90 // then the body, first an extra newline
star297 0:768ae9838086 91 size += 2;
star297 0:768ae9838086 92
star297 0:768ae9838086 93 if (!is_chunked) {
star297 0:768ae9838086 94 // body
star297 0:768ae9838086 95 size += body_size;
star297 0:768ae9838086 96 }
star297 0:768ae9838086 97
star297 0:768ae9838086 98 // Now let's print it
star297 0:768ae9838086 99 char* req = (char*)calloc(size + 1, 1);
star297 0:768ae9838086 100 char* originalReq = req;
star297 0:768ae9838086 101
star297 0:768ae9838086 102 if (strlen(parsed_url->query())) {
star297 0:768ae9838086 103 sprintf(req, "%s %s?%s HTTP/1.1\r\n", method_str, parsed_url->path(), parsed_url->query());
star297 0:768ae9838086 104 } else {
star297 0:768ae9838086 105 sprintf(req, "%s %s%s HTTP/1.1\r\n", method_str, parsed_url->path(), parsed_url->query());
star297 0:768ae9838086 106 }
star297 0:768ae9838086 107 req += strlen(method_str) + 1 + strlen(parsed_url->path()) + (strlen(parsed_url->query()) ? strlen(parsed_url->query()) + 1 : 0) + 1 + 8 + 2;
star297 0:768ae9838086 108
star297 0:768ae9838086 109 typedef map<string, string>::iterator it_type;
star297 0:768ae9838086 110 for(it_type it = headers.begin(); it != headers.end(); it++) {
star297 0:768ae9838086 111 // line is KEY: VALUE\r\n
star297 0:768ae9838086 112 sprintf(req, "%s: %s\r\n", it->first.c_str(), it->second.c_str());
star297 0:768ae9838086 113 req += it->first.length() + 1 + 1 + it->second.length() + 2;
star297 0:768ae9838086 114 }
star297 0:768ae9838086 115
star297 0:768ae9838086 116 sprintf(req, "\r\n");
star297 0:768ae9838086 117 req += 2;
star297 0:768ae9838086 118
star297 0:768ae9838086 119 if (body_size > 0) {
star297 0:768ae9838086 120 memcpy(req, body, body_size);
star297 0:768ae9838086 121 }
star297 0:768ae9838086 122 req += body_size;
star297 0:768ae9838086 123
star297 0:768ae9838086 124 // Uncomment to debug...
star297 0:768ae9838086 125 // printf("----- BEGIN REQUEST -----\n");
star297 0:768ae9838086 126 // printf("%s", originalReq);
star297 0:768ae9838086 127 // printf("----- END REQUEST -----\n");
star297 0:768ae9838086 128
star297 0:768ae9838086 129 return originalReq;
star297 0:768ae9838086 130 }
star297 0:768ae9838086 131
star297 0:768ae9838086 132 private:
star297 0:768ae9838086 133 bool has_header(const char* key, const char* value = NULL) {
star297 0:768ae9838086 134 typedef map<string, string>::iterator it_type;
star297 0:768ae9838086 135 for(it_type it = headers.begin(); it != headers.end(); it++) {
star297 0:768ae9838086 136 if (strcmp(it->first.c_str(), key) == 0) { // key matches
star297 0:768ae9838086 137 if (value == NULL || (strcmp(it->second.c_str(), value) == 0)) { // value is NULL or matches
star297 0:768ae9838086 138 return true;
star297 0:768ae9838086 139 }
star297 0:768ae9838086 140 }
star297 0:768ae9838086 141 }
star297 0:768ae9838086 142
star297 0:768ae9838086 143 return false;
star297 0:768ae9838086 144 }
star297 0:768ae9838086 145
star297 0:768ae9838086 146 http_method method;
star297 0:768ae9838086 147 ParsedUrl* parsed_url;
star297 0:768ae9838086 148 map<string, string> headers;
star297 0:768ae9838086 149 };
star297 0:768ae9838086 150
star297 0:768ae9838086 151 #endif // _MBED_HTTP_REQUEST_BUILDER_H_