From 567b0a555333ccf4c87b721028c4580bf80ded27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcel=20St=C3=B6r?= Date: Thu, 11 Aug 2016 05:22:31 +0200 Subject: [PATCH] Allow to override User-Agent and Host HTTP headers (#1426) * Allow to override User-Agent and Host HTTP headers Fixes #1410 Idea borrowed from (unmerged) #1157 * Do not send port for host header for default ports --- app/http/httpclient.c | 83 +++++++++++++++++++++++++---------------- docs/en/modules/http.md | 8 +--- 2 files changed, 51 insertions(+), 40 deletions(-) diff --git a/app/http/httpclient.c b/app/http/httpclient.c index 0868bf9d..fc9b4598 100644 --- a/app/http/httpclient.c +++ b/app/http/httpclient.c @@ -181,7 +181,6 @@ static void ICACHE_FLASH_ATTR http_connect_callback( void * arg ) HTTPCLIENT_DEBUG( "Connected\n" ); struct espconn * conn = (struct espconn *) arg; request_args_t * req = (request_args_t *) conn->reverse; - int len; espconn_regist_recvcb( conn, http_receive_callback ); espconn_regist_sentcb( conn, http_send_callback ); @@ -198,39 +197,57 @@ static void ICACHE_FLASH_ATTR http_connect_callback( void * arg ) req->headers[0] = '\0'; } - char buf[69 + strlen( req->method ) + strlen( req->path ) + strlen( req->hostname ) + - strlen( req->headers ) + strlen( post_headers )]; + char ua_header[32] = ""; + int ua_len = 0; + if (os_strstr( req->headers, "User-Agent:" ) == NULL && os_strstr( req->headers, "user-agent:" ) == NULL) + { + os_sprintf( ua_header, "User-Agent: %s\r\n", "ESP8266" ); + ua_len = strlen(ua_header); + } - if ((req->port == 80) || ((req->port == 443) && ( req->secure ))) - { - len = os_sprintf( buf, - "%s %s HTTP/1.1\r\n" - "Host: %s\r\n" - "Connection: close\r\n" - "User-Agent: ESP8266\r\n" - "%s" - "%s" - "\r\n", - req->method, req->path, req->hostname, req->headers, post_headers ); - } else { - len = os_sprintf( buf, - "%s %s HTTP/1.1\r\n" - "Host: %s:%d\r\n" - "Connection: close\r\n" - "User-Agent: ESP8266\r\n" - "%s" - "%s" - "\r\n", - req->method, req->path, req->hostname, req->port, req->headers, post_headers ); - } - if ( req->secure ) - espconn_secure_send( conn, (uint8_t *) buf, len ); - else - espconn_send( conn, (uint8_t *) buf, len ); - if(req->headers != NULL) - os_free( req->headers ); - req->headers = NULL; - HTTPCLIENT_DEBUG( "Sending request header\n" ); + char host_header[32] = ""; + int host_len = 0; + if ( os_strstr( req->headers, "Host:" ) == NULL && os_strstr( req->headers, "host:" ) == NULL) + { + if ((req->port == 80) || ((req->port == 443) && ( req->secure ))) + { + os_sprintf( host_header, "Host: %s\r\n", req->hostname ); + } + else + { + os_sprintf( host_header, "Host: %s:%d\r\n", req->hostname, req->port ); + } + host_len = strlen(host_header); + } + + char buf[69 + strlen( req->method ) + strlen( req->path ) + host_len + + strlen( req->headers ) + ua_len + strlen( post_headers )]; + int len = os_sprintf( buf, + "%s %s HTTP/1.1\r\n" + "%s" // Host (if not provided in the headers from Lua) + "Connection: close\r\n" + "%s" // Headers from Lua (optional) + "%s" // User-Agent (if not provided in the headers from Lua) + "%s" // Content-Length + "\r\n", + req->method, req->path, host_header, req->headers, ua_header, post_headers ); + + if (req->secure) + { + espconn_secure_send( conn, (uint8_t *) buf, len ); + } + else + { + espconn_send( conn, (uint8_t *) buf, len ); + } + + if (req->headers != NULL) + { + os_free( req->headers ); + } + + req->headers = NULL; + HTTPCLIENT_DEBUG( "Sending request header\n" ); } static void http_free_req( request_args_t * req) diff --git a/docs/en/modules/http.md b/docs/en/modules/http.md index 04df0bb0..b35afc31 100644 --- a/docs/en/modules/http.md +++ b/docs/en/modules/http.md @@ -11,13 +11,7 @@ Basic HTTP *client* module that provides an interface to do GET/POST/PUT/DELETE Each request method takes a callback which is invoked when the response has been received from the server. The first argument is the status code, which is either a regular HTTP status code, or -1 to denote a DNS, connection or out-of-memory failure, or a timeout (currently at 10 seconds). -For each operation it is also possible to include custom headers. Note that following headers *can not* be overridden however: - -- Host -- Connection -- User-Agent - -The `Host` header is taken from the URL itself, the `Connection` is always set to `close`, and the `User-Agent` is `ESP8266`. +For each operation it is possible to provide custom HTTP headers or override standard headers. By default the `Host` header is deduced from the URL and `User-Agent` is `ESP8266`. Note, however, that the `Connection` header *can not* be overridden! It is always set to `close`. **SSL/TLS support**