Merge branch 'fix/http2_request_example_v4.3' into 'release/v4.3'

http2_request_example: Change the target http2 server to http2.github.io (v4.3)

See merge request espressif/esp-idf!16671
This commit is contained in:
Mahavir Jain
2022-01-27 06:39:45 +00:00
8 changed files with 124 additions and 24 deletions

View File

@@ -1,6 +1,55 @@
# HTTP/2 Request Example # HTTP/2 Request Example
Established HTTP/2 connection with https://http2.golang.org Establish an HTTP/2 connection with https://http2.github.io
- Performs a GET on /clockstream - Performs a GET on /index.html
- Performs a PUT on /ECHO
## How to use example
Before project configuration and build, be sure to set the correct chip target using `idf.py set-target <chip_name>`.
### Hardware Required
* A development board with ESP32/ESP32-S2/ESP32-C3 SoC (e.g., ESP32-DevKitC, ESP-WROVER-KIT, etc.)
* A USB cable for power supply and programming
### Configure the project
```
idf.py menuconfig
```
Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
### Build and Flash
Build the project and flash it to the board, then run monitor tool to view serial output:
```
idf.py -p PORT flash monitor
```
(Replace PORT with the name of the serial port to use.)
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
```
I (5609) example_connect: - IPv4 address: 192.168.0.103
I (5609) example_connect: - IPv6 address: fe80:0000:0000:0000:ae67:b2ff:fe45:0194, type: ESP_IP6_ADDR_IS_LINK_LOCAL
Connecting to server
Connection done
[get-response] <!DOCTYPE HTML>
<html lang="en">
.
.
.
Body of index.html
.
.
.
.
</html>
[get-response] Frame fully received
[get-response] Stream Closed
```

View File

