HTTP and HTTPS example application for Mbed OS 5

Dependencies:   mbed-http

This application demonstrates how to make HTTP and HTTPS requests and parse the response from Mbed OS 5.

It consists of six example applications, which you can select in source/select-demo.h:

Response parsing is done through nodejs/http-parser.

Note: HTTPS requests do not work on targets with less than 128K of RAM due to the size of the TLS handshake. For more background see mbed-http.

To build

  1. If you're using WiFi, specify the credentials in mbed_app.json.
  2. Build the project in the online compiler or using Mbed CLI.
  3. Flash the project to your development board.
  4. Attach a serial monitor to your board to see the debug messages.

Defining the network interface

This application uses the on-board network interface for your board. If you use an external network interface (f.e. a WiFi module) you need to add the driver to this project. Then, open network-helper.h and specify which network driver to use.

More information is in the Mbed OS documentation under IP Networking.

Entropy (or lack thereof)

On all platforms that do not have the TRNG feature, the application is compiled without TLS entropy sources. This means that your code is inherently unsafe and should not be deployed to any production systems. To enable entropy, remove the MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES and MBEDTLS_TEST_NULL_ENTROPY macros from mbed_app.json.

Flash size

Default flash size for HTTPS is very large, as the application is loading the default Mbed TLS configuration. To use a more optimized version, you can disable unused cypher suites and other Mbed TLS features with a custom configuration file. Create a new configuration file, then add in mbed_app.json:

"MBEDTLS_CONFIG_FILE=\"mbedtls_config.h\""

to the macros array.

Running tests

You can run the integration tests from this project via Mbed CLI.

  1. In select-demo.h set the DEMO macro to DEMO_TESTS.
  2. Set your WiFi credentials in mbed_app.json.
  3. Then run the tests via:

$ mbed test -v -n mbed-http-tests-tests-*

Tested on

  • K64F with Ethernet.
  • NUCLEO_F411RE with ESP8266 (not working on Mbed OS 5.12+)
  • ODIN-W2 with WiFi.
  • K64F with Atmel 6LoWPAN shield.
  • DISCO-L475VG-IOT01A with WiFi (requires the wifi-ism43362 driver).
