diff --git a/include/zephyr/net/http/server.h b/include/zephyr/net/http/server.h index d493e5b3251e..7bfb60938435 100644 --- a/include/zephyr/net/http/server.h +++ b/include/zephyr/net/http/server.h @@ -82,6 +82,9 @@ struct http_resource_detail { /** Content encoding of the resource. */ const char *content_encoding; + + /** Content type of the resource. */ + const char *content_type; }; /** @cond INTERNAL_HIDDEN */ diff --git a/subsys/net/lib/http/http_server_http1.c b/subsys/net/lib/http/http_server_http1.c index 799485f537c2..d718c37bc350 100644 --- a/subsys/net/lib/http/http_server_http1.c +++ b/subsys/net/lib/http/http_server_http1.c @@ -31,12 +31,13 @@ static int handle_http1_static_resource( { #define RESPONSE_TEMPLATE \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ + "%s%s\r\n" \ "Content-Length: %d\r\n" /* Add couple of bytes to total response */ char http_response[sizeof(RESPONSE_TEMPLATE) + sizeof("Content-Encoding: 01234567890123456789\r\n") + + sizeof("Content-Type: \r\n") + HTTP_SERVER_MAX_CONTENT_TYPE_LEN + sizeof("xxxx") + sizeof("\r\n")]; const char *data; @@ -51,10 +52,17 @@ static int handle_http1_static_resource( static_detail->common.content_encoding[0] != '\0') { snprintk(http_response, sizeof(http_response), RESPONSE_TEMPLATE "Content-Encoding: %s\r\n\r\n", + "Content-Type: ", + static_detail->common.content_type == NULL ? + "text/html" : static_detail->common.content_type, len, static_detail->common.content_encoding); } else { snprintk(http_response, sizeof(http_response), - RESPONSE_TEMPLATE "\r\n", len); + RESPONSE_TEMPLATE "\r\n", + "Content-Type: ", + static_detail->common.content_type == NULL ? + "text/html" : static_detail->common.content_type, + len); } ret = http_server_sendall(client, http_response, @@ -74,12 +82,28 @@ static int handle_http1_static_resource( #define RESPONSE_TEMPLATE_CHUNKED \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n" \ + "%s%s\r\n" \ "Transfer-Encoding: chunked\r\n\r\n" #define RESPONSE_TEMPLATE_DYNAMIC \ "HTTP/1.1 200 OK\r\n" \ - "Content-Type: text/html\r\n\r\n" \ + "%s%s\r\n\r\n" + +#define SEND_RESPONSE(_template, _content_type) ({ \ + char http_response[sizeof(_template) + \ + sizeof("Content-Type: \r\n") + \ + HTTP_SERVER_MAX_CONTENT_TYPE_LEN + \ + sizeof("xxxx") + \ + sizeof("\r\n")]; \ + snprintk(http_response, sizeof(http_response), \ + _template "\r\n", \ + "Content-Type: ", \ + _content_type == NULL ? \ + "text/html" : _content_type); \ + ret = http_server_sendall(client, http_response, \ + strnlen(http_response, \ + sizeof(_template) - 1)); \ + ret; }) static int dynamic_get_req(struct http_resource_detail_dynamic *dynamic_detail, struct http_client_ctx *client) @@ -89,8 +113,8 @@ static int dynamic_get_req(struct http_resource_detail_dynamic *dynamic_detail, char *ptr; char tmp[TEMP_BUF_LEN]; - ret = http_server_sendall(client, RESPONSE_TEMPLATE_CHUNKED, - sizeof(RESPONSE_TEMPLATE_CHUNKED) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } @@ -167,8 +191,8 @@ static int dynamic_post_req(struct http_resource_detail_dynamic *dynamic_detail, } if (!client->headers_sent) { - ret = http_server_sendall(client, RESPONSE_TEMPLATE_CHUNKED, - sizeof(RESPONSE_TEMPLATE_CHUNKED) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_CHUNKED, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } @@ -266,9 +290,8 @@ static int handle_http1_dynamic_resource( switch (client->method) { case HTTP_HEAD: if (user_method & BIT(HTTP_HEAD)) { - ret = http_server_sendall( - client, RESPONSE_TEMPLATE_DYNAMIC, - sizeof(RESPONSE_TEMPLATE_DYNAMIC) - 1); + ret = SEND_RESPONSE(RESPONSE_TEMPLATE_DYNAMIC, + dynamic_detail->common.content_type); if (ret < 0) { return ret; } diff --git a/subsys/net/lib/http/http_server_http2.c b/subsys/net/lib/http/http_server_http2.c index 3948401057f7..b455340bf389 100644 --- a/subsys/net/lib/http/http_server_http2.c +++ b/subsys/net/lib/http/http_server_http2.c @@ -149,7 +149,8 @@ static void encode_frame_header(uint8_t *buf, uint32_t payload_len, static int send_headers_frame(struct http_client_ctx *client, enum http_status status, uint32_t stream_id, - const char *content_encoding, uint8_t flags) + struct http_resource_detail *detail_common, + uint8_t flags) { uint8_t headers_frame[64]; uint8_t status_str[4]; @@ -168,7 +169,7 @@ static int send_headers_frame(struct http_client_ctx *client, return ret; } - if (content_encoding != NULL) { + if (detail_common && detail_common->content_encoding != NULL) { ret = add_header_field(client, &buf, &buflen, "content-encoding", "gzip"); if (ret < 0) { @@ -176,6 +177,14 @@ static int send_headers_frame(struct http_client_ctx *client, } } + if (detail_common && detail_common->content_type != NULL) { + ret = add_header_field(client, &buf, &buflen, "content-type", + detail_common->content_type); + if (ret < 0) { + return ret; + } + } + payload_len = sizeof(headers_frame) - buflen - HTTP_SERVER_FRAME_HEADER_SIZE; flags |= HTTP_SERVER_FLAG_END_HEADERS; @@ -349,7 +358,7 @@ static int handle_http2_static_resource( content_len = static_detail->static_data_len; ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, - static_detail->common.content_encoding, 0); + &static_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); goto out; @@ -375,7 +384,7 @@ static int dynamic_get_req_v2(struct http_resource_detail_dynamic *dynamic_detai char *ptr; ret = send_headers_frame(client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, 0); + &dynamic_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); return ret; @@ -481,7 +490,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta if (!client->headers_sent) { ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, 0); + &dynamic_detail->common, 0); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret); return ret; @@ -518,7 +527,7 @@ static int dynamic_post_req_v2(struct http_resource_detail_dynamic *dynamic_deta */ ret = send_headers_frame( client, HTTP_200_OK, frame->stream_identifier, - dynamic_detail->common.content_encoding, + &dynamic_detail->common, HTTP_SERVER_FLAG_END_STREAM); if (ret < 0) { LOG_DBG("Cannot write to socket (%d)", ret);