HTTP and HTTPS library for Mbed OS 5

Dependents:   RZ_A2M_Mbed_samples_20201012 RZ_A2M_Mbed_samples

Committer:
RyoheiHagimoto@os.mbed.com
Date:
Wed Sep 16 14:40:45 2020 +0900
Revision:
40:8fe3b866f1f4
Parent:
34:6daf67a96a91
Modified some API for Mbed OS 6.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jan Jongboom 34:6daf67a96a91 1 /*
Jan Jongboom 34:6daf67a96a91 2 * PackageLicenseDeclared: Apache-2.0
Jan Jongboom 34:6daf67a96a91 3 * Copyright (c) 2018 ARM Limited
Jan Jongboom 34:6daf67a96a91 4 *
Jan Jongboom 34:6daf67a96a91 5 * Licensed under the Apache License, Version 2.0 (the "License");
Jan Jongboom 34:6daf67a96a91 6 * you may not use this file except in compliance with the License.
Jan Jongboom 34:6daf67a96a91 7 * You may obtain a copy of the License at
Jan Jongboom 34:6daf67a96a91 8 *
Jan Jongboom 34:6daf67a96a91 9 * http://www.apache.org/licenses/LICENSE-2.0
Jan Jongboom 34:6daf67a96a91 10 *
Jan Jongboom 34:6daf67a96a91 11 * Unless required by applicable law or agreed to in writing, software
Jan Jongboom 34:6daf67a96a91 12 * distributed under the License is distributed on an "AS IS" BASIS,
Jan Jongboom 34:6daf67a96a91 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Jan Jongboom 34:6daf67a96a91 14 * See the License for the specific language governing permissions and
Jan Jongboom 34:6daf67a96a91 15 * limitations under the License.
Jan Jongboom 34:6daf67a96a91 16 */
Jan Jongboom 34:6daf67a96a91 17
Jan Jongboom 34:6daf67a96a91 18 #include "mbed.h"
Jan Jongboom 34:6daf67a96a91 19 #include "http_request.h"
Jan Jongboom 34:6daf67a96a91 20 #include "https_request.h"
Jan Jongboom 34:6daf67a96a91 21 #include "test_setup.h"
Jan Jongboom 34:6daf67a96a91 22 #include "utest/utest.h"
Jan Jongboom 34:6daf67a96a91 23 #include "unity/unity.h"
Jan Jongboom 34:6daf67a96a91 24 #include "greentea-client/test_env.h"
Jan Jongboom 34:6daf67a96a91 25
Jan Jongboom 34:6daf67a96a91 26 using namespace utest::v1;
Jan Jongboom 34:6daf67a96a91 27
Jan Jongboom 34:6daf67a96a91 28 static NetworkInterface *network;
Jan Jongboom 34:6daf67a96a91 29
Jan Jongboom 34:6daf67a96a91 30 static void setup_verify_network() {
Jan Jongboom 34:6daf67a96a91 31 if (!network) network = connect_to_default_network_interface();
Jan Jongboom 34:6daf67a96a91 32 TEST_ASSERT_NOT_NULL(network);
Jan Jongboom 34:6daf67a96a91 33 }
Jan Jongboom 34:6daf67a96a91 34
Jan Jongboom 34:6daf67a96a91 35 // verifies that the header is present and has a certain value
Jan Jongboom 34:6daf67a96a91 36 static void assert_header(HttpResponse *res, const char *header, const char *value) {
Jan Jongboom 34:6daf67a96a91 37 bool headerPresent = false;
Jan Jongboom 34:6daf67a96a91 38 for (size_t ix = 0; ix < res->get_headers_length(); ix++) {
Jan Jongboom 34:6daf67a96a91 39 if (res->get_headers_fields()[ix]->compare(header)) {
Jan Jongboom 34:6daf67a96a91 40 headerPresent = true;
Jan Jongboom 34:6daf67a96a91 41
Jan Jongboom 34:6daf67a96a91 42 TEST_ASSERT(res->get_headers_values()[ix]->compare(value));
Jan Jongboom 34:6daf67a96a91 43 }
Jan Jongboom 34:6daf67a96a91 44 }
Jan Jongboom 34:6daf67a96a91 45 TEST_ASSERT_EQUAL(true, headerPresent);
Jan Jongboom 34:6daf67a96a91 46 }
Jan Jongboom 34:6daf67a96a91 47
Jan Jongboom 34:6daf67a96a91 48 static control_t http_get(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 49 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 50
Jan Jongboom 34:6daf67a96a91 51 HttpRequest *req = new HttpRequest(network, HTTP_GET, "http://httpbin.org/status/418");
Jan Jongboom 34:6daf67a96a91 52
Jan Jongboom 34:6daf67a96a91 53 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 54 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 55 TEST_ASSERT_EQUAL(418, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 56
Jan Jongboom 34:6daf67a96a91 57 delete req;
Jan Jongboom 34:6daf67a96a91 58
Jan Jongboom 34:6daf67a96a91 59 return CaseNext;
Jan Jongboom 34:6daf67a96a91 60 }
Jan Jongboom 34:6daf67a96a91 61
Jan Jongboom 34:6daf67a96a91 62 static control_t http_post(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 63 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 64
Jan Jongboom 34:6daf67a96a91 65 HttpRequest* req = new HttpRequest(network, HTTP_POST, "http://httpbin.org/post");
Jan Jongboom 34:6daf67a96a91 66 req->set_header("Content-Type", "application/json");
Jan Jongboom 34:6daf67a96a91 67
Jan Jongboom 34:6daf67a96a91 68 const char body[] = "{\"mykey\":\"mbedvalue\"}";
Jan Jongboom 34:6daf67a96a91 69
Jan Jongboom 34:6daf67a96a91 70 HttpResponse* res = req->send(body, strlen(body));
Jan Jongboom 34:6daf67a96a91 71 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 72 TEST_ASSERT_EQUAL(200, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 73
Jan Jongboom 34:6daf67a96a91 74 // verify that the Content-Type header is present, and set to application/json
Jan Jongboom 34:6daf67a96a91 75 assert_header(res, "Content-Type", "application/json");
Jan Jongboom 34:6daf67a96a91 76
Jan Jongboom 34:6daf67a96a91 77 // verify that both the key and value are present in the response
Jan Jongboom 34:6daf67a96a91 78 TEST_ASSERT(res->get_body_length() > 0);
Jan Jongboom 34:6daf67a96a91 79 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("mykey"), string::npos);
Jan Jongboom 34:6daf67a96a91 80 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("mbedvalue"), string::npos);
Jan Jongboom 34:6daf67a96a91 81
Jan Jongboom 34:6daf67a96a91 82 delete req;
Jan Jongboom 34:6daf67a96a91 83
Jan Jongboom 34:6daf67a96a91 84 return CaseNext;
Jan Jongboom 34:6daf67a96a91 85 }
Jan Jongboom 34:6daf67a96a91 86
Jan Jongboom 34:6daf67a96a91 87 static control_t http_socket_reuse(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 88 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 89
Jan Jongboom 34:6daf67a96a91 90 TCPSocket socket;
Jan Jongboom 34:6daf67a96a91 91 nsapi_error_t open_result = socket.open(network);
Jan Jongboom 34:6daf67a96a91 92 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, open_result);
Jan Jongboom 34:6daf67a96a91 93
Jan Jongboom 34:6daf67a96a91 94 nsapi_error_t connect_result = socket.connect("httpbin.org", 80);
Jan Jongboom 34:6daf67a96a91 95 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, connect_result);
Jan Jongboom 34:6daf67a96a91 96
Jan Jongboom 34:6daf67a96a91 97 {
Jan Jongboom 34:6daf67a96a91 98 HttpRequest *req = new HttpRequest(&socket, HTTP_GET, "http://httpbin.org/status/404");
Jan Jongboom 34:6daf67a96a91 99
Jan Jongboom 34:6daf67a96a91 100 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 101 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 102 TEST_ASSERT_EQUAL(404, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 103
Jan Jongboom 34:6daf67a96a91 104 delete req;
Jan Jongboom 34:6daf67a96a91 105 }
Jan Jongboom 34:6daf67a96a91 106
Jan Jongboom 34:6daf67a96a91 107 {
Jan Jongboom 34:6daf67a96a91 108 HttpRequest *req = new HttpRequest(&socket, HTTP_GET, "http://httpbin.org/status/403");
Jan Jongboom 34:6daf67a96a91 109
Jan Jongboom 34:6daf67a96a91 110 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 111 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 112 TEST_ASSERT_EQUAL(403, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 113
Jan Jongboom 34:6daf67a96a91 114 delete req;
Jan Jongboom 34:6daf67a96a91 115 }
Jan Jongboom 34:6daf67a96a91 116
Jan Jongboom 34:6daf67a96a91 117 return CaseNext;
Jan Jongboom 34:6daf67a96a91 118 }
Jan Jongboom 34:6daf67a96a91 119
Jan Jongboom 34:6daf67a96a91 120 static control_t https_get(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 121 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 122
Jan Jongboom 34:6daf67a96a91 123 HttpsRequest *req = new HttpsRequest(network, SSL_CA_PEM, HTTP_GET, "https://os.mbed.com/media/uploads/mbed_official/hello.txt");
Jan Jongboom 34:6daf67a96a91 124
Jan Jongboom 34:6daf67a96a91 125 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 126 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 127 TEST_ASSERT_EQUAL(200, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 128 TEST_ASSERT(res->get_body_length() > 0);
Jan Jongboom 34:6daf67a96a91 129 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("Hello world!"), string::npos);
Jan Jongboom 34:6daf67a96a91 130
Jan Jongboom 34:6daf67a96a91 131 delete req;
Jan Jongboom 34:6daf67a96a91 132
Jan Jongboom 34:6daf67a96a91 133 return CaseNext;
Jan Jongboom 34:6daf67a96a91 134 }
Jan Jongboom 34:6daf67a96a91 135
Jan Jongboom 34:6daf67a96a91 136 static control_t https_post(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 137 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 138
Jan Jongboom 34:6daf67a96a91 139 HttpsRequest* req = new HttpsRequest(network, SSL_CA_PEM, HTTP_POST, "https://httpbin.org/post");
Jan Jongboom 34:6daf67a96a91 140 req->set_header("Content-Type", "application/json");
Jan Jongboom 34:6daf67a96a91 141
Jan Jongboom 34:6daf67a96a91 142 const char body[] = "{\"myhttpskey\":\"janjanjan\"}";
Jan Jongboom 34:6daf67a96a91 143
Jan Jongboom 34:6daf67a96a91 144 HttpResponse* res = req->send(body, strlen(body));
Jan Jongboom 34:6daf67a96a91 145 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 146 TEST_ASSERT_EQUAL(200, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 147
Jan Jongboom 34:6daf67a96a91 148 // verify that the Content-Type header is present, and set to application/json
Jan Jongboom 34:6daf67a96a91 149 assert_header(res, "Content-Type", "application/json");
Jan Jongboom 34:6daf67a96a91 150
Jan Jongboom 34:6daf67a96a91 151 // verify that both the key and value are present in the response
Jan Jongboom 34:6daf67a96a91 152 TEST_ASSERT(res->get_body_length() > 0);
Jan Jongboom 34:6daf67a96a91 153 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("myhttpskey"), string::npos);
Jan Jongboom 34:6daf67a96a91 154 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("janjanjan"), string::npos);
Jan Jongboom 34:6daf67a96a91 155
Jan Jongboom 34:6daf67a96a91 156 delete req;
Jan Jongboom 34:6daf67a96a91 157
Jan Jongboom 34:6daf67a96a91 158 return CaseNext;
Jan Jongboom 34:6daf67a96a91 159 }
Jan Jongboom 34:6daf67a96a91 160
Jan Jongboom 34:6daf67a96a91 161 static control_t https_socket_reuse(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 162 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 163
Jan Jongboom 34:6daf67a96a91 164 TLSSocket socket;
Jan Jongboom 34:6daf67a96a91 165 nsapi_error_t open_result = socket.open(network);
Jan Jongboom 34:6daf67a96a91 166 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, open_result);
Jan Jongboom 34:6daf67a96a91 167
Jan Jongboom 34:6daf67a96a91 168 nsapi_error_t ca_result = socket.set_root_ca_cert(SSL_CA_PEM);
Jan Jongboom 34:6daf67a96a91 169 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, ca_result);
Jan Jongboom 34:6daf67a96a91 170
Jan Jongboom 34:6daf67a96a91 171 nsapi_error_t connect_result = socket.connect("httpbin.org", 443);
Jan Jongboom 34:6daf67a96a91 172 TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, connect_result);
Jan Jongboom 34:6daf67a96a91 173
Jan Jongboom 34:6daf67a96a91 174 {
Jan Jongboom 34:6daf67a96a91 175 HttpsRequest *req = new HttpsRequest(&socket, HTTP_GET, "http://httpbin.org/status/404");
Jan Jongboom 34:6daf67a96a91 176
Jan Jongboom 34:6daf67a96a91 177 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 178 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 179 TEST_ASSERT_EQUAL(404, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 180
Jan Jongboom 34:6daf67a96a91 181 delete req;
Jan Jongboom 34:6daf67a96a91 182 }
Jan Jongboom 34:6daf67a96a91 183
Jan Jongboom 34:6daf67a96a91 184 {
Jan Jongboom 34:6daf67a96a91 185 HttpsRequest *req = new HttpsRequest(&socket, HTTP_GET, "http://httpbin.org/status/403");
Jan Jongboom 34:6daf67a96a91 186
Jan Jongboom 34:6daf67a96a91 187 HttpResponse* res = req->send();
Jan Jongboom 34:6daf67a96a91 188 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 189 TEST_ASSERT_EQUAL(403, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 190
Jan Jongboom 34:6daf67a96a91 191 delete req;
Jan Jongboom 34:6daf67a96a91 192 }
Jan Jongboom 34:6daf67a96a91 193
Jan Jongboom 34:6daf67a96a91 194 return CaseNext;
Jan Jongboom 34:6daf67a96a91 195 }
Jan Jongboom 34:6daf67a96a91 196
Jan Jongboom 34:6daf67a96a91 197 // Spread the message out over 3 different chunks
Jan Jongboom 34:6daf67a96a91 198 const char * chunks[] = {
Jan Jongboom 34:6daf67a96a91 199 "{\"message\":",
Jan Jongboom 34:6daf67a96a91 200 "\"this is an example",
Jan Jongboom 34:6daf67a96a91 201 " of chunked encoding\"}"
Jan Jongboom 34:6daf67a96a91 202 };
Jan Jongboom 34:6daf67a96a91 203
Jan Jongboom 34:6daf67a96a91 204 int chunk_ix = 0;
Jan Jongboom 34:6daf67a96a91 205
Jan Jongboom 34:6daf67a96a91 206 // Callback function, grab the next chunk and return it
Jan Jongboom 34:6daf67a96a91 207 const void * get_chunk(uint32_t* out_size) {
Jan Jongboom 34:6daf67a96a91 208 // If you don't have any data left, set out_size to 0 and return a null pointer
Jan Jongboom 34:6daf67a96a91 209 if (chunk_ix == (sizeof(chunks) / sizeof(chunks[0]))) {
Jan Jongboom 34:6daf67a96a91 210 *out_size = 0;
Jan Jongboom 34:6daf67a96a91 211 return NULL;
Jan Jongboom 34:6daf67a96a91 212 }
Jan Jongboom 34:6daf67a96a91 213 const char *chunk = chunks[chunk_ix];
Jan Jongboom 34:6daf67a96a91 214 *out_size = strlen(chunk);
Jan Jongboom 34:6daf67a96a91 215 chunk_ix++;
Jan Jongboom 34:6daf67a96a91 216
Jan Jongboom 34:6daf67a96a91 217 return chunk;
Jan Jongboom 34:6daf67a96a91 218 }
Jan Jongboom 34:6daf67a96a91 219
Jan Jongboom 34:6daf67a96a91 220 static control_t chunked_request(const size_t call_count) {
Jan Jongboom 34:6daf67a96a91 221 setup_verify_network();
Jan Jongboom 34:6daf67a96a91 222
Jan Jongboom 34:6daf67a96a91 223 HttpsRequest *req = new HttpsRequest(network, SSL_CA_PEM, HTTP_POST, "https://reqres.in/api/users");
Jan Jongboom 34:6daf67a96a91 224 req->set_header("Content-Type", "application/json");
Jan Jongboom 34:6daf67a96a91 225
Jan Jongboom 34:6daf67a96a91 226 HttpResponse* res = req->send(&get_chunk);
Jan Jongboom 34:6daf67a96a91 227 TEST_ASSERT(res);
Jan Jongboom 34:6daf67a96a91 228 TEST_ASSERT_EQUAL(201, res->get_status_code());
Jan Jongboom 34:6daf67a96a91 229 TEST_ASSERT(res->get_body_length() > 0);
Jan Jongboom 34:6daf67a96a91 230 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("message"), string::npos);
Jan Jongboom 34:6daf67a96a91 231 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("this is an example of chunked encoding"), string::npos);
Jan Jongboom 34:6daf67a96a91 232 TEST_ASSERT_NOT_EQUAL(res->get_body_as_string().find("createdAt"), string::npos);
Jan Jongboom 34:6daf67a96a91 233
Jan Jongboom 34:6daf67a96a91 234 delete req;
Jan Jongboom 34:6daf67a96a91 235
Jan Jongboom 34:6daf67a96a91 236 return CaseNext;
Jan Jongboom 34:6daf67a96a91 237 }
Jan Jongboom 34:6daf67a96a91 238
Jan Jongboom 34:6daf67a96a91 239 utest::v1::status_t greentea_setup(const size_t number_of_cases) {
Jan Jongboom 34:6daf67a96a91 240 GREENTEA_SETUP(1*60, "default_auto");
Jan Jongboom 34:6daf67a96a91 241 return greentea_test_setup_handler(number_of_cases);
Jan Jongboom 34:6daf67a96a91 242 }
Jan Jongboom 34:6daf67a96a91 243
Jan Jongboom 34:6daf67a96a91 244 Case cases[] = {
Jan Jongboom 34:6daf67a96a91 245 Case("http get", http_get),
Jan Jongboom 34:6daf67a96a91 246 Case("http post", http_post),
Jan Jongboom 34:6daf67a96a91 247 Case("http socket reuse", http_socket_reuse),
Jan Jongboom 34:6daf67a96a91 248 Case("https get", https_get),
Jan Jongboom 34:6daf67a96a91 249 Case("https post", https_post),
Jan Jongboom 34:6daf67a96a91 250 Case("https socket reuse", https_socket_reuse),
Jan Jongboom 34:6daf67a96a91 251 Case("chunked request", chunked_request)
Jan Jongboom 34:6daf67a96a91 252 };
Jan Jongboom 34:6daf67a96a91 253
Jan Jongboom 34:6daf67a96a91 254 Specification specification(greentea_setup, cases);
Jan Jongboom 34:6daf67a96a91 255
Jan Jongboom 34:6daf67a96a91 256 void blink_led() {
Jan Jongboom 34:6daf67a96a91 257 static DigitalOut led(LED1);
Jan Jongboom 34:6daf67a96a91 258 led = !led;
Jan Jongboom 34:6daf67a96a91 259 }
Jan Jongboom 34:6daf67a96a91 260
Jan Jongboom 34:6daf67a96a91 261 int main() {
Jan Jongboom 34:6daf67a96a91 262 Ticker t;
Jan Jongboom 34:6daf67a96a91 263 t.attach(blink_led, 0.5);
Jan Jongboom 34:6daf67a96a91 264
Jan Jongboom 34:6daf67a96a91 265 return !Harness::run(specification);
Jan Jongboom 34:6daf67a96a91 266 }