fix the problem http request with '\0' and fixx query string in url
Fork of mbed-http by
http_request.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 _HTTP_REQUEST_ 00019 #define _HTTP_REQUEST_ 00020 00021 #include <string> 00022 #include <vector> 00023 #include <map> 00024 #include "http_parser.h" 00025 #include "http_response.h" 00026 #include "http_request_builder.h" 00027 #include "http_response_parser.h" 00028 #include "http_parsed_url.h" 00029 00030 /** 00031 * @todo: 00032 * - Userinfo parameter is not handled 00033 * - Allow socket re-use 00034 */ 00035 00036 00037 /** 00038 * \brief HttpRequest implements the logic for interacting with HTTPS servers. 00039 */ 00040 class HttpRequest { 00041 public: 00042 /** 00043 * HttpRequest Constructor 00044 * 00045 * @param[in] aNetwork The network interface 00046 * @param[in] aMethod HTTP method to use 00047 * @param[in] url URL to the resource 00048 * @param[in] aBodyCallback Callback on which to retrieve chunks of the response body. 00049 If not set, the complete body will be allocated on the HttpResponse object, 00050 which might use lots of memory. 00051 */ 00052 HttpRequest(NetworkInterface* aNetwork, http_method aMethod, const char* url, Callback<void(const char *at, size_t length)> aBodyCallback = 0) 00053 : network(aNetwork), method(aMethod), body_callback(aBodyCallback) 00054 { 00055 error = 0; 00056 response = NULL; 00057 00058 parsed_url = new ParsedUrl(url); 00059 request_builder = new HttpRequestBuilder(method, parsed_url); 00060 } 00061 00062 /** 00063 * HttpRequest Constructor 00064 */ 00065 ~HttpRequest() { 00066 // should response be owned by us? Or should user free it? 00067 // maybe implement copy constructor on response... 00068 if (response) { 00069 delete response; 00070 } 00071 00072 if (parsed_url) { 00073 delete parsed_url; 00074 } 00075 00076 if (request_builder) { 00077 delete request_builder; 00078 } 00079 } 00080 00081 /** 00082 * Execute the request and receive the response. 00083 */ 00084 HttpResponse* send(const void* body = NULL, nsapi_size_t body_size = 0) { 00085 if (response != NULL) { 00086 // already executed this response 00087 error = -2100; // @todo, make a lookup table with errors 00088 return NULL; 00089 } 00090 00091 error = 0; 00092 00093 TCPSocket socket; 00094 00095 nsapi_error_t open_result = socket.open(network); 00096 if (open_result != 0) { 00097 error = open_result; 00098 return NULL; 00099 } 00100 00101 nsapi_error_t connection_result = socket.connect(parsed_url->host(), parsed_url->port()); 00102 if (connection_result != 0) { 00103 error = connection_result; 00104 return NULL; 00105 } 00106 00107 size_t request_size = 0; 00108 char* request = request_builder->build(body, body_size, request_size); 00109 00110 nsapi_size_or_error_t send_result = socket.send(request, request_size); 00111 00112 free(request); 00113 00114 if (send_result != request_size) { 00115 error = send_result; 00116 return NULL; 00117 } 00118 00119 // Create a response object 00120 response = new HttpResponse(); 00121 // And a response parser 00122 HttpResponseParser parser(response, body_callback); 00123 00124 // Set up a receive buffer (on the heap) 00125 uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE); 00126 00127 // TCPSocket::recv is called until we don't have any data anymore 00128 nsapi_size_or_error_t recv_ret; 00129 while ((recv_ret = socket.recv(recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) { 00130 00131 // Pass the chunk into the http_parser 00132 size_t nparsed = parser.execute((const char*)recv_buffer, recv_ret); 00133 if (nparsed != recv_ret) { 00134 // printf("Parsing failed... parsed %d bytes, received %d bytes\n", nparsed, recv_ret); 00135 error = -2101; 00136 free(recv_buffer); 00137 return NULL; 00138 } 00139 00140 if (response->is_message_complete()) { 00141 break; 00142 } 00143 } 00144 // error? 00145 if (recv_ret < 0) { 00146 error = recv_ret; 00147 free(recv_buffer); 00148 return NULL; 00149 } 00150 00151 // When done, call parser.finish() 00152 parser.finish(); 00153 00154 // Free the receive buffer 00155 free(recv_buffer); 00156 00157 // Close the socket 00158 socket.close(); 00159 00160 return response; 00161 } 00162 00163 /** 00164 * Set a header for the request. 00165 * 00166 * The 'Host' and 'Content-Length' headers are set automatically. 00167 * Setting the same header twice will overwrite the previous entry. 00168 * 00169 * @param[in] key Header key 00170 * @param[in] value Header value 00171 */ 00172 void set_header(string key, string value) { 00173 request_builder->set_header(key, value); 00174 } 00175 00176 /** 00177 * Get the error code. 00178 * 00179 * When send() fails, this error is set. 00180 */ 00181 nsapi_error_t get_error() { 00182 return error; 00183 } 00184 00185 private: 00186 NetworkInterface* network; 00187 http_method method; 00188 Callback<void(const char *at, size_t length)> body_callback; 00189 00190 ParsedUrl* parsed_url; 00191 00192 HttpRequestBuilder* request_builder; 00193 HttpResponse* response; 00194 00195 nsapi_error_t error; 00196 }; 00197 00198 #endif // _HTTP_REQUEST_
Generated on Fri Jul 22 2022 08:07:18 by 1.7.2