Committer:
Jan Jongboom
Date:
Wed Feb 15 21:57:31 2017 +0100
Revision:
0:85fdc69bc10c
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jan Jongboom 0:85fdc69bc10c 1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
Jan Jongboom 0:85fdc69bc10c 2 *
Jan Jongboom 0:85fdc69bc10c 3 * Permission is hereby granted, free of charge, to any person obtaining a copy
Jan Jongboom 0:85fdc69bc10c 4 * of this software and associated documentation files (the "Software"), to
Jan Jongboom 0:85fdc69bc10c 5 * deal in the Software without restriction, including without limitation the
Jan Jongboom 0:85fdc69bc10c 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Jan Jongboom 0:85fdc69bc10c 7 * sell copies of the Software, and to permit persons to whom the Software is
Jan Jongboom 0:85fdc69bc10c 8 * furnished to do so, subject to the following conditions:
Jan Jongboom 0:85fdc69bc10c 9 *
Jan Jongboom 0:85fdc69bc10c 10 * The above copyright notice and this permission notice shall be included in
Jan Jongboom 0:85fdc69bc10c 11 * all copies or substantial portions of the Software.
Jan Jongboom 0:85fdc69bc10c 12 *
Jan Jongboom 0:85fdc69bc10c 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jan Jongboom 0:85fdc69bc10c 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Jan Jongboom 0:85fdc69bc10c 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
Jan Jongboom 0:85fdc69bc10c 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
Jan Jongboom 0:85fdc69bc10c 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
Jan Jongboom 0:85fdc69bc10c 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
Jan Jongboom 0:85fdc69bc10c 19 * IN THE SOFTWARE.
Jan Jongboom 0:85fdc69bc10c 20 */
Jan Jongboom 0:85fdc69bc10c 21 #ifndef http_parser_h
Jan Jongboom 0:85fdc69bc10c 22 #define http_parser_h
Jan Jongboom 0:85fdc69bc10c 23 #ifdef __cplusplus
Jan Jongboom 0:85fdc69bc10c 24 extern "C" {
Jan Jongboom 0:85fdc69bc10c 25 #endif
Jan Jongboom 0:85fdc69bc10c 26
Jan Jongboom 0:85fdc69bc10c 27 /* Also update SONAME in the Makefile whenever you change these. */
Jan Jongboom 0:85fdc69bc10c 28 #define HTTP_PARSER_VERSION_MAJOR 2
Jan Jongboom 0:85fdc69bc10c 29 #define HTTP_PARSER_VERSION_MINOR 7
Jan Jongboom 0:85fdc69bc10c 30 #define HTTP_PARSER_VERSION_PATCH 1
Jan Jongboom 0:85fdc69bc10c 31
Jan Jongboom 0:85fdc69bc10c 32 #include <sys/types.h>
Jan Jongboom 0:85fdc69bc10c 33 #if defined(_WIN32) && !defined(__MINGW32__) && \
Jan Jongboom 0:85fdc69bc10c 34 (!defined(_MSC_VER) || _MSC_VER<1600) && !defined(__WINE__)
Jan Jongboom 0:85fdc69bc10c 35 #include <BaseTsd.h>
Jan Jongboom 0:85fdc69bc10c 36 #include <stddef.h>
Jan Jongboom 0:85fdc69bc10c 37 typedef __int8 int8_t;
Jan Jongboom 0:85fdc69bc10c 38 typedef unsigned __int8 uint8_t;
Jan Jongboom 0:85fdc69bc10c 39 typedef __int16 int16_t;
Jan Jongboom 0:85fdc69bc10c 40 typedef unsigned __int16 uint16_t;
Jan Jongboom 0:85fdc69bc10c 41 typedef __int32 int32_t;
Jan Jongboom 0:85fdc69bc10c 42 typedef unsigned __int32 uint32_t;
Jan Jongboom 0:85fdc69bc10c 43 typedef __int64 int64_t;
Jan Jongboom 0:85fdc69bc10c 44 typedef unsigned __int64 uint64_t;
Jan Jongboom 0:85fdc69bc10c 45 #else
Jan Jongboom 0:85fdc69bc10c 46 #include <stdint.h>
Jan Jongboom 0:85fdc69bc10c 47 #endif
Jan Jongboom 0:85fdc69bc10c 48
Jan Jongboom 0:85fdc69bc10c 49 /* Compile with -DHTTP_PARSER_STRICT=0 to make less checks, but run
Jan Jongboom 0:85fdc69bc10c 50 * faster
Jan Jongboom 0:85fdc69bc10c 51 */
Jan Jongboom 0:85fdc69bc10c 52 #ifndef HTTP_PARSER_STRICT
Jan Jongboom 0:85fdc69bc10c 53 # define HTTP_PARSER_STRICT 1
Jan Jongboom 0:85fdc69bc10c 54 #endif
Jan Jongboom 0:85fdc69bc10c 55
Jan Jongboom 0:85fdc69bc10c 56 /* Maximium header size allowed. If the macro is not defined
Jan Jongboom 0:85fdc69bc10c 57 * before including this header then the default is used. To
Jan Jongboom 0:85fdc69bc10c 58 * change the maximum header size, define the macro in the build
Jan Jongboom 0:85fdc69bc10c 59 * environment (e.g. -DHTTP_MAX_HEADER_SIZE=<value>). To remove
Jan Jongboom 0:85fdc69bc10c 60 * the effective limit on the size of the header, define the macro
Jan Jongboom 0:85fdc69bc10c 61 * to a very large number (e.g. -DHTTP_MAX_HEADER_SIZE=0x7fffffff)
Jan Jongboom 0:85fdc69bc10c 62 */
Jan Jongboom 0:85fdc69bc10c 63 #ifndef HTTP_MAX_HEADER_SIZE
Jan Jongboom 0:85fdc69bc10c 64 # define HTTP_MAX_HEADER_SIZE (80*1024)
Jan Jongboom 0:85fdc69bc10c 65 #endif
Jan Jongboom 0:85fdc69bc10c 66
Jan Jongboom 0:85fdc69bc10c 67 typedef struct http_parser http_parser;
Jan Jongboom 0:85fdc69bc10c 68 typedef struct http_parser_settings http_parser_settings;
Jan Jongboom 0:85fdc69bc10c 69
Jan Jongboom 0:85fdc69bc10c 70
Jan Jongboom 0:85fdc69bc10c 71 /* Callbacks should return non-zero to indicate an error. The parser will
Jan Jongboom 0:85fdc69bc10c 72 * then halt execution.
Jan Jongboom 0:85fdc69bc10c 73 *
Jan Jongboom 0:85fdc69bc10c 74 * The one exception is on_headers_complete. In a HTTP_RESPONSE parser
Jan Jongboom 0:85fdc69bc10c 75 * returning '1' from on_headers_complete will tell the parser that it
Jan Jongboom 0:85fdc69bc10c 76 * should not expect a body. This is used when receiving a response to a
Jan Jongboom 0:85fdc69bc10c 77 * HEAD request which may contain 'Content-Length' or 'Transfer-Encoding:
Jan Jongboom 0:85fdc69bc10c 78 * chunked' headers that indicate the presence of a body.
Jan Jongboom 0:85fdc69bc10c 79 *
Jan Jongboom 0:85fdc69bc10c 80 * Returning `2` from on_headers_complete will tell parser that it should not
Jan Jongboom 0:85fdc69bc10c 81 * expect neither a body nor any futher responses on this connection. This is
Jan Jongboom 0:85fdc69bc10c 82 * useful for handling responses to a CONNECT request which may not contain
Jan Jongboom 0:85fdc69bc10c 83 * `Upgrade` or `Connection: upgrade` headers.
Jan Jongboom 0:85fdc69bc10c 84 *
Jan Jongboom 0:85fdc69bc10c 85 * http_data_cb does not return data chunks. It will be called arbitrarily
Jan Jongboom 0:85fdc69bc10c 86 * many times for each string. E.G. you might get 10 callbacks for "on_url"
Jan Jongboom 0:85fdc69bc10c 87 * each providing just a few characters more data.
Jan Jongboom 0:85fdc69bc10c 88 */
Jan Jongboom 0:85fdc69bc10c 89 typedef int (*http_data_cb) (http_parser*, const char *at, size_t length);
Jan Jongboom 0:85fdc69bc10c 90 typedef int (*http_cb) (http_parser*);
Jan Jongboom 0:85fdc69bc10c 91
Jan Jongboom 0:85fdc69bc10c 92
Jan Jongboom 0:85fdc69bc10c 93 /* Status Codes */
Jan Jongboom 0:85fdc69bc10c 94 #define HTTP_STATUS_MAP(XX) \
Jan Jongboom 0:85fdc69bc10c 95 XX(100, CONTINUE, Continue) \
Jan Jongboom 0:85fdc69bc10c 96 XX(101, SWITCHING_PROTOCOLS, Switching Protocols) \
Jan Jongboom 0:85fdc69bc10c 97 XX(102, PROCESSING, Processing) \
Jan Jongboom 0:85fdc69bc10c 98 XX(200, OK, OK) \
Jan Jongboom 0:85fdc69bc10c 99 XX(201, CREATED, Created) \
Jan Jongboom 0:85fdc69bc10c 100 XX(202, ACCEPTED, Accepted) \
Jan Jongboom 0:85fdc69bc10c 101 XX(203, NON_AUTHORITATIVE_INFORMATION, Non-Authoritative Information) \
Jan Jongboom 0:85fdc69bc10c 102 XX(204, NO_CONTENT, No Content) \
Jan Jongboom 0:85fdc69bc10c 103 XX(205, RESET_CONTENT, Reset Content) \
Jan Jongboom 0:85fdc69bc10c 104 XX(206, PARTIAL_CONTENT, Partial Content) \
Jan Jongboom 0:85fdc69bc10c 105 XX(207, MULTI_STATUS, Multi-Status) \
Jan Jongboom 0:85fdc69bc10c 106 XX(208, ALREADY_REPORTED, Already Reported) \
Jan Jongboom 0:85fdc69bc10c 107 XX(226, IM_USED, IM Used) \
Jan Jongboom 0:85fdc69bc10c 108 XX(300, MULTIPLE_CHOICES, Multiple Choices) \
Jan Jongboom 0:85fdc69bc10c 109 XX(301, MOVED_PERMANENTLY, Moved Permanently) \
Jan Jongboom 0:85fdc69bc10c 110 XX(302, FOUND, Found) \
Jan Jongboom 0:85fdc69bc10c 111 XX(303, SEE_OTHER, See Other) \
Jan Jongboom 0:85fdc69bc10c 112 XX(304, NOT_MODIFIED, Not Modified) \
Jan Jongboom 0:85fdc69bc10c 113 XX(305, USE_PROXY, Use Proxy) \
Jan Jongboom 0:85fdc69bc10c 114 XX(307, TEMPORARY_REDIRECT, Temporary Redirect) \
Jan Jongboom 0:85fdc69bc10c 115 XX(308, PERMANENT_REDIRECT, Permanent Redirect) \
Jan Jongboom 0:85fdc69bc10c 116 XX(400, BAD_REQUEST, Bad Request) \
Jan Jongboom 0:85fdc69bc10c 117 XX(401, UNAUTHORIZED, Unauthorized) \
Jan Jongboom 0:85fdc69bc10c 118 XX(402, PAYMENT_REQUIRED, Payment Required) \
Jan Jongboom 0:85fdc69bc10c 119 XX(403, FORBIDDEN, Forbidden) \
Jan Jongboom 0:85fdc69bc10c 120 XX(404, NOT_FOUND, Not Found) \
Jan Jongboom 0:85fdc69bc10c 121 XX(405, METHOD_NOT_ALLOWED, Method Not Allowed) \
Jan Jongboom 0:85fdc69bc10c 122 XX(406, NOT_ACCEPTABLE, Not Acceptable) \
Jan Jongboom 0:85fdc69bc10c 123 XX(407, PROXY_AUTHENTICATION_REQUIRED, Proxy Authentication Required) \
Jan Jongboom 0:85fdc69bc10c 124 XX(408, REQUEST_TIMEOUT, Request Timeout) \
Jan Jongboom 0:85fdc69bc10c 125 XX(409, CONFLICT, Conflict) \
Jan Jongboom 0:85fdc69bc10c 126 XX(410, GONE, Gone) \
Jan Jongboom 0:85fdc69bc10c 127 XX(411, LENGTH_REQUIRED, Length Required) \
Jan Jongboom 0:85fdc69bc10c 128 XX(412, PRECONDITION_FAILED, Precondition Failed) \
Jan Jongboom 0:85fdc69bc10c 129 XX(413, PAYLOAD_TOO_LARGE, Payload Too Large) \
Jan Jongboom 0:85fdc69bc10c 130 XX(414, URI_TOO_LONG, URI Too Long) \
Jan Jongboom 0:85fdc69bc10c 131 XX(415, UNSUPPORTED_MEDIA_TYPE, Unsupported Media Type) \
Jan Jongboom 0:85fdc69bc10c 132 XX(416, RANGE_NOT_SATISFIABLE, Range Not Satisfiable) \
Jan Jongboom 0:85fdc69bc10c 133 XX(417, EXPECTATION_FAILED, Expectation Failed) \
Jan Jongboom 0:85fdc69bc10c 134 XX(421, MISDIRECTED_REQUEST, Misdirected Request) \
Jan Jongboom 0:85fdc69bc10c 135 XX(422, UNPROCESSABLE_ENTITY, Unprocessable Entity) \
Jan Jongboom 0:85fdc69bc10c 136 XX(423, LOCKED, Locked) \
Jan Jongboom 0:85fdc69bc10c 137 XX(424, FAILED_DEPENDENCY, Failed Dependency) \
Jan Jongboom 0:85fdc69bc10c 138 XX(426, UPGRADE_REQUIRED, Upgrade Required) \
Jan Jongboom 0:85fdc69bc10c 139 XX(428, PRECONDITION_REQUIRED, Precondition Required) \
Jan Jongboom 0:85fdc69bc10c 140 XX(429, TOO_MANY_REQUESTS, Too Many Requests) \
Jan Jongboom 0:85fdc69bc10c 141 XX(431, REQUEST_HEADER_FIELDS_TOO_LARGE, Request Header Fields Too Large) \
Jan Jongboom 0:85fdc69bc10c 142 XX(451, UNAVAILABLE_FOR_LEGAL_REASONS, Unavailable For Legal Reasons) \
Jan Jongboom 0:85fdc69bc10c 143 XX(500, INTERNAL_SERVER_ERROR, Internal Server Error) \
Jan Jongboom 0:85fdc69bc10c 144 XX(501, NOT_IMPLEMENTED, Not Implemented) \
Jan Jongboom 0:85fdc69bc10c 145 XX(502, BAD_GATEWAY, Bad Gateway) \
Jan Jongboom 0:85fdc69bc10c 146 XX(503, SERVICE_UNAVAILABLE, Service Unavailable) \
Jan Jongboom 0:85fdc69bc10c 147 XX(504, GATEWAY_TIMEOUT, Gateway Timeout) \
Jan Jongboom 0:85fdc69bc10c 148 XX(505, HTTP_VERSION_NOT_SUPPORTED, HTTP Version Not Supported) \
Jan Jongboom 0:85fdc69bc10c 149 XX(506, VARIANT_ALSO_NEGOTIATES, Variant Also Negotiates) \
Jan Jongboom 0:85fdc69bc10c 150 XX(507, INSUFFICIENT_STORAGE, Insufficient Storage) \
Jan Jongboom 0:85fdc69bc10c 151 XX(508, LOOP_DETECTED, Loop Detected) \
Jan Jongboom 0:85fdc69bc10c 152 XX(510, NOT_EXTENDED, Not Extended) \
Jan Jongboom 0:85fdc69bc10c 153 XX(511, NETWORK_AUTHENTICATION_REQUIRED, Network Authentication Required) \
Jan Jongboom 0:85fdc69bc10c 154
Jan Jongboom 0:85fdc69bc10c 155 enum http_status
Jan Jongboom 0:85fdc69bc10c 156 {
Jan Jongboom 0:85fdc69bc10c 157 #define XX(num, name, string) HTTP_STATUS_##name = num,
Jan Jongboom 0:85fdc69bc10c 158 HTTP_STATUS_MAP(XX)
Jan Jongboom 0:85fdc69bc10c 159 #undef XX
Jan Jongboom 0:85fdc69bc10c 160 };
Jan Jongboom 0:85fdc69bc10c 161
Jan Jongboom 0:85fdc69bc10c 162
Jan Jongboom 0:85fdc69bc10c 163 /* Request Methods */
Jan Jongboom 0:85fdc69bc10c 164 #define HTTP_METHOD_MAP(XX) \
Jan Jongboom 0:85fdc69bc10c 165 XX(0, DELETE, DELETE) \
Jan Jongboom 0:85fdc69bc10c 166 XX(1, GET, GET) \
Jan Jongboom 0:85fdc69bc10c 167 XX(2, HEAD, HEAD) \
Jan Jongboom 0:85fdc69bc10c 168 XX(3, POST, POST) \
Jan Jongboom 0:85fdc69bc10c 169 XX(4, PUT, PUT) \
Jan Jongboom 0:85fdc69bc10c 170 /* pathological */ \
Jan Jongboom 0:85fdc69bc10c 171 XX(5, CONNECT, CONNECT) \
Jan Jongboom 0:85fdc69bc10c 172 XX(6, OPTIONS, OPTIONS) \
Jan Jongboom 0:85fdc69bc10c 173 XX(7, TRACE, TRACE) \
Jan Jongboom 0:85fdc69bc10c 174 /* WebDAV */ \
Jan Jongboom 0:85fdc69bc10c 175 XX(8, COPY, COPY) \
Jan Jongboom 0:85fdc69bc10c 176 XX(9, LOCK, LOCK) \
Jan Jongboom 0:85fdc69bc10c 177 XX(10, MKCOL, MKCOL) \
Jan Jongboom 0:85fdc69bc10c 178 XX(11, MOVE, MOVE) \
Jan Jongboom 0:85fdc69bc10c 179 XX(12, PROPFIND, PROPFIND) \
Jan Jongboom 0:85fdc69bc10c 180 XX(13, PROPPATCH, PROPPATCH) \
Jan Jongboom 0:85fdc69bc10c 181 XX(14, SEARCH, SEARCH) \
Jan Jongboom 0:85fdc69bc10c 182 XX(15, UNLOCK, UNLOCK) \
Jan Jongboom 0:85fdc69bc10c 183 XX(16, BIND, BIND) \
Jan Jongboom 0:85fdc69bc10c 184 XX(17, REBIND, REBIND) \
Jan Jongboom 0:85fdc69bc10c 185 XX(18, UNBIND, UNBIND) \
Jan Jongboom 0:85fdc69bc10c 186 XX(19, ACL, ACL) \
Jan Jongboom 0:85fdc69bc10c 187 /* subversion */ \
Jan Jongboom 0:85fdc69bc10c 188 XX(20, REPORT, REPORT) \
Jan Jongboom 0:85fdc69bc10c 189 XX(21, MKACTIVITY, MKACTIVITY) \
Jan Jongboom 0:85fdc69bc10c 190 XX(22, CHECKOUT, CHECKOUT) \
Jan Jongboom 0:85fdc69bc10c 191 XX(23, MERGE, MERGE) \
Jan Jongboom 0:85fdc69bc10c 192 /* upnp */ \
Jan Jongboom 0:85fdc69bc10c 193 XX(24, MSEARCH, M-SEARCH) \
Jan Jongboom 0:85fdc69bc10c 194 XX(25, NOTIFY, NOTIFY) \
Jan Jongboom 0:85fdc69bc10c 195 XX(26, SUBSCRIBE, SUBSCRIBE) \
Jan Jongboom 0:85fdc69bc10c 196 XX(27, UNSUBSCRIBE, UNSUBSCRIBE) \
Jan Jongboom 0:85fdc69bc10c 197 /* RFC-5789 */ \
Jan Jongboom 0:85fdc69bc10c 198 XX(28, PATCH, PATCH) \
Jan Jongboom 0:85fdc69bc10c 199 XX(29, PURGE, PURGE) \
Jan Jongboom 0:85fdc69bc10c 200 /* CalDAV */ \
Jan Jongboom 0:85fdc69bc10c 201 XX(30, MKCALENDAR, MKCALENDAR) \
Jan Jongboom 0:85fdc69bc10c 202 /* RFC-2068, section 19.6.1.2 */ \
Jan Jongboom 0:85fdc69bc10c 203 XX(31, LINK, LINK) \
Jan Jongboom 0:85fdc69bc10c 204 XX(32, UNLINK, UNLINK) \
Jan Jongboom 0:85fdc69bc10c 205
Jan Jongboom 0:85fdc69bc10c 206 enum http_method
Jan Jongboom 0:85fdc69bc10c 207 {
Jan Jongboom 0:85fdc69bc10c 208 #define XX(num, name, string) HTTP_##name = num,
Jan Jongboom 0:85fdc69bc10c 209 HTTP_METHOD_MAP(XX)
Jan Jongboom 0:85fdc69bc10c 210 #undef XX
Jan Jongboom 0:85fdc69bc10c 211 };
Jan Jongboom 0:85fdc69bc10c 212
Jan Jongboom 0:85fdc69bc10c 213
Jan Jongboom 0:85fdc69bc10c 214 enum http_parser_type { HTTP_REQUEST, HTTP_RESPONSE, HTTP_BOTH };
Jan Jongboom 0:85fdc69bc10c 215
Jan Jongboom 0:85fdc69bc10c 216
Jan Jongboom 0:85fdc69bc10c 217 /* Flag values for http_parser.flags field */
Jan Jongboom 0:85fdc69bc10c 218 enum flags
Jan Jongboom 0:85fdc69bc10c 219 { F_CHUNKED = 1 << 0
Jan Jongboom 0:85fdc69bc10c 220 , F_CONNECTION_KEEP_ALIVE = 1 << 1
Jan Jongboom 0:85fdc69bc10c 221 , F_CONNECTION_CLOSE = 1 << 2
Jan Jongboom 0:85fdc69bc10c 222 , F_CONNECTION_UPGRADE = 1 << 3
Jan Jongboom 0:85fdc69bc10c 223 , F_TRAILING = 1 << 4
Jan Jongboom 0:85fdc69bc10c 224 , F_UPGRADE = 1 << 5
Jan Jongboom 0:85fdc69bc10c 225 , F_SKIPBODY = 1 << 6
Jan Jongboom 0:85fdc69bc10c 226 , F_CONTENTLENGTH = 1 << 7
Jan Jongboom 0:85fdc69bc10c 227 };
Jan Jongboom 0:85fdc69bc10c 228
Jan Jongboom 0:85fdc69bc10c 229
Jan Jongboom 0:85fdc69bc10c 230 /* Map for errno-related constants
Jan Jongboom 0:85fdc69bc10c 231 *
Jan Jongboom 0:85fdc69bc10c 232 * The provided argument should be a macro that takes 2 arguments.
Jan Jongboom 0:85fdc69bc10c 233 */
Jan Jongboom 0:85fdc69bc10c 234 #define HTTP_ERRNO_MAP(XX) \
Jan Jongboom 0:85fdc69bc10c 235 /* No error */ \
Jan Jongboom 0:85fdc69bc10c 236 XX(OK, "success") \
Jan Jongboom 0:85fdc69bc10c 237 \
Jan Jongboom 0:85fdc69bc10c 238 /* Callback-related errors */ \
Jan Jongboom 0:85fdc69bc10c 239 XX(CB_message_begin, "the on_message_begin callback failed") \
Jan Jongboom 0:85fdc69bc10c 240 XX(CB_url, "the on_url callback failed") \
Jan Jongboom 0:85fdc69bc10c 241 XX(CB_header_field, "the on_header_field callback failed") \
Jan Jongboom 0:85fdc69bc10c 242 XX(CB_header_value, "the on_header_value callback failed") \
Jan Jongboom 0:85fdc69bc10c 243 XX(CB_headers_complete, "the on_headers_complete callback failed") \
Jan Jongboom 0:85fdc69bc10c 244 XX(CB_body, "the on_body callback failed") \
Jan Jongboom 0:85fdc69bc10c 245 XX(CB_message_complete, "the on_message_complete callback failed") \
Jan Jongboom 0:85fdc69bc10c 246 XX(CB_status, "the on_status callback failed") \
Jan Jongboom 0:85fdc69bc10c 247 XX(CB_chunk_header, "the on_chunk_header callback failed") \
Jan Jongboom 0:85fdc69bc10c 248 XX(CB_chunk_complete, "the on_chunk_complete callback failed") \
Jan Jongboom 0:85fdc69bc10c 249 \
Jan Jongboom 0:85fdc69bc10c 250 /* Parsing-related errors */ \
Jan Jongboom 0:85fdc69bc10c 251 XX(INVALID_EOF_STATE, "stream ended at an unexpected time") \
Jan Jongboom 0:85fdc69bc10c 252 XX(HEADER_OVERFLOW, \
Jan Jongboom 0:85fdc69bc10c 253 "too many header bytes seen; overflow detected") \
Jan Jongboom 0:85fdc69bc10c 254 XX(CLOSED_CONNECTION, \
Jan Jongboom 0:85fdc69bc10c 255 "data received after completed connection: close message") \
Jan Jongboom 0:85fdc69bc10c 256 XX(INVALID_VERSION, "invalid HTTP version") \
Jan Jongboom 0:85fdc69bc10c 257 XX(INVALID_STATUS, "invalid HTTP status code") \
Jan Jongboom 0:85fdc69bc10c 258 XX(INVALID_METHOD, "invalid HTTP method") \
Jan Jongboom 0:85fdc69bc10c 259 XX(INVALID_URL, "invalid URL") \
Jan Jongboom 0:85fdc69bc10c 260 XX(INVALID_HOST, "invalid host") \
Jan Jongboom 0:85fdc69bc10c 261 XX(INVALID_PORT, "invalid port") \
Jan Jongboom 0:85fdc69bc10c 262 XX(INVALID_PATH, "invalid path") \
Jan Jongboom 0:85fdc69bc10c 263 XX(INVALID_QUERY_STRING, "invalid query string") \
Jan Jongboom 0:85fdc69bc10c 264 XX(INVALID_FRAGMENT, "invalid fragment") \
Jan Jongboom 0:85fdc69bc10c 265 XX(LF_EXPECTED, "LF character expected") \
Jan Jongboom 0:85fdc69bc10c 266 XX(INVALID_HEADER_TOKEN, "invalid character in header") \
Jan Jongboom 0:85fdc69bc10c 267 XX(INVALID_CONTENT_LENGTH, \
Jan Jongboom 0:85fdc69bc10c 268 "invalid character in content-length header") \
Jan Jongboom 0:85fdc69bc10c 269 XX(UNEXPECTED_CONTENT_LENGTH, \
Jan Jongboom 0:85fdc69bc10c 270 "unexpected content-length header") \
Jan Jongboom 0:85fdc69bc10c 271 XX(INVALID_CHUNK_SIZE, \
Jan Jongboom 0:85fdc69bc10c 272 "invalid character in chunk size header") \
Jan Jongboom 0:85fdc69bc10c 273 XX(INVALID_CONSTANT, "invalid constant string") \
Jan Jongboom 0:85fdc69bc10c 274 XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
Jan Jongboom 0:85fdc69bc10c 275 XX(STRICT, "strict mode assertion failed") \
Jan Jongboom 0:85fdc69bc10c 276 XX(PAUSED, "parser is paused") \
Jan Jongboom 0:85fdc69bc10c 277 XX(UNKNOWN, "an unknown error occurred")
Jan Jongboom 0:85fdc69bc10c 278
Jan Jongboom 0:85fdc69bc10c 279
Jan Jongboom 0:85fdc69bc10c 280 /* Define HPE_* values for each errno value above */
Jan Jongboom 0:85fdc69bc10c 281 #define HTTP_ERRNO_GEN(n, s) HPE_##n,
Jan Jongboom 0:85fdc69bc10c 282 enum http_errno {
Jan Jongboom 0:85fdc69bc10c 283 HTTP_ERRNO_MAP(HTTP_ERRNO_GEN)
Jan Jongboom 0:85fdc69bc10c 284 };
Jan Jongboom 0:85fdc69bc10c 285 #undef HTTP_ERRNO_GEN
Jan Jongboom 0:85fdc69bc10c 286
Jan Jongboom 0:85fdc69bc10c 287
Jan Jongboom 0:85fdc69bc10c 288 /* Get an http_errno value from an http_parser */
Jan Jongboom 0:85fdc69bc10c 289 #define HTTP_PARSER_ERRNO(p) ((enum http_errno) (p)->http_errno)
Jan Jongboom 0:85fdc69bc10c 290
Jan Jongboom 0:85fdc69bc10c 291
Jan Jongboom 0:85fdc69bc10c 292 struct http_parser {
Jan Jongboom 0:85fdc69bc10c 293 /** PRIVATE **/
Jan Jongboom 0:85fdc69bc10c 294 unsigned int type : 2; /* enum http_parser_type */
Jan Jongboom 0:85fdc69bc10c 295 unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
Jan Jongboom 0:85fdc69bc10c 296 unsigned int state : 7; /* enum state from http_parser.c */
Jan Jongboom 0:85fdc69bc10c 297 unsigned int header_state : 7; /* enum header_state from http_parser.c */
Jan Jongboom 0:85fdc69bc10c 298 unsigned int index : 7; /* index into current matcher */
Jan Jongboom 0:85fdc69bc10c 299 unsigned int lenient_http_headers : 1;
Jan Jongboom 0:85fdc69bc10c 300
Jan Jongboom 0:85fdc69bc10c 301 uint32_t nread; /* # bytes read in various scenarios */
Jan Jongboom 0:85fdc69bc10c 302 uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */
Jan Jongboom 0:85fdc69bc10c 303
Jan Jongboom 0:85fdc69bc10c 304 /** READ-ONLY **/
Jan Jongboom 0:85fdc69bc10c 305 unsigned short http_major;
Jan Jongboom 0:85fdc69bc10c 306 unsigned short http_minor;
Jan Jongboom 0:85fdc69bc10c 307 unsigned int status_code : 16; /* responses only */
Jan Jongboom 0:85fdc69bc10c 308 unsigned int method : 8; /* requests only */
Jan Jongboom 0:85fdc69bc10c 309 unsigned int http_errno : 7;
Jan Jongboom 0:85fdc69bc10c 310
Jan Jongboom 0:85fdc69bc10c 311 /* 1 = Upgrade header was present and the parser has exited because of that.
Jan Jongboom 0:85fdc69bc10c 312 * 0 = No upgrade header present.
Jan Jongboom 0:85fdc69bc10c 313 * Should be checked when http_parser_execute() returns in addition to
Jan Jongboom 0:85fdc69bc10c 314 * error checking.
Jan Jongboom 0:85fdc69bc10c 315 */
Jan Jongboom 0:85fdc69bc10c 316 unsigned int upgrade : 1;
Jan Jongboom 0:85fdc69bc10c 317
Jan Jongboom 0:85fdc69bc10c 318 /** PUBLIC **/
Jan Jongboom 0:85fdc69bc10c 319 void *data; /* A pointer to get hook to the "connection" or "socket" object */
Jan Jongboom 0:85fdc69bc10c 320 };
Jan Jongboom 0:85fdc69bc10c 321
Jan Jongboom 0:85fdc69bc10c 322
Jan Jongboom 0:85fdc69bc10c 323 struct http_parser_settings {
Jan Jongboom 0:85fdc69bc10c 324 http_cb on_message_begin;
Jan Jongboom 0:85fdc69bc10c 325 http_data_cb on_url;
Jan Jongboom 0:85fdc69bc10c 326 http_data_cb on_status;
Jan Jongboom 0:85fdc69bc10c 327 http_data_cb on_header_field;
Jan Jongboom 0:85fdc69bc10c 328 http_data_cb on_header_value;
Jan Jongboom 0:85fdc69bc10c 329 http_cb on_headers_complete;
Jan Jongboom 0:85fdc69bc10c 330 http_data_cb on_body;
Jan Jongboom 0:85fdc69bc10c 331 http_cb on_message_complete;
Jan Jongboom 0:85fdc69bc10c 332 /* When on_chunk_header is called, the current chunk length is stored
Jan Jongboom 0:85fdc69bc10c 333 * in parser->content_length.
Jan Jongboom 0:85fdc69bc10c 334 */
Jan Jongboom 0:85fdc69bc10c 335 http_cb on_chunk_header;
Jan Jongboom 0:85fdc69bc10c 336 http_cb on_chunk_complete;
Jan Jongboom 0:85fdc69bc10c 337 };
Jan Jongboom 0:85fdc69bc10c 338
Jan Jongboom 0:85fdc69bc10c 339
Jan Jongboom 0:85fdc69bc10c 340 enum http_parser_url_fields
Jan Jongboom 0:85fdc69bc10c 341 { UF_SCHEMA = 0
Jan Jongboom 0:85fdc69bc10c 342 , UF_HOST = 1
Jan Jongboom 0:85fdc69bc10c 343 , UF_PORT = 2
Jan Jongboom 0:85fdc69bc10c 344 , UF_PATH = 3
Jan Jongboom 0:85fdc69bc10c 345 , UF_QUERY = 4
Jan Jongboom 0:85fdc69bc10c 346 , UF_FRAGMENT = 5
Jan Jongboom 0:85fdc69bc10c 347 , UF_USERINFO = 6
Jan Jongboom 0:85fdc69bc10c 348 , UF_MAX = 7
Jan Jongboom 0:85fdc69bc10c 349 };
Jan Jongboom 0:85fdc69bc10c 350
Jan Jongboom 0:85fdc69bc10c 351
Jan Jongboom 0:85fdc69bc10c 352 /* Result structure for http_parser_parse_url().
Jan Jongboom 0:85fdc69bc10c 353 *
Jan Jongboom 0:85fdc69bc10c 354 * Callers should index into field_data[] with UF_* values iff field_set
Jan Jongboom 0:85fdc69bc10c 355 * has the relevant (1 << UF_*) bit set. As a courtesy to clients (and
Jan Jongboom 0:85fdc69bc10c 356 * because we probably have padding left over), we convert any port to
Jan Jongboom 0:85fdc69bc10c 357 * a uint16_t.
Jan Jongboom 0:85fdc69bc10c 358 */
Jan Jongboom 0:85fdc69bc10c 359 struct http_parser_url {
Jan Jongboom 0:85fdc69bc10c 360 uint16_t field_set; /* Bitmask of (1 << UF_*) values */
Jan Jongboom 0:85fdc69bc10c 361 uint16_t port; /* Converted UF_PORT string */
Jan Jongboom 0:85fdc69bc10c 362
Jan Jongboom 0:85fdc69bc10c 363 struct {
Jan Jongboom 0:85fdc69bc10c 364 uint16_t off; /* Offset into buffer in which field starts */
Jan Jongboom 0:85fdc69bc10c 365 uint16_t len; /* Length of run in buffer */
Jan Jongboom 0:85fdc69bc10c 366 } field_data[UF_MAX];
Jan Jongboom 0:85fdc69bc10c 367 };
Jan Jongboom 0:85fdc69bc10c 368
Jan Jongboom 0:85fdc69bc10c 369
Jan Jongboom 0:85fdc69bc10c 370 /* Returns the library version. Bits 16-23 contain the major version number,
Jan Jongboom 0:85fdc69bc10c 371 * bits 8-15 the minor version number and bits 0-7 the patch level.
Jan Jongboom 0:85fdc69bc10c 372 * Usage example:
Jan Jongboom 0:85fdc69bc10c 373 *
Jan Jongboom 0:85fdc69bc10c 374 * unsigned long version = http_parser_version();
Jan Jongboom 0:85fdc69bc10c 375 * unsigned major = (version >> 16) & 255;
Jan Jongboom 0:85fdc69bc10c 376 * unsigned minor = (version >> 8) & 255;
Jan Jongboom 0:85fdc69bc10c 377 * unsigned patch = version & 255;
Jan Jongboom 0:85fdc69bc10c 378 * printf("http_parser v%u.%u.%u\n", major, minor, patch);
Jan Jongboom 0:85fdc69bc10c 379 */
Jan Jongboom 0:85fdc69bc10c 380 unsigned long http_parser_version(void);
Jan Jongboom 0:85fdc69bc10c 381
Jan Jongboom 0:85fdc69bc10c 382 void http_parser_init(http_parser *parser, enum http_parser_type type);
Jan Jongboom 0:85fdc69bc10c 383
Jan Jongboom 0:85fdc69bc10c 384
Jan Jongboom 0:85fdc69bc10c 385 /* Initialize http_parser_settings members to 0
Jan Jongboom 0:85fdc69bc10c 386 */
Jan Jongboom 0:85fdc69bc10c 387 void http_parser_settings_init(http_parser_settings *settings);
Jan Jongboom 0:85fdc69bc10c 388
Jan Jongboom 0:85fdc69bc10c 389
Jan Jongboom 0:85fdc69bc10c 390 /* Executes the parser. Returns number of parsed bytes. Sets
Jan Jongboom 0:85fdc69bc10c 391 * `parser->http_errno` on error. */
Jan Jongboom 0:85fdc69bc10c 392 size_t http_parser_execute(http_parser *parser,
Jan Jongboom 0:85fdc69bc10c 393 const http_parser_settings *settings,
Jan Jongboom 0:85fdc69bc10c 394 const char *data,
Jan Jongboom 0:85fdc69bc10c 395 size_t len);
Jan Jongboom 0:85fdc69bc10c 396
Jan Jongboom 0:85fdc69bc10c 397
Jan Jongboom 0:85fdc69bc10c 398 /* If http_should_keep_alive() in the on_headers_complete or
Jan Jongboom 0:85fdc69bc10c 399 * on_message_complete callback returns 0, then this should be
Jan Jongboom 0:85fdc69bc10c 400 * the last message on the connection.
Jan Jongboom 0:85fdc69bc10c 401 * If you are the server, respond with the "Connection: close" header.
Jan Jongboom 0:85fdc69bc10c 402 * If you are the client, close the connection.
Jan Jongboom 0:85fdc69bc10c 403 */
Jan Jongboom 0:85fdc69bc10c 404 int http_should_keep_alive(const http_parser *parser);
Jan Jongboom 0:85fdc69bc10c 405
Jan Jongboom 0:85fdc69bc10c 406 /* Returns a string version of the HTTP method. */
Jan Jongboom 0:85fdc69bc10c 407 const char *http_method_str(enum http_method m);
Jan Jongboom 0:85fdc69bc10c 408
Jan Jongboom 0:85fdc69bc10c 409 /* Return a string name of the given error */
Jan Jongboom 0:85fdc69bc10c 410 const char *http_errno_name(enum http_errno err);
Jan Jongboom 0:85fdc69bc10c 411
Jan Jongboom 0:85fdc69bc10c 412 /* Return a string description of the given error */
Jan Jongboom 0:85fdc69bc10c 413 const char *http_errno_description(enum http_errno err);
Jan Jongboom 0:85fdc69bc10c 414
Jan Jongboom 0:85fdc69bc10c 415 /* Initialize all http_parser_url members to 0 */
Jan Jongboom 0:85fdc69bc10c 416 void http_parser_url_init(struct http_parser_url *u);
Jan Jongboom 0:85fdc69bc10c 417
Jan Jongboom 0:85fdc69bc10c 418 /* Parse a URL; return nonzero on failure */
Jan Jongboom 0:85fdc69bc10c 419 int http_parser_parse_url(const char *buf, size_t buflen,
Jan Jongboom 0:85fdc69bc10c 420 int is_connect,
Jan Jongboom 0:85fdc69bc10c 421 struct http_parser_url *u);
Jan Jongboom 0:85fdc69bc10c 422
Jan Jongboom 0:85fdc69bc10c 423 /* Pause or un-pause the parser; a nonzero value pauses */
Jan Jongboom 0:85fdc69bc10c 424 void http_parser_pause(http_parser *parser, int paused);
Jan Jongboom 0:85fdc69bc10c 425
Jan Jongboom 0:85fdc69bc10c 426 /* Checks if this is the final chunk of the body. */
Jan Jongboom 0:85fdc69bc10c 427 int http_body_is_final(const http_parser *parser);
Jan Jongboom 0:85fdc69bc10c 428
Jan Jongboom 0:85fdc69bc10c 429 #ifdef __cplusplus
Jan Jongboom 0:85fdc69bc10c 430 }
Jan Jongboom 0:85fdc69bc10c 431 #endif
Jan Jongboom 0:85fdc69bc10c 432 #endif