Experimental HTTP and HTTPS library for mbed OS 5

Committer:
nmathon
Date:
Sun Dec 23 17:55:40 2018 +0000
Revision:
33:305c17fe6737
Parent:
31:b3730a2c4f39
Remove TLSSocket because it's already in Mbed 0S 5.11

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jan Jongboom 31:b3730a2c4f39 1 /*
Jan Jongboom 31:b3730a2c4f39 2 * PackageLicenseDeclared: Apache-2.0
Jan Jongboom 31:b3730a2c4f39 3 * Copyright (c) 2017 ARM Limited
Jan Jongboom 31:b3730a2c4f39 4 *
Jan Jongboom 31:b3730a2c4f39 5 * Licensed under the Apache License, Version 2.0 (the "License");
Jan Jongboom 31:b3730a2c4f39 6 * you may not use this file except in compliance with the License.
Jan Jongboom 31:b3730a2c4f39 7 * You may obtain a copy of the License at
Jan Jongboom 31:b3730a2c4f39 8 *
Jan Jongboom 31:b3730a2c4f39 9 * http://www.apache.org/licenses/LICENSE-2.0
Jan Jongboom 31:b3730a2c4f39 10 *
Jan Jongboom 31:b3730a2c4f39 11 * Unless required by applicable law or agreed to in writing, software
Jan Jongboom 31:b3730a2c4f39 12 * distributed under the License is distributed on an "AS IS" BASIS,
Jan Jongboom 31:b3730a2c4f39 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Jan Jongboom 31:b3730a2c4f39 14 * See the License for the specific language governing permissions and
Jan Jongboom 31:b3730a2c4f39 15 * limitations under the License.
Jan Jongboom 31:b3730a2c4f39 16 */
Jan Jongboom 31:b3730a2c4f39 17
Jan Jongboom 31:b3730a2c4f39 18 #ifndef _HTTP_REQUEST_BASE_H_
Jan Jongboom 31:b3730a2c4f39 19 #define _HTTP_REQUEST_BASE_H_
Jan Jongboom 31:b3730a2c4f39 20
Jan Jongboom 31:b3730a2c4f39 21 #include <map>
Jan Jongboom 31:b3730a2c4f39 22 #include <string>
Jan Jongboom 31:b3730a2c4f39 23 #include <vector>
Jan Jongboom 31:b3730a2c4f39 24 #include "mbed.h"
Jan Jongboom 31:b3730a2c4f39 25 #include "http_parser.h"
Jan Jongboom 31:b3730a2c4f39 26 #include "http_parsed_url.h"
Jan Jongboom 31:b3730a2c4f39 27 #include "http_request_builder.h"
Jan Jongboom 31:b3730a2c4f39 28 #include "http_request_parser.h"
Jan Jongboom 31:b3730a2c4f39 29 #include "http_response.h"
Jan Jongboom 31:b3730a2c4f39 30 #include "NetworkInterface.h"
Jan Jongboom 31:b3730a2c4f39 31 #include "netsocket/Socket.h"
Jan Jongboom 31:b3730a2c4f39 32
Jan Jongboom 31:b3730a2c4f39 33 /**
Jan Jongboom 31:b3730a2c4f39 34 * @todo:
Jan Jongboom 31:b3730a2c4f39 35 * - Userinfo parameter is not handled
Jan Jongboom 31:b3730a2c4f39 36 */
Jan Jongboom 31:b3730a2c4f39 37
Jan Jongboom 31:b3730a2c4f39 38 #ifndef HTTP_RECEIVE_BUFFER_SIZE
Jan Jongboom 31:b3730a2c4f39 39 #define HTTP_RECEIVE_BUFFER_SIZE 8 * 1024
Jan Jongboom 31:b3730a2c4f39 40 #endif
Jan Jongboom 31:b3730a2c4f39 41
Jan Jongboom 31:b3730a2c4f39 42 class HttpRequest;
Jan Jongboom 31:b3730a2c4f39 43 class HttpsRequest;
Jan Jongboom 31:b3730a2c4f39 44
Jan Jongboom 31:b3730a2c4f39 45 /**
Jan Jongboom 31:b3730a2c4f39 46 * \brief HttpRequest implements the logic for interacting with HTTP servers.
Jan Jongboom 31:b3730a2c4f39 47 */
Jan Jongboom 31:b3730a2c4f39 48 class HttpRequestBase {
Jan Jongboom 31:b3730a2c4f39 49 friend class HttpRequest;
Jan Jongboom 31:b3730a2c4f39 50 friend class HttpsRequest;
Jan Jongboom 31:b3730a2c4f39 51
Jan Jongboom 31:b3730a2c4f39 52 public:
Jan Jongboom 31:b3730a2c4f39 53 HttpRequestBase(Socket *socket, Callback<void(const char *at, uint32_t length)> bodyCallback)
Jan Jongboom 31:b3730a2c4f39 54 : _socket(socket), _body_callback(bodyCallback), _request_buffer(NULL), _request_buffer_ix(0)
Jan Jongboom 31:b3730a2c4f39 55 {}
Jan Jongboom 31:b3730a2c4f39 56
Jan Jongboom 31:b3730a2c4f39 57 /**
Jan Jongboom 31:b3730a2c4f39 58 * HttpRequest Constructor
Jan Jongboom 31:b3730a2c4f39 59 */
Jan Jongboom 31:b3730a2c4f39 60 virtual ~HttpRequestBase() {
Jan Jongboom 31:b3730a2c4f39 61 // should response be owned by us? Or should user free it?
Jan Jongboom 31:b3730a2c4f39 62 // maybe implement copy constructor on response...
Jan Jongboom 31:b3730a2c4f39 63 if (_response) {
Jan Jongboom 31:b3730a2c4f39 64 delete _response;
Jan Jongboom 31:b3730a2c4f39 65 }
Jan Jongboom 31:b3730a2c4f39 66
Jan Jongboom 31:b3730a2c4f39 67 if (_parsed_url) {
Jan Jongboom 31:b3730a2c4f39 68 delete _parsed_url;
Jan Jongboom 31:b3730a2c4f39 69 }
Jan Jongboom 31:b3730a2c4f39 70
Jan Jongboom 31:b3730a2c4f39 71 if (_request_builder) {
Jan Jongboom 31:b3730a2c4f39 72 delete _request_builder;
Jan Jongboom 31:b3730a2c4f39 73 }
Jan Jongboom 31:b3730a2c4f39 74
Jan Jongboom 31:b3730a2c4f39 75 if (_socket && _we_created_socket) {
Jan Jongboom 31:b3730a2c4f39 76 delete _socket;
Jan Jongboom 31:b3730a2c4f39 77 }
Jan Jongboom 31:b3730a2c4f39 78 }
Jan Jongboom 31:b3730a2c4f39 79
Jan Jongboom 31:b3730a2c4f39 80 /**
Jan Jongboom 31:b3730a2c4f39 81 * Execute the request and receive the response.
Jan Jongboom 31:b3730a2c4f39 82 * This adds a Content-Length header to the request (when body_size is set), and sends the data to the server.
Jan Jongboom 31:b3730a2c4f39 83 * @param body Pointer to the body to be sent
Jan Jongboom 31:b3730a2c4f39 84 * @param body_size Size of the body to be sent
Jan Jongboom 31:b3730a2c4f39 85 * @return An HttpResponse pointer on success, or NULL on failure.
Jan Jongboom 31:b3730a2c4f39 86 * See get_error() for the error code.
Jan Jongboom 31:b3730a2c4f39 87 */
Jan Jongboom 31:b3730a2c4f39 88 HttpResponse* send(const void* body = NULL, nsapi_size_t body_size = 0) {
Jan Jongboom 31:b3730a2c4f39 89 nsapi_size_or_error_t ret = connect_socket();
Jan Jongboom 31:b3730a2c4f39 90
Jan Jongboom 31:b3730a2c4f39 91 if (ret != NSAPI_ERROR_OK) {
Jan Jongboom 31:b3730a2c4f39 92 _error = ret;
Jan Jongboom 31:b3730a2c4f39 93 return NULL;
Jan Jongboom 31:b3730a2c4f39 94 }
Jan Jongboom 31:b3730a2c4f39 95
Jan Jongboom 31:b3730a2c4f39 96 _request_buffer_ix = 0;
Jan Jongboom 31:b3730a2c4f39 97
Jan Jongboom 31:b3730a2c4f39 98 uint32_t request_size = 0;
Jan Jongboom 31:b3730a2c4f39 99 char* request = _request_builder->build(body, body_size, request_size);
Jan Jongboom 31:b3730a2c4f39 100
Jan Jongboom 31:b3730a2c4f39 101 ret = send_buffer(request, request_size);
Jan Jongboom 31:b3730a2c4f39 102
Jan Jongboom 31:b3730a2c4f39 103 free(request);
Jan Jongboom 31:b3730a2c4f39 104
Jan Jongboom 31:b3730a2c4f39 105 if (ret < 0) {
Jan Jongboom 31:b3730a2c4f39 106 _error = ret;
Jan Jongboom 31:b3730a2c4f39 107 return NULL;
Jan Jongboom 31:b3730a2c4f39 108 }
Jan Jongboom 31:b3730a2c4f39 109
Jan Jongboom 31:b3730a2c4f39 110 return create_http_response();
Jan Jongboom 31:b3730a2c4f39 111 }
Jan Jongboom 31:b3730a2c4f39 112
Jan Jongboom 31:b3730a2c4f39 113 /**
Jan Jongboom 31:b3730a2c4f39 114 * Execute the request and receive the response.
Jan Jongboom 31:b3730a2c4f39 115 * This sends the request through chunked-encoding.
Jan Jongboom 31:b3730a2c4f39 116 * @param body_cb Callback which generates the next chunk of the request
Jan Jongboom 31:b3730a2c4f39 117 * @return An HttpResponse pointer on success, or NULL on failure.
Jan Jongboom 31:b3730a2c4f39 118 * See get_error() for the error code.
Jan Jongboom 31:b3730a2c4f39 119 */
Jan Jongboom 31:b3730a2c4f39 120 HttpResponse* send(Callback<const void*(uint32_t*)> body_cb) {
Jan Jongboom 31:b3730a2c4f39 121
Jan Jongboom 31:b3730a2c4f39 122 nsapi_error_t ret;
Jan Jongboom 31:b3730a2c4f39 123
Jan Jongboom 31:b3730a2c4f39 124 if ((ret = connect_socket()) != NSAPI_ERROR_OK) {
Jan Jongboom 31:b3730a2c4f39 125 _error = ret;
Jan Jongboom 31:b3730a2c4f39 126 return NULL;
Jan Jongboom 31:b3730a2c4f39 127 }
Jan Jongboom 31:b3730a2c4f39 128
Jan Jongboom 31:b3730a2c4f39 129 _request_buffer_ix = 0;
Jan Jongboom 31:b3730a2c4f39 130
Jan Jongboom 31:b3730a2c4f39 131 set_header("Transfer-Encoding", "chunked");
Jan Jongboom 31:b3730a2c4f39 132
Jan Jongboom 31:b3730a2c4f39 133 uint32_t request_size = 0;
Jan Jongboom 31:b3730a2c4f39 134 char* request = _request_builder->build(NULL, 0, request_size);
Jan Jongboom 31:b3730a2c4f39 135
Jan Jongboom 31:b3730a2c4f39 136 // first... send this request headers without the body
Jan Jongboom 31:b3730a2c4f39 137 nsapi_size_or_error_t total_send_count = send_buffer(request, request_size);
Jan Jongboom 31:b3730a2c4f39 138
Jan Jongboom 31:b3730a2c4f39 139 if (total_send_count < 0) {
Jan Jongboom 31:b3730a2c4f39 140 free(request);
Jan Jongboom 31:b3730a2c4f39 141 _error = total_send_count;
Jan Jongboom 31:b3730a2c4f39 142 return NULL;
Jan Jongboom 31:b3730a2c4f39 143 }
Jan Jongboom 31:b3730a2c4f39 144
Jan Jongboom 31:b3730a2c4f39 145 // ok... now it's time to start sending chunks...
Jan Jongboom 31:b3730a2c4f39 146 while (1) {
Jan Jongboom 31:b3730a2c4f39 147 uint32_t size;
Jan Jongboom 31:b3730a2c4f39 148 const void *buffer = body_cb(&size);
Jan Jongboom 31:b3730a2c4f39 149
Jan Jongboom 31:b3730a2c4f39 150 if (size == 0) break;
Jan Jongboom 31:b3730a2c4f39 151
Jan Jongboom 31:b3730a2c4f39 152 // so... size in HEX, \r\n, data, \r\n again
Jan Jongboom 31:b3730a2c4f39 153 char size_buff[10]; // if sending length of more than 8 digits, you have another problem on a microcontroller...
Jan Jongboom 31:b3730a2c4f39 154 int size_buff_size = sprintf(size_buff, "%X\r\n", static_cast<size_t>(size));
Jan Jongboom 31:b3730a2c4f39 155 if ((total_send_count = send_buffer(size_buff, static_cast<uint32_t>(size_buff_size))) < 0) {
Jan Jongboom 31:b3730a2c4f39 156 free(request);
Jan Jongboom 31:b3730a2c4f39 157 _error = total_send_count;
Jan Jongboom 31:b3730a2c4f39 158 return NULL;
Jan Jongboom 31:b3730a2c4f39 159 }
Jan Jongboom 31:b3730a2c4f39 160
Jan Jongboom 31:b3730a2c4f39 161 // now send the normal buffer... and then \r\n at the end
Jan Jongboom 31:b3730a2c4f39 162 total_send_count = send_buffer((char*)buffer, size);
Jan Jongboom 31:b3730a2c4f39 163 if (total_send_count < 0) {
Jan Jongboom 31:b3730a2c4f39 164 free(request);
Jan Jongboom 31:b3730a2c4f39 165 _error = total_send_count;
Jan Jongboom 31:b3730a2c4f39 166 return NULL;
Jan Jongboom 31:b3730a2c4f39 167 }
Jan Jongboom 31:b3730a2c4f39 168
Jan Jongboom 31:b3730a2c4f39 169 // and... \r\n
Jan Jongboom 31:b3730a2c4f39 170 const char* rn = "\r\n";
Jan Jongboom 31:b3730a2c4f39 171 if ((total_send_count = send_buffer((char*)rn, 2)) < 0) {
Jan Jongboom 31:b3730a2c4f39 172 free(request);
Jan Jongboom 31:b3730a2c4f39 173 _error = total_send_count;
Jan Jongboom 31:b3730a2c4f39 174 return NULL;
Jan Jongboom 31:b3730a2c4f39 175 }
Jan Jongboom 31:b3730a2c4f39 176 }
Jan Jongboom 31:b3730a2c4f39 177
Jan Jongboom 31:b3730a2c4f39 178 // finalize...?
Jan Jongboom 31:b3730a2c4f39 179 const char* fin = "0\r\n\r\n";
Jan Jongboom 31:b3730a2c4f39 180 if ((total_send_count = send_buffer((char*)fin, strlen(fin))) < 0) {
Jan Jongboom 31:b3730a2c4f39 181 free(request);
Jan Jongboom 31:b3730a2c4f39 182 _error = total_send_count;
Jan Jongboom 31:b3730a2c4f39 183 return NULL;
Jan Jongboom 31:b3730a2c4f39 184 }
Jan Jongboom 31:b3730a2c4f39 185
Jan Jongboom 31:b3730a2c4f39 186 free(request);
Jan Jongboom 31:b3730a2c4f39 187
Jan Jongboom 31:b3730a2c4f39 188 return create_http_response();
Jan Jongboom 31:b3730a2c4f39 189 }
Jan Jongboom 31:b3730a2c4f39 190
Jan Jongboom 31:b3730a2c4f39 191 /**
Jan Jongboom 31:b3730a2c4f39 192 * Set a header for the request.
Jan Jongboom 31:b3730a2c4f39 193 *
Jan Jongboom 31:b3730a2c4f39 194 * The 'Host', 'Content-Length', and (optionally) 'Transfer-Encoding: chunked'
Jan Jongboom 31:b3730a2c4f39 195 * headers are set automatically.
Jan Jongboom 31:b3730a2c4f39 196 * Setting the same header twice will overwrite the previous entry.
Jan Jongboom 31:b3730a2c4f39 197 *
Jan Jongboom 31:b3730a2c4f39 198 * @param key Header key
Jan Jongboom 31:b3730a2c4f39 199 * @param value Header value
Jan Jongboom 31:b3730a2c4f39 200 */
Jan Jongboom 31:b3730a2c4f39 201 void set_header(string key, string value) {
Jan Jongboom 31:b3730a2c4f39 202 _request_builder->set_header(key, value);
Jan Jongboom 31:b3730a2c4f39 203 }
Jan Jongboom 31:b3730a2c4f39 204
Jan Jongboom 31:b3730a2c4f39 205 /**
Jan Jongboom 31:b3730a2c4f39 206 * Get the error code.
Jan Jongboom 31:b3730a2c4f39 207 *
Jan Jongboom 31:b3730a2c4f39 208 * When send() fails, this error is set.
Jan Jongboom 31:b3730a2c4f39 209 */
Jan Jongboom 31:b3730a2c4f39 210 nsapi_error_t get_error() {
Jan Jongboom 31:b3730a2c4f39 211 return _error;
Jan Jongboom 31:b3730a2c4f39 212 }
Jan Jongboom 31:b3730a2c4f39 213
Jan Jongboom 31:b3730a2c4f39 214 /**
Jan Jongboom 31:b3730a2c4f39 215 * Set the request log buffer, all bytes that are sent for this request are logged here.
Jan Jongboom 31:b3730a2c4f39 216 * If the buffer would overflow logging is stopped.
Jan Jongboom 31:b3730a2c4f39 217 *
Jan Jongboom 31:b3730a2c4f39 218 * @param buffer Pointer to a buffer to store the data in
Jan Jongboom 31:b3730a2c4f39 219 * @param buffer_size Size of the buffer
Jan Jongboom 31:b3730a2c4f39 220 */
Jan Jongboom 31:b3730a2c4f39 221 void set_request_log_buffer(uint8_t *buffer, size_t buffer_size) {
Jan Jongboom 31:b3730a2c4f39 222 _request_buffer = buffer;
Jan Jongboom 31:b3730a2c4f39 223 _request_buffer_size = buffer_size;
Jan Jongboom 31:b3730a2c4f39 224 _request_buffer_ix = 0;
Jan Jongboom 31:b3730a2c4f39 225 }
Jan Jongboom 31:b3730a2c4f39 226
Jan Jongboom 31:b3730a2c4f39 227 /**
Jan Jongboom 31:b3730a2c4f39 228 * Get the number of bytes written to the request log buffer, since the last request.
Jan Jongboom 31:b3730a2c4f39 229 * If no request was sent, or if the request log buffer is NULL, then this returns 0.
Jan Jongboom 31:b3730a2c4f39 230 */
Jan Jongboom 31:b3730a2c4f39 231 size_t get_request_log_buffer_length() {
Jan Jongboom 31:b3730a2c4f39 232 return _request_buffer_ix;
Jan Jongboom 31:b3730a2c4f39 233 }
Jan Jongboom 31:b3730a2c4f39 234
Jan Jongboom 31:b3730a2c4f39 235 protected:
Jan Jongboom 31:b3730a2c4f39 236 virtual nsapi_error_t connect_socket(char *host, uint16_t port) = 0;
Jan Jongboom 31:b3730a2c4f39 237
Jan Jongboom 31:b3730a2c4f39 238 private:
Jan Jongboom 31:b3730a2c4f39 239 nsapi_error_t connect_socket( ) {
Jan Jongboom 31:b3730a2c4f39 240 if (_response != NULL) {
Jan Jongboom 31:b3730a2c4f39 241 // already executed this response
Jan Jongboom 31:b3730a2c4f39 242 return -2100; // @todo, make a lookup table with errors
Jan Jongboom 31:b3730a2c4f39 243 }
Jan Jongboom 31:b3730a2c4f39 244
Jan Jongboom 31:b3730a2c4f39 245
Jan Jongboom 31:b3730a2c4f39 246 if (_we_created_socket) {
Jan Jongboom 31:b3730a2c4f39 247 nsapi_error_t connection_result = connect_socket(_parsed_url->host(), _parsed_url->port());
Jan Jongboom 31:b3730a2c4f39 248 if (connection_result != NSAPI_ERROR_OK) {
Jan Jongboom 31:b3730a2c4f39 249 return connection_result;
Jan Jongboom 31:b3730a2c4f39 250 }
Jan Jongboom 31:b3730a2c4f39 251 }
Jan Jongboom 31:b3730a2c4f39 252
Jan Jongboom 31:b3730a2c4f39 253 return NSAPI_ERROR_OK;
Jan Jongboom 31:b3730a2c4f39 254 }
Jan Jongboom 31:b3730a2c4f39 255
Jan Jongboom 31:b3730a2c4f39 256 nsapi_size_or_error_t send_buffer(char* buffer, uint32_t buffer_size) {
Jan Jongboom 31:b3730a2c4f39 257 nsapi_size_or_error_t total_send_count = 0;
Jan Jongboom 31:b3730a2c4f39 258 while (total_send_count < buffer_size) {
Jan Jongboom 31:b3730a2c4f39 259
Jan Jongboom 31:b3730a2c4f39 260 // get a slice of the buffer
Jan Jongboom 31:b3730a2c4f39 261 char *buffer_slice = buffer + total_send_count;
Jan Jongboom 31:b3730a2c4f39 262 uint32_t buffer_slice_size = buffer_size - total_send_count;
Jan Jongboom 31:b3730a2c4f39 263
Jan Jongboom 31:b3730a2c4f39 264 // if request buffer was set, copy it there
Jan Jongboom 31:b3730a2c4f39 265 if (_request_buffer != NULL && _request_buffer_ix + buffer_slice_size < _request_buffer_size) {
Jan Jongboom 31:b3730a2c4f39 266 memcpy(_request_buffer + _request_buffer_ix, buffer_slice, buffer_slice_size);
Jan Jongboom 31:b3730a2c4f39 267 _request_buffer_ix += buffer_slice_size;
Jan Jongboom 31:b3730a2c4f39 268 }
Jan Jongboom 31:b3730a2c4f39 269
Jan Jongboom 31:b3730a2c4f39 270 nsapi_size_or_error_t send_result = _socket->send(buffer_slice, buffer_slice_size);
Jan Jongboom 31:b3730a2c4f39 271
Jan Jongboom 31:b3730a2c4f39 272 if (send_result < 0) {
Jan Jongboom 31:b3730a2c4f39 273 total_send_count = send_result;
Jan Jongboom 31:b3730a2c4f39 274 break;
Jan Jongboom 31:b3730a2c4f39 275 }
Jan Jongboom 31:b3730a2c4f39 276
Jan Jongboom 31:b3730a2c4f39 277 if (send_result == 0) {
Jan Jongboom 31:b3730a2c4f39 278 break;
Jan Jongboom 31:b3730a2c4f39 279 }
Jan Jongboom 31:b3730a2c4f39 280
Jan Jongboom 31:b3730a2c4f39 281 total_send_count += send_result;
Jan Jongboom 31:b3730a2c4f39 282 }
Jan Jongboom 31:b3730a2c4f39 283
Jan Jongboom 31:b3730a2c4f39 284 return total_send_count;
Jan Jongboom 31:b3730a2c4f39 285 }
Jan Jongboom 31:b3730a2c4f39 286
Jan Jongboom 31:b3730a2c4f39 287 HttpResponse* create_http_response() {
Jan Jongboom 31:b3730a2c4f39 288 // Create a response object
Jan Jongboom 31:b3730a2c4f39 289 _response = new HttpResponse();
Jan Jongboom 31:b3730a2c4f39 290 // And a response parser
Jan Jongboom 31:b3730a2c4f39 291 HttpParser parser(_response, HTTP_RESPONSE, _body_callback);
Jan Jongboom 31:b3730a2c4f39 292
Jan Jongboom 31:b3730a2c4f39 293 // Set up a receive buffer (on the heap)
Jan Jongboom 31:b3730a2c4f39 294 uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE);
Jan Jongboom 31:b3730a2c4f39 295
Jan Jongboom 31:b3730a2c4f39 296 // Socket::recv is called until we don't have any data anymore
Jan Jongboom 31:b3730a2c4f39 297 nsapi_size_or_error_t recv_ret;
Jan Jongboom 31:b3730a2c4f39 298 while ((recv_ret = _socket->recv(recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) {
Jan Jongboom 31:b3730a2c4f39 299
Jan Jongboom 31:b3730a2c4f39 300 // Pass the chunk into the http_parser
Jan Jongboom 31:b3730a2c4f39 301 uint32_t nparsed = parser.execute((const char*)recv_buffer, recv_ret);
Jan Jongboom 31:b3730a2c4f39 302 if (nparsed != recv_ret) {
Jan Jongboom 31:b3730a2c4f39 303 // printf("Parsing failed... parsed %d bytes, received %d bytes\n", nparsed, recv_ret);
Jan Jongboom 31:b3730a2c4f39 304 _error = -2101;
Jan Jongboom 31:b3730a2c4f39 305 free(recv_buffer);
Jan Jongboom 31:b3730a2c4f39 306 return NULL;
Jan Jongboom 31:b3730a2c4f39 307 }
Jan Jongboom 31:b3730a2c4f39 308
Jan Jongboom 31:b3730a2c4f39 309 if (_response->is_message_complete()) {
Jan Jongboom 31:b3730a2c4f39 310 break;
Jan Jongboom 31:b3730a2c4f39 311 }
Jan Jongboom 31:b3730a2c4f39 312 }
Jan Jongboom 31:b3730a2c4f39 313 // error?
Jan Jongboom 31:b3730a2c4f39 314 if (recv_ret < 0) {
Jan Jongboom 31:b3730a2c4f39 315 _error = recv_ret;
Jan Jongboom 31:b3730a2c4f39 316 free(recv_buffer);
Jan Jongboom 31:b3730a2c4f39 317 return NULL;
Jan Jongboom 31:b3730a2c4f39 318 }
Jan Jongboom 31:b3730a2c4f39 319
Jan Jongboom 31:b3730a2c4f39 320 // When done, call parser.finish()
Jan Jongboom 31:b3730a2c4f39 321 parser.finish();
Jan Jongboom 31:b3730a2c4f39 322
Jan Jongboom 31:b3730a2c4f39 323 // Free the receive buffer
Jan Jongboom 31:b3730a2c4f39 324 free(recv_buffer);
Jan Jongboom 31:b3730a2c4f39 325
Jan Jongboom 31:b3730a2c4f39 326 if (_we_created_socket) {
Jan Jongboom 31:b3730a2c4f39 327 // Close the socket
Jan Jongboom 31:b3730a2c4f39 328 _socket->close();
Jan Jongboom 31:b3730a2c4f39 329 }
Jan Jongboom 31:b3730a2c4f39 330
Jan Jongboom 31:b3730a2c4f39 331 return _response;
Jan Jongboom 31:b3730a2c4f39 332 }
Jan Jongboom 31:b3730a2c4f39 333
Jan Jongboom 31:b3730a2c4f39 334 private:
Jan Jongboom 31:b3730a2c4f39 335 Socket* _socket;
Jan Jongboom 31:b3730a2c4f39 336 Callback<void(const char *at, uint32_t length)> _body_callback;
Jan Jongboom 31:b3730a2c4f39 337
Jan Jongboom 31:b3730a2c4f39 338 ParsedUrl* _parsed_url;
Jan Jongboom 31:b3730a2c4f39 339
Jan Jongboom 31:b3730a2c4f39 340 HttpRequestBuilder* _request_builder;
Jan Jongboom 31:b3730a2c4f39 341 HttpResponse* _response;
Jan Jongboom 31:b3730a2c4f39 342
Jan Jongboom 31:b3730a2c4f39 343 bool _we_created_socket;
Jan Jongboom 31:b3730a2c4f39 344
Jan Jongboom 31:b3730a2c4f39 345 nsapi_error_t _error;
Jan Jongboom 31:b3730a2c4f39 346
Jan Jongboom 31:b3730a2c4f39 347 uint8_t *_request_buffer;
Jan Jongboom 31:b3730a2c4f39 348 size_t _request_buffer_size;
Jan Jongboom 31:b3730a2c4f39 349 size_t _request_buffer_ix;
Jan Jongboom 31:b3730a2c4f39 350 };
Jan Jongboom 31:b3730a2c4f39 351
Jan Jongboom 31:b3730a2c4f39 352 #endif // _HTTP_REQUEST_BASE_H_