From 660149dbf7d16cf080b6b910f89c63882e8d663c Mon Sep 17 00:00:00 2001 From: Jukka Rissanen Date: Thu, 9 Nov 2023 20:15:12 +0200 Subject: [PATCH] samples: net: http_server: Add HTTP server sample application A simple HTTP server sample application. Signed-off-by: Emna Rekik Signed-off-by: Jukka Rissanen Signed-off-by: Robert Lubos --- .../net/sockets/http_server/CMakeLists.txt | 59 ++++++ samples/net/sockets/http_server/Kconfig | 41 ++++ samples/net/sockets/http_server/README.rst | 118 ++++++++++++ samples/net/sockets/http_server/prj.conf | 71 +++++++ samples/net/sockets/http_server/sample.yaml | 16 ++ .../net/sockets/http_server/sections-rom.ld | 4 + samples/net/sockets/http_server/src/ca.der | Bin 0 -> 783 bytes .../net/sockets/http_server/src/certificate.h | 50 +++++ .../net/sockets/http_server/src/dummy_psk.h | 14 ++ .../http_server/src/https-server-cert.der | Bin 0 -> 767 bytes .../http_server/src/https-server-key.der | Bin 0 -> 1218 bytes .../net/sockets/http_server/src/index.html | 10 + samples/net/sockets/http_server/src/main.c | 180 ++++++++++++++++++ .../http_server/src/not_found_page.html | 10 + .../net/sockets/http_server/src/server.der | Bin 0 -> 693 bytes .../http_server/src/server_privkey.der | Bin 0 -> 1219 bytes 16 files changed, 573 insertions(+) create mode 100644 samples/net/sockets/http_server/CMakeLists.txt create mode 100644 samples/net/sockets/http_server/Kconfig create mode 100644 samples/net/sockets/http_server/README.rst create mode 100644 samples/net/sockets/http_server/prj.conf create mode 100644 samples/net/sockets/http_server/sample.yaml create mode 100644 samples/net/sockets/http_server/sections-rom.ld create mode 100644 samples/net/sockets/http_server/src/ca.der create mode 100644 samples/net/sockets/http_server/src/certificate.h create mode 100644 samples/net/sockets/http_server/src/dummy_psk.h create mode 100644 samples/net/sockets/http_server/src/https-server-cert.der create mode 100644 samples/net/sockets/http_server/src/https-server-key.der create mode 100644 samples/net/sockets/http_server/src/index.html create mode 100644 samples/net/sockets/http_server/src/main.c create mode 100644 samples/net/sockets/http_server/src/not_found_page.html create mode 100644 samples/net/sockets/http_server/src/server.der create mode 100644 samples/net/sockets/http_server/src/server_privkey.der diff --git a/samples/net/sockets/http_server/CMakeLists.txt b/samples/net/sockets/http_server/CMakeLists.txt new file mode 100644 index 00000000000000..5b27e5ee7ca96f --- /dev/null +++ b/samples/net/sockets/http_server/CMakeLists.txt @@ -0,0 +1,59 @@ +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +find_package(Python REQUIRED COMPONENTS Interpreter) + +project(http_server) + +if(CONFIG_NET_SOCKETS_SOCKOPT_TLS AND + CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND + (CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h")) + add_custom_target(development_psk + COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------" + COMMAND ${CMAKE_COMMAND} -E echo "--- WARNING: Using dummy PSK! Only suitable for ---" + COMMAND ${CMAKE_COMMAND} -E echo "--- development. Set NET_SAMPLE_PSK_HEADER_FILE to use ---" + COMMAND ${CMAKE_COMMAND} -E echo "--- own pre-shared key. ---" + COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------" + ) + add_dependencies(app development_psk) +endif() + +option(INCLUDE_HTML_CONTENT "Include the HTML content" ON) + +target_sources(app PRIVATE src/main.c) + +set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/) + +set(source_file_index src/index.html) +generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.inc --gzip) + +set(source_file_not_found src/not_found_page.html) +generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_page.html.gz.inc --gzip) + +target_link_libraries(app PRIVATE zephyr_interface zephyr) + +zephyr_linker_sources(SECTIONS sections-rom.ld) +zephyr_linker_section_ifdef(CONFIG_NET_SAMPLE_HTTPS_SERVICE NAME + http_resource_desc_test_https_service + KVMA RAM_REGION GROUP RODATA_REGION + SUBALIGN Z_LINK_ITERABLE_SUBALIGN) +zephyr_linker_section_ifdef(CONFIG_NET_SAMPLE_HTTP_SERVICE NAME + http_resource_desc_test_http_service + KVMA RAM_REGION GROUP RODATA_REGION + SUBALIGN Z_LINK_ITERABLE_SUBALIGN) + +foreach(inc_file + ca.der + server.der + server_privkey.der + https-server-cert.der + https-server-key.der + ) + generate_inc_file_for_target( + app + src/${inc_file} + ${gen_dir}/${inc_file}.inc + ) +endforeach() diff --git a/samples/net/sockets/http_server/Kconfig b/samples/net/sockets/http_server/Kconfig new file mode 100644 index 00000000000000..90104be01fa19a --- /dev/null +++ b/samples/net/sockets/http_server/Kconfig @@ -0,0 +1,41 @@ +# Config options for http2 server sample application + +# Copyright (c) 2023, Emna Rekik +# SPDX-License-Identifier: Apache-2.0 + +mainmenu "HTTP2 server sample application" + +config NET_SAMPLE_HTTP_SERVICE + bool "Enable http service" + default y + +config NET_SAMPLE_HTTP_SERVER_SERVICE_PORT + int "Port number for http service" + default 80 + depends on NET_SAMPLE_HTTP_SERVICE + +config NET_SAMPLE_HTTPS_SERVICE + bool "Enable https service" + depends on NET_SOCKETS_SOCKOPT_TLS || TLS_CREDENTIALS + +config NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT + int "Port number for https service" + default 443 + depends on NET_SAMPLE_HTTPS_SERVICE + +config NET_SAMPLE_PSK_HEADER_FILE + string "Header file containing PSK" + default "dummy_psk.h" + depends on MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + help + Name of a header file containing a + pre-shared key. + +config NET_SAMPLE_CERTS_WITH_SC + bool "Signed certificates" + depends on NET_SOCKETS_SOCKOPT_TLS + help + Enable this flag, if you are interested to run this + application with signed certificates and keys. + +source "Kconfig.zephyr" diff --git a/samples/net/sockets/http_server/README.rst b/samples/net/sockets/http_server/README.rst new file mode 100644 index 00000000000000..cc4cd1c5482196 --- /dev/null +++ b/samples/net/sockets/http_server/README.rst @@ -0,0 +1,118 @@ +Zephyr HTTP Server +================== + +Overview +-------- + +This sample application demonstrates the use of the ``http_server`` library. +This library provides high-level functions to simplify and abstract server implementation. +The server supports the HTTP/1.1 protocol which can also be upgraded to HTTP/2, +it also support native HTTP/2 protocol without upgrading. + +Requirement +----------- + +`QEMU Networking `_ + +Building and running the server +------------------------------- + +To build and run the application: + +.. code-block:: bash + + $ west build -p auto -b -t run samples/net/sockets/http_server + +When the server is up, we can make requests to the server using either HTTP/1.1 or +HTTP/2 protocol from the host machine. + +**With HTTP/1.1:** + +- Using a browser: ``http://192.0.2.1/`` +- Using curl: ``curl -v --compressed http://192.0.2.1/`` +- Using ab (Apache Bench): ``ab -n10 http://192.0.2.1/`` + +**With HTTP/2:** + +- Using nghttp client: ``nghttp -v --no-dep http://192.0.2.1/`` +- Using curl: ``curl --http2 -v --compressed http://192.0.2.1/`` +- Using h2load: ``h2load -n10 http://192.0.2.1/`` + +Server Customization +--------------------- + +The server sample contains several parameters that can be customized based on +the requirements. These are the configurable parameters: + +- ``CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT``: Configures the service port. + +- ``CONFIG_HTTP_SERVER_MAX_CLIENTS``: Defines the maximum number of HTTP/2 + clients that the server can handle simultaneously. + +- ``CONFIG_HTTP_SERVER_MAX_STREAMS``: Specifies the maximum number of HTTP/2 + streams that can be established per client. + +- ``CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE``: Defines the buffer size allocated + for each client. This limits the maximum length of an individual HTTP header + supported. + +- ``CONFIG_HTTP_SERVER_MAX_URL_LENGTH``: Specifies the maximum length of an HTTP + URL that the server can process. + +To customize these options, we can run ``west build -t menuconfig``, which provides +us with an interactive configuration interface. Then we could navigate from the top-level +menu to: ``-> Subsystems and OS Services -> Networking -> Network Protocols``. + +Performance Analysis +-------------------- + +CPU Usage Profiling +******************* + +We can use ``perf`` to collect statistics about the CPU usage of our server +running in native_sim board with the ``stat`` command: + +.. code-block:: bash + + $ sudo perf stat -p + +``perf stat`` will then start monitoring our server. We can let it run while +sending requests to our server. Once we've collected enough data, we can +stop ``perf stat``, which will print a summary of the performance statistics. + +Hotspot Analysis +**************** + +``perf record`` and ``perf report`` can be used together to identify the +functions in our code that consume the most CPU time: + +.. code-block:: bash + + $ sudo perf record -g -p -o perf.data + +After running our server under load (For example, using ApacheBench tool), +we can stop the recording and analyze the data using: + +.. code-block:: bash + + $ sudo perf report -i perf.data + +After generating a file named ``perf.data`` which contains the profiling data, +we can visualize it using ``FlameGraph`` tool. It's particularly useful for +identifying the most expensive code-paths and inspect where our application is +spending the most time. + +To do this, we need to convert the ``perf.data`` to a format that ``FlameGraph`` +can understand: + +.. code-block:: bash + + $ sudo perf script | ~/FlameGraph/stackcollapse-perf.pl > out.perf-folded + +And, then, generate the ``FlameGraph``: + +.. code-block:: bash + + $ ~/FlameGraph/flamegraph.pl out.perf-folded > flamegraph.svg + +We can view flamegraph.svg using a web browser. diff --git a/samples/net/sockets/http_server/prj.conf b/samples/net/sockets/http_server/prj.conf new file mode 100644 index 00000000000000..9e56f3332e7f2b --- /dev/null +++ b/samples/net/sockets/http_server/prj.conf @@ -0,0 +1,71 @@ +# General config +CONFIG_MAIN_STACK_SIZE=3072 +CONFIG_SHELL=y +CONFIG_LOG=y +CONFIG_ENTROPY_GENERATOR=y +CONFIG_TEST_RANDOM_GENERATOR=y +CONFIG_INIT_STACKS=y +CONFIG_POSIX_MAX_FDS=32 +CONFIG_POSIX_API=y +CONFIG_FDTABLE=y +CONFIG_NET_SOCKETS_POLL_MAX=32 + +# Eventfd +CONFIG_EVENTFD=y + +# Networking config +CONFIG_NETWORKING=y +CONFIG_NET_IPV4=y +CONFIG_NET_IPV6=y +CONFIG_NET_TCP=y +CONFIG_NET_SOCKETS=y +CONFIG_NET_CONNECTION_MANAGER=y +CONFIG_NET_SHELL=y +CONFIG_NET_LOG=y + +# JSON +CONFIG_JSON_LIBRARY=y + +# HTTP parser +CONFIG_HTTP_PARSER_URL=y +CONFIG_HTTP_PARSER=y +CONFIG_HTTP_SERVER=y + +# Network buffers +CONFIG_NET_PKT_RX_COUNT=16 +CONFIG_NET_PKT_TX_COUNT=16 +CONFIG_NET_BUF_RX_COUNT=128 +CONFIG_NET_BUF_TX_COUNT=128 +CONFIG_NET_CONTEXT_NET_PKT_POOL=y + +# IP address options +CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3 +CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4 +CONFIG_NET_MAX_CONTEXTS=32 +CONFIG_NET_MAX_CONN=32 + +# Network address config +CONFIG_NET_CONFIG_SETTINGS=y +CONFIG_NET_CONFIG_NEED_IPV4=y +CONFIG_NET_CONFIG_NEED_IPV6=y +CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1" +CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2" +CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2" +CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1" +CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2" + +# TLS configuration +CONFIG_MBEDTLS=y +CONFIG_MBEDTLS_BUILTIN=y +CONFIG_MBEDTLS_ENABLE_HEAP=y +CONFIG_MBEDTLS_HEAP_SIZE=60000 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048 +CONFIG_NET_SOCKETS_SOCKOPT_TLS=y +CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6 +CONFIG_TLS_CREDENTIALS=y +CONFIG_TLS_MAX_CREDENTIALS_NUMBER=5 + +# Networking tweaks +# Required to handle large number of consecutive connections, +# e.g. when testing with ApacheBench. +CONFIG_NET_TCP_TIME_WAIT_DELAY=0 diff --git a/samples/net/sockets/http_server/sample.yaml b/samples/net/sockets/http_server/sample.yaml new file mode 100644 index 00000000000000..eeaca47d386eda --- /dev/null +++ b/samples/net/sockets/http_server/sample.yaml @@ -0,0 +1,16 @@ +sample: + description: HTTP Server Sample + name: http_server_sample +common: + harness: net + min_ram: 192 + tags: + - http + - net + - server + - socket + platform_exclude: + - native_posix + - native_posix/native/64 +tests: + sample.net.sockets.http.server: {} diff --git a/samples/net/sockets/http_server/sections-rom.ld b/samples/net/sockets/http_server/sections-rom.ld new file mode 100644 index 00000000000000..d51cad087f3e90 --- /dev/null +++ b/samples/net/sockets/http_server/sections-rom.ld @@ -0,0 +1,4 @@ +#include + +ITERABLE_SECTION_ROM(http_resource_desc_test_http_service, Z_LINK_ITERABLE_SUBALIGN) +ITERABLE_SECTION_ROM(http_resource_desc_test_https_service, Z_LINK_ITERABLE_SUBALIGN) diff --git a/samples/net/sockets/http_server/src/ca.der b/samples/net/sockets/http_server/src/ca.der new file mode 100644 index 0000000000000000000000000000000000000000..b1d3e097cadcea344d9b172b4a540ddd57dae71e GIT binary patch literal 783 zcmXqLV&*nzV*I>-nTe5!NkrQ5sj}%5hTSG>R`_Lq-*o88&x{EMylk9WZ60mkc^MhG zSs4sO4228?*qB3En0Yu;D-v@Ha#Ecg4HU$AjSLJ74b2TKfs|#G1iz7?p{1dbkqJ}) zhrT98C1eX2Ss9p{82K51ZsKBUVq|34wV`KTh|5~Fr}HK2;*u6Ee|T=)1e1!xi;caz z-Z<-YoAX;FSjv^Y>1nk1mK&woeDe9}%lcDyWX(QRwR~w^i;nQdPj^{11~o3t{h`P~MygMx|HOPX%tXsnEOA>fFBedeU33Yx~_59X84`-hUap=ymBqc8_=e zXJ0AHhzvS^yv$SG(`m0>x{E^8F`u&eJ(a)Lt@-kAO77R3LtU3@X0!0{EwG4T-8z42 z@`rzOzWi!tInektcgxn$j9`t&6D!)di-I|~?Tzus+tW+_OU zBOPJG^i2Jk=Y-?xkG9WkdAoLt*%`^MJMCs?Hr>7-wUvpPk%4h>utA`KEHKPv`B=nQ zL;`E>*2qT+TP*1l-lo3#WLEad32P1HLDI@B5(Z)o*cI@D6bLgi{%2t|UYw?JA%`W?xT7A$?XFl} zX+CG(vMCB{-fr{pd|lDHbz#Hxjy)3f&IdyKXSc+pI<5$Nwf$h;y-8pD0*`A~XmRRD S-t=3uW{SGEL-b8SsSE(&xI?V~ literal 0 HcmV?d00001 diff --git a/samples/net/sockets/http_server/src/certificate.h b/samples/net/sockets/http_server/src/certificate.h new file mode 100644 index 00000000000000..52a3fa9c8ea18f --- /dev/null +++ b/samples/net/sockets/http_server/src/certificate.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2023 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __CERTIFICATE_H__ +#define __CERTIFICATE_H__ + +enum tls_tag { + /** The Certificate Authority public key */ + HTTP_SERVER_CA_CERTIFICATE_TAG, + /** Used for both the public and private server keys */ + HTTP_SERVER_CERTIFICATE_TAG, + /** Used for both the public and private client keys */ + HTTP_SERVER_CLIENT_CERTIFICATE_TAG, + PSK_TAG, +}; + +#if !defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) +static const unsigned char server_certificate[] = { +#include "https-server-cert.der.inc" +}; + +/* This is the private key in pkcs#8 format. */ +static const unsigned char private_key[] = { +#include "https-server-key.der.inc" +}; + +#else + +static const unsigned char ca_certificate[] = { +#include "ca.der.inc" +}; + +static const unsigned char server_certificate[] = { +#include "server.der.inc" +}; + +/* This is the private key in pkcs#8 format. */ +static const unsigned char private_key[] = { +#include "server_privkey.der.inc" +}; +#endif + +#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) +#include CONFIG_NET_SAMPLE_PSK_HEADER_FILE +#endif + +#endif /* __CERTIFICATE_H__ */ diff --git a/samples/net/sockets/http_server/src/dummy_psk.h b/samples/net/sockets/http_server/src/dummy_psk.h new file mode 100644 index 00000000000000..e67107266fda45 --- /dev/null +++ b/samples/net/sockets/http_server/src/dummy_psk.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2019 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef __DUMMY_PSK_H__ +#define __DUMMY_PSK_H__ + +static const unsigned char psk[] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, +0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}; +static const char psk_id[] = "PSK_identity"; + +#endif /* __DUMMY_PSK_H__ */ diff --git a/samples/net/sockets/http_server/src/https-server-cert.der b/samples/net/sockets/http_server/src/https-server-cert.der new file mode 100644 index 0000000000000000000000000000000000000000..bfcb335e31c8c37fd5c964276c42a3554abc3f4e GIT binary patch literal 767 zcmXqLV)|{+#Q1mtGZP~d6DPwv0r`WU3|LlA&)ap-DdR6;hMk(GhDiIJZH z=nO8VCPqevV+_^27sZ{kS1zxd!{1vz@zQs9)6L?K?!L`s{JC+`NsopH^5?fNiT_~s zYX3vyA1jYOyCT`$q&%G?~a`7n%!BhJR8NxJ8LeAXMj8@Z}=^MXr+0N72oA?D7SXK(^cx;@x^i)my z(tRQdLffsY{O=sUs>_nL`zz1ck4Bc)1848L{c-s}-C57(WQW}Pc-Q0S^$(^seJXV> z`k(h(@=aU)(3QD6qd7+wwtn5CeIu6c$fmF-&;}Dq9gkyFl=eiRu;X}cf0k(j@>)) zviDuwwgnHgTeUi?cV#qa|IX8EcwRM~bF02W-`hPi@~2*nwpEi<6R~VsvBJr1b>w9C z=I@pJi?_zcR{Tp^^LD$O*V@A~EolM$ literal 0 HcmV?d00001 diff --git a/samples/net/sockets/http_server/src/https-server-key.der b/samples/net/sockets/http_server/src/https-server-key.der new file mode 100644 index 0000000000000000000000000000000000000000..5a4d67372ea41873b1c69e5e9371f6f9d2c5a4bd GIT binary patch literal 1218 zcmV;z1U>sOf&{(-0RS)!1_>&LNQUrs4#*Aqyhl|0)hbn0LB1&4bc}v zYpJJsoDYq6k<#}^HM1Au-R*4w`LUA8NPyrU&$pys@HXnd;WPND#pcu*i-IND8FX-Y z?8a!x@6H;j@V5aqk^j?mZUVXnnkuZ%BEKsi!E!hvHR{@L-DjdJ88{gZMA30Lv~4DZ z*2ccUZ#?d=lspAiPOVdci_{}AX>uo%v^uOK=n$^;p9`jL({sug5z4-C09Gk9RLt5b zTP7))O<$p=xyviE4-fzZsSzwlv6-dHd}pP;6d)3}J9YgF3t-AMV@@HKpnBz{CM^S?O`maE}K1B+DL;kFThAp!#d009Dm0RaH7 z0UN?WjiWr2jsEeC*@o6{wYkmT#(VLVd8DRNY9H7lcyumSAs^->(9OQQ2?gklP=v-L`Gx}l}Epd9hrmzrWPB^HgY2; zPe4Raxg5}uhi0bmA2T-mx#s85P@au1X1#k-Aozb#I!LTKGTvnxtemE5>_qMcl?C!j z#SDE>AF8y#xd(^;D<~3x>O7vYf$#m);|U+hoAc_SeGMv2ZJY+*hf(xP2JocW!N5Gh>(fq?+ts}+mI(T~AV*HlNM#ec4c%-zD89*-5W zoj3kXL$XrmvJT)MNZtpI|8%|ly(cPqz-9@rTLkUAoS)`Hqn^ieJ#j$+4frJ&sg!>B1V-0 zfq+K~=0jzRp|HDkq&((1 z4^sTRXxZnW?SQnSc0LySo5cU}$nFBvF(&`13#hnd=8Im5cx&cpoOA&>{Ra-O67MCI z&{4EyJ}s*>fq2TSrW{4Sogwp8<_}h%jHv>FfdJOeMWN~48AK`JI_MJJDU z8=_kU!4}(t3vFMBFF}{=yak@NV(~@!ROfCqUOUOBjX|tSjTWBzA{$rPt$=l?X&Xg< zGCkVbG5nX724gmcghG9WqLN(tyh?m2u) + + + Zephyr HTTP Server + + +

Welcome to Zephyr HTTP Server!

+

This is a simple HTML file.

+ + diff --git a/samples/net/sockets/http_server/src/main.c b/samples/net/sockets/http_server/src/main.c new file mode 100644 index 00000000000000..dac4499029d4db --- /dev/null +++ b/samples/net/sockets/http_server/src/main.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2023, Emna Rekik + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(net_http_server_sample, LOG_LEVEL_DBG); + +static uint8_t index_html_gz[] = { +#include "index.html.gz.inc" +}; + +#if defined(CONFIG_NET_SAMPLE_HTTP_SERVICE) +static uint16_t test_http_service_port = CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT; +HTTP_SERVICE_DEFINE(test_http_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &test_http_service_port, 1, + 10, NULL); + +struct http_resource_detail_static index_html_gz_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_STATIC, + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + .content_encoding = "gzip", + }, + .static_data = index_html_gz, + .static_data_len = sizeof(index_html_gz), +}; + +HTTP_RESOURCE_DEFINE(index_html_gz_resource, test_http_service, "/", + &index_html_gz_resource_detail); + +static uint8_t recv_buffer[1024]; + +static int dyn_handler(struct http_client_ctx *client, enum http_data_status status, + uint8_t *buffer, size_t len, void *user_data) +{ +#define MAX_TEMP_PRINT_LEN 32 + static char print_str[MAX_TEMP_PRINT_LEN]; + enum http_method method = client->method; + static size_t processed; + + __ASSERT_NO_MSG(buffer != NULL); + + if (status == HTTP_SERVER_DATA_ABORTED) { + LOG_DBG("Transaction aborted after %zd bytes.", processed); + processed = 0; + return 0; + } + + processed += len; + + snprintf(print_str, sizeof(print_str), "%s received (%zd bytes)", + http_method_str(method), len); + LOG_HEXDUMP_DBG(buffer, len, print_str); + + if (status == HTTP_SERVER_DATA_FINAL) { + LOG_DBG("All data received (%zd bytes).", processed); + processed = 0; + } + + /* This will echo data back to client as the buffer and recv_buffer + * point to same area. + */ + return len; +} + +struct http_resource_detail_dynamic dyn_resource_detail = { + .common = { + .type = HTTP_RESOURCE_TYPE_DYNAMIC, + .bitmask_of_supported_http_methods = + BIT(HTTP_GET) | BIT(HTTP_POST), + }, + .cb = dyn_handler, + .data_buffer = recv_buffer, + .data_buffer_len = sizeof(recv_buffer), + .user_data = NULL, +}; + +HTTP_RESOURCE_DEFINE(dyn_resource, test_http_service, "/dynamic", + &dyn_resource_detail); + +#endif /* CONFIG_NET_SAMPLE_HTTP_SERVICE */ + +#if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) +#include "certificate.h" + +static const sec_tag_t sec_tag_list_verify_none[] = { + HTTP_SERVER_CERTIFICATE_TAG, +#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + PSK_TAG, +#endif + }; + +static uint16_t test_https_service_port = CONFIG_NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT; +HTTPS_SERVICE_DEFINE(test_https_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, + &test_https_service_port, 1, 10, NULL, + sec_tag_list_verify_none, sizeof(sec_tag_list_verify_none)); + +static struct http_resource_detail_static index_html_gz_resource_detail_https = { + .common = { + .type = HTTP_RESOURCE_TYPE_STATIC, + .bitmask_of_supported_http_methods = BIT(HTTP_GET), + .content_encoding = "gzip", + }, + .static_data = index_html_gz, + .static_data_len = sizeof(index_html_gz), +}; + +HTTP_RESOURCE_DEFINE(index_html_gz_resource_https, test_https_service, "/", + &index_html_gz_resource_detail_https); + +#endif /* CONFIG_NET_SAMPLE_HTTPS_SERVICE */ + +static void setup_tls(void) +{ +#if defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) +#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) + int err; + +#if defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) + err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, + TLS_CREDENTIAL_CA_CERTIFICATE, + ca_certificate, + sizeof(ca_certificate)); + if (err < 0) { + LOG_ERR("Failed to register CA certificate: %d", err); + } +#endif /* defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC) */ + + err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, + TLS_CREDENTIAL_SERVER_CERTIFICATE, + server_certificate, + sizeof(server_certificate)); + if (err < 0) { + LOG_ERR("Failed to register public certificate: %d", err); + } + + err = tls_credential_add(HTTP_SERVER_CERTIFICATE_TAG, + TLS_CREDENTIAL_PRIVATE_KEY, + private_key, sizeof(private_key)); + if (err < 0) { + LOG_ERR("Failed to register private key: %d", err); + } + +#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) + err = tls_credential_add(PSK_TAG, + TLS_CREDENTIAL_PSK, + psk, + sizeof(psk)); + if (err < 0) { + LOG_ERR("Failed to register PSK: %d", err); + } + + err = tls_credential_add(PSK_TAG, + TLS_CREDENTIAL_PSK_ID, + psk_id, + sizeof(psk_id) - 1); + if (err < 0) { + LOG_ERR("Failed to register PSK ID: %d", err); + } +#endif /* defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED) */ +#endif /* defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS) */ +#endif /* defined(CONFIG_NET_SAMPLE_HTTPS_SERVICE) */ +} + +int main(void) +{ + setup_tls(); + http_server_start(); + return 0; +} diff --git a/samples/net/sockets/http_server/src/not_found_page.html b/samples/net/sockets/http_server/src/not_found_page.html new file mode 100644 index 00000000000000..c4bf66f08ee1e6 --- /dev/null +++ b/samples/net/sockets/http_server/src/not_found_page.html @@ -0,0 +1,10 @@ + + + + 404 Not Found + + +

404 Not Found

+

The requested resource was not found.

+ + diff --git a/samples/net/sockets/http_server/src/server.der b/samples/net/sockets/http_server/src/server.der new file mode 100644 index 0000000000000000000000000000000000000000..2b664a4bdb2ce64d9e2f92d88aa163d09fd0a073 GIT binary patch literal 693 zcmXqLV%liX#5j{lBd#AN85K^Mn-N{1_Kd8 zAp-$6=1>-99?sN?#N2|MRA)y61#w;@0|P@ta|25QLnDJI34S9(LrX&=BNM0qioTru zik^@kDXYAcf~pQKuP)zo+30&- zdsL`W?2aE_c8Ub||GIFX(J^B};2(|hvNbb#i*={IPiDy3J$tJ&ci@?4VMWV=4&VCe zed*i}zE-9BtHZF9qVy(`sT+oy{ksJnS;amZ=bj_*v&j0}v(Aq0#9UNL&?l7Jj%zSgmElFXmI`$*a$X#J<0sy{~v`PEt_XN{9Kv4~>gL4f1N!%QHKI zrQ!?c2J27zSdg}K;<*B6sk_I_f9h;pVn08MKhh_xqvX6o-GpVLVd2xY%A(A-@$z5W zA6>qdW5xTj>8pMAgl1+(2pQNNu1#6e`Z4|)(;s_#+qPfTUHR2lm>=v4@vgY1wJ2i3 MBGv5t+z!hv0H2m3zyJUM literal 0 HcmV?d00001 diff --git a/samples/net/sockets/http_server/src/server_privkey.der b/samples/net/sockets/http_server/src/server_privkey.der new file mode 100644 index 0000000000000000000000000000000000000000..2269293fe790f2276d24bb62e5347e2d6e5b9cdf GIT binary patch literal 1219 zcmV;!1U&mNf&{+;0RS)!1_>&LNQUrsW5^Br2+u}0)hbn0Nqb)D1e?a zp8&aImt7ZC<#fYJP1_)U~2r>KV;Sh&|uxsbgd+Wqim>*RQP17 zN+MEv!KZt7vePp6ZiiY`B3-!n^tlvMkNVKSfk9}HQT!-(cC48Vb1jwcV*qTso3%p= zQOxF6a;8$l+WAY$!e4q1-E5KRYMu^m^R8*?f@AY^R3J|xb1OnZyf)d%@7jF-n#bq{w z_V0-_an4m}EhQL0a0eyJLfgYUma~AbF4TKUx0e^de%Z>SRLcd3_W}a}009Dm0RaG! zDnpyyq31e$(;f_OH=9&LUdAGWmcg)_U4%E0mb$XCnj(|v8LAHpDTtP?vr%m06^$EJ zZpnTE;H3hyxV~h-V=#o!93n{(=c4FC>CFRKQ-|zrZ1|YaIP9Ik-N}{ zy2<3cWREtdn{P+&|LN!)p7{mIkU|!Zt`2R(;Pg#_N=yr%0Vbp2xs8}fq?+{ zc_*4}atI@kiq43z4w}weDdyNNVAbB4NkS;27(x^wl z9J%b|Zc?z3;9TOiJK1`TB(hH8#oFnIv_f(!BjM<1Tj6}HlvN;ezG8sA3fPIW5j-m0 zrtNkO#a&BWxBBTNvSLcW2Sl27{uX5dfq?+z1E4J%6tye))MkM!X;Uf?8bH~Szs0u6 z*)cirwi2tZjOy@!RH&>XpF<1p??`R2z_I*@ponczcJ58;AN9n=lmO7)}?cPxq}S7K$e| z%_M>YTZQ&9fy?JR7<=cE*V;m7sn;&-g+MhbC^OY4hZM-K;ApehPU?Alz@8rI#vgD* ziCnquP~ol5;^064q^Ud%WP58WWvLp2efKx^7FEPDLiY hlYUM(QL<8v)b323|FJ#?NUg;s4_k!y09su`yV-?yRI&g7 literal 0 HcmV?d00001