@@ -235,27 +235,35 @@ static int do_http2_connect(struct sh2lib_handle *hd)
return 0; return 0;
} }
int sh2lib_connect(struct sh2lib_handle *hd, const char *uri) int sh2lib_connect(struct sh2lib_config_t *cfg, struct sh2lib_handle *hd)
{ {
memset(hd, 0, sizeof(*hd)); memset(hd, 0, sizeof(*hd));
if (cfg == NULL) {
ESP_LOGE(TAG, "[sh2-connect] pointer to sh2lib configurations cannot be NULL");
goto error;
}
const char *proto[] = {"h2", NULL}; const char *proto[] = {"h2", NULL};
esp_tls_cfg_t tls_cfg = { esp_tls_cfg_t tls_cfg = {
.alpn_protos = proto, .alpn_protos = proto,
.cacert_buf = cfg->cacert_buf,
.cacert_bytes = cfg->cacert_bytes,
.non_block = true, .non_block = true,
.timeout_ms = 10 * 1000, .timeout_ms = 10 * 1000,
}; };
if ((hd->http2_tls = esp_tls_conn_http_new(uri, &tls_cfg)) == NULL) { if ((hd->http2_tls = esp_tls_conn_http_new(cfg->uri, &tls_cfg)) == NULL) {
ESP_LOGE(TAG, "[sh2-connect] esp-tls connection failed"); ESP_LOGE(TAG, "[sh2-connect] esp-tls connection failed");
goto error; goto error;
} }
struct http_parser_url u; struct http_parser_url u;
http_parser_url_init(&u); http_parser_url_init(&u);
http_parser_parse_url(uri, strlen(uri), 0, &u); http_parser_parse_url(cfg->uri, strlen(cfg->uri), 0, &u);
hd->hostname = strndup(&uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len); hd->hostname = strndup(&cfg->uri[u.field_data[UF_HOST].off], u.field_data[UF_HOST].len);
/* HTTP/2 Connection */ /* HTTP/2 Connection */
if (do_http2_connect(hd) != 0) { if (do_http2_connect(hd) != 0) {
ESP_LOGE(TAG, "[sh2-connect] HTTP2 Connection failed with %s", uri); ESP_LOGE(TAG, "[sh2-connect] HTTP2 Connection failed with %s", cfg->uri);
goto error; goto error;
} }

View File

@@ -38,6 +38,15 @@ struct sh2lib_handle {
struct esp_tls *http2_tls; /*!< Pointer to the TLS session handle */ struct esp_tls *http2_tls; /*!< Pointer to the TLS session handle */
}; };
/**
* @brief sh2lib configuration structure
*/
struct sh2lib_config_t {
const char *uri; /*!< Pointer to the URI that should be connected to */
const unsigned char *cacert_buf; /*!< Pointer to the buffer containing CA certificate */
unsigned int cacert_bytes; /*!< Size of the CA certifiacte pointed by cacert_buf */
};
/** Flag indicating receive stream is reset */ /** Flag indicating receive stream is reset */
#define DATA_RECV_RST_STREAM 1 #define DATA_RECV_RST_STREAM 1
/** Flag indicating frame is completely received */ /** Flag indicating frame is completely received */
@@ -88,14 +97,13 @@ typedef int (*sh2lib_putpost_data_cb_t)(struct sh2lib_handle *handle, char *data
* *
* Only 'https' URIs are supported. * Only 'https' URIs are supported.
* *
* @param[in] cfg Pointer to the sh2lib configurations of the type 'struct sh2lib_config_t'.
* @param[out] hd Pointer to a variable of the type 'struct sh2lib_handle'. * @param[out] hd Pointer to a variable of the type 'struct sh2lib_handle'.
* @param[in] uri Pointer to the URI that should be connected to.
*
* @return * @return
* - ESP_OK if the connection was successful * - ESP_OK if the connection was successful
* - ESP_FAIL if the connection fails * - ESP_FAIL if the connection fails
*/ */
int sh2lib_connect(struct sh2lib_handle *hd, const char *uri); int sh2lib_connect(struct sh2lib_config_t *cfg, struct sh2lib_handle *hd);
/** /**
* @brief Free a sh2lib handle * @brief Free a sh2lib handle

View File

@@ -1,2 +1,3 @@
idf_component_register(SRCS "http2_request_example_main.c" idf_component_register(SRCS "http2_request_example_main.c"
INCLUDE_DIRS ".") INCLUDE_DIRS "."
EMBED_TXTFILES "http2_github_io_root_cert.pem")

View File

@@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
COMPONENT_EMBED_TXTFILES := http2_github_io_root_cert.pem

View File

@@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE-----
MIIEsTCCA5mgAwIBAgIQBOHnpNxc8vNtwCtCuF0VnzANBgkqhkiG9w0BAQsFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAyMjEyMDAwMFowcDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTEvMC0GA1UEAxMmRGlnaUNlcnQgU0hBMiBIaWdoIEFzc3Vy
YW5jZSBTZXJ2ZXIgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC2
4C/CJAbIbQRf1+8KZAayfSImZRauQkCbztyfn3YHPsMwVYcZuU+UDlqUH1VWtMIC
Kq/QmO4LQNfE0DtyyBSe75CxEamu0si4QzrZCwvV1ZX1QK/IHe1NnF9Xt4ZQaJn1
itrSxwUfqJfJ3KSxgoQtxq2lnMcZgqaFD15EWCo3j/018QsIJzJa9buLnqS9UdAn
4t07QjOjBSjEuyjMmqwrIw14xnvmXnG3Sj4I+4G3FhahnSMSTeXXkgisdaScus0X
sh5ENWV/UyU50RwKmmMbGZJ0aAo3wsJSSMs5WqK24V3B3aAguCGikyZvFEohQcft
bZvySC/zA/WiaJJTL17jAgMBAAGjggFJMIIBRTASBgNVHRMBAf8ECDAGAQH/AgEA
MA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw
NAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2Vy
dC5jb20wSwYDVR0fBEQwQjBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNlcnQuY29t
L0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDA9BgNVHSAENjA0MDIG
BFUdIAAwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQ
UzAdBgNVHQ4EFgQUUWj/kK8CB3U8zNllZGKiErhZcjswHwYDVR0jBBgwFoAUsT7D
aQP4v0cB1JgmGggC72NkK8MwDQYJKoZIhvcNAQELBQADggEBABiKlYkD5m3fXPwd
aOpKj4PWUS+Na0QWnqxj9dJubISZi6qBcYRb7TROsLd5kinMLYBq8I4g4Xmk/gNH
E+r1hspZcX30BJZr01lYPf7TMSVcGDiEo+afgv2MW5gxTs14nhr9hctJqvIni5ly
/D6q1UEL2tU2ob8cbkdJf17ZSHwD2f2LSaCYJkJA69aSEaRkCldUxPUd1gJea6zu
xICaEnL6VpPX/78whQYwvwt/Tv9XBZ0k7YXDK/umdaisLRbvfXknsuvCnQsH6qqF
0wGjIChBWUMo0oHjqvbsezt3tkBigAVBRQHvFwY+3sAzm2fTYS5yh+Rp/BIAV0Ae
cPUeybQ=
-----END CERTIFICATE-----

View File

@@ -1,6 +1,6 @@
/* HTTP2 GET Example using nghttp2 /* HTTP2 GET Example using nghttp2
Contacts http2.golang.org and executes the GET/PUT requests. A thin API Contacts http2.github.io and executes the GET request. A thin API
wrapper on top of nghttp2, to properly demonstrate the interactions. wrapper on top of nghttp2, to properly demonstrate the interactions.
This example code is in the Public Domain (or CC0 licensed, at your option.) This example code is in the Public Domain (or CC0 licensed, at your option.)
@@ -26,12 +26,13 @@
#include "sh2lib.h" #include "sh2lib.h"
extern const uint8_t server_root_cert_pem_start[] asm("_binary_http2_github_io_root_cert_pem_start");
extern const uint8_t server_root_cert_pem_end[] asm("_binary_http2_github_io_root_cert_pem_end");
/* The HTTP/2 server to connect to */ /* The HTTP/2 server to connect to */
#define HTTP2_SERVER_URI "https://http2.golang.org" #define HTTP2_SERVER_URI "https://http2.github.io"
/* A GET request that keeps streaming current time every second */ /* A GET request that keeps streaming current time every second */
#define HTTP2_STREAMING_GET_PATH "/clockstream" #define HTTP2_STREAMING_GET_PATH "/index.html"
/* A PUT request that echoes whatever we had sent to it */
#define HTTP2_PUT_PATH "/ECHO"
int handle_get_response(struct sh2lib_handle *handle, const char *data, size_t len, int flags) int handle_get_response(struct sh2lib_handle *handle, const char *data, size_t len, int flags)
@@ -101,8 +102,14 @@ static void http2_task(void *args)
/* HTTP2: one connection multiple requests. Do the TLS/TCP connection first */ /* HTTP2: one connection multiple requests. Do the TLS/TCP connection first */
printf("Connecting to server\n"); printf("Connecting to server\n");
struct sh2lib_config_t cfg = {
.uri = HTTP2_SERVER_URI,
.cacert_buf = server_root_cert_pem_start,
.cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
};
struct sh2lib_handle hd; struct sh2lib_handle hd;
if (sh2lib_connect(&hd, HTTP2_SERVER_URI) != 0) {
if (sh2lib_connect(&cfg, &hd) != 0) {
printf("Failed to connect\n"); printf("Failed to connect\n");
vTaskDelete(NULL); vTaskDelete(NULL);
return; return;
@@ -111,10 +118,6 @@ static void http2_task(void *args)
/* HTTP GET */ /* HTTP GET */
sh2lib_do_get(&hd, HTTP2_STREAMING_GET_PATH, handle_get_response); sh2lib_do_get(&hd, HTTP2_STREAMING_GET_PATH, handle_get_response);
/* HTTP PUT */
sh2lib_do_put(&hd, HTTP2_PUT_PATH, send_put_data, handle_echo_response);
while (1) { while (1) {
/* Process HTTP2 send/receive */ /* Process HTTP2 send/receive */
if (sh2lib_execute(&hd) < 0) { if (sh2lib_execute(&hd) < 0) {

View File

@@ -1,2 +0,0 @@
CONFIG_ESP_TLS_INSECURE=y
CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y