Skip to content

Commit 660149d

Browse files
jukkarcarlescufi
authored andcommitted
samples: net: http_server: Add HTTP server sample application
A simple HTTP server sample application. Signed-off-by: Emna Rekik <[email protected]> Signed-off-by: Jukka Rissanen <[email protected]> Signed-off-by: Robert Lubos <[email protected]>
1 parent 87f45d1 commit 660149d

File tree

16 files changed

+573
-0
lines changed

16 files changed

+573
-0
lines changed
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
find_package(Python REQUIRED COMPONENTS Interpreter)
7+
8+
project(http_server)
9+
10+
if(CONFIG_NET_SOCKETS_SOCKOPT_TLS AND
11+
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED AND
12+
(CONFIG_NET_SAMPLE_PSK_HEADER_FILE STREQUAL "dummy_psk.h"))
13+
add_custom_target(development_psk
14+
COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------"
15+
COMMAND ${CMAKE_COMMAND} -E echo "--- WARNING: Using dummy PSK! Only suitable for ---"
16+
COMMAND ${CMAKE_COMMAND} -E echo "--- development. Set NET_SAMPLE_PSK_HEADER_FILE to use ---"
17+
COMMAND ${CMAKE_COMMAND} -E echo "--- own pre-shared key. ---"
18+
COMMAND ${CMAKE_COMMAND} -E echo "----------------------------------------------------------"
19+
)
20+
add_dependencies(app development_psk)
21+
endif()
22+
23+
option(INCLUDE_HTML_CONTENT "Include the HTML content" ON)
24+
25+
target_sources(app PRIVATE src/main.c)
26+
27+
set(gen_dir ${ZEPHYR_BINARY_DIR}/include/generated/)
28+
29+
set(source_file_index src/index.html)
30+
generate_inc_file_for_target(app ${source_file_index} ${gen_dir}/index.html.gz.inc --gzip)
31+
32+
set(source_file_not_found src/not_found_page.html)
33+
generate_inc_file_for_target(app ${source_file_not_found} ${gen_dir}/not_found_page.html.gz.inc --gzip)
34+
35+
target_link_libraries(app PRIVATE zephyr_interface zephyr)
36+
37+
zephyr_linker_sources(SECTIONS sections-rom.ld)
38+
zephyr_linker_section_ifdef(CONFIG_NET_SAMPLE_HTTPS_SERVICE NAME
39+
http_resource_desc_test_https_service
40+
KVMA RAM_REGION GROUP RODATA_REGION
41+
SUBALIGN Z_LINK_ITERABLE_SUBALIGN)
42+
zephyr_linker_section_ifdef(CONFIG_NET_SAMPLE_HTTP_SERVICE NAME
43+
http_resource_desc_test_http_service
44+
KVMA RAM_REGION GROUP RODATA_REGION
45+
SUBALIGN Z_LINK_ITERABLE_SUBALIGN)
46+
47+
foreach(inc_file
48+
ca.der
49+
server.der
50+
server_privkey.der
51+
https-server-cert.der
52+
https-server-key.der
53+
)
54+
generate_inc_file_for_target(
55+
app
56+
src/${inc_file}
57+
${gen_dir}/${inc_file}.inc
58+
)
59+
endforeach()
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Config options for http2 server sample application
2+
3+
# Copyright (c) 2023, Emna Rekik
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
mainmenu "HTTP2 server sample application"
7+
8+
config NET_SAMPLE_HTTP_SERVICE
9+
bool "Enable http service"
10+
default y
11+
12+
config NET_SAMPLE_HTTP_SERVER_SERVICE_PORT
13+
int "Port number for http service"
14+
default 80
15+
depends on NET_SAMPLE_HTTP_SERVICE
16+
17+
config NET_SAMPLE_HTTPS_SERVICE
18+
bool "Enable https service"
19+
depends on NET_SOCKETS_SOCKOPT_TLS || TLS_CREDENTIALS
20+
21+
config NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT
22+
int "Port number for https service"
23+
default 443
24+
depends on NET_SAMPLE_HTTPS_SERVICE
25+
26+
config NET_SAMPLE_PSK_HEADER_FILE
27+
string "Header file containing PSK"
28+
default "dummy_psk.h"
29+
depends on MBEDTLS_KEY_EXCHANGE_PSK_ENABLED
30+
help
31+
Name of a header file containing a
32+
pre-shared key.
33+
34+
config NET_SAMPLE_CERTS_WITH_SC
35+
bool "Signed certificates"
36+
depends on NET_SOCKETS_SOCKOPT_TLS
37+
help
38+
Enable this flag, if you are interested to run this
39+
application with signed certificates and keys.
40+
41+
source "Kconfig.zephyr"
Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
Zephyr HTTP Server
2+
==================
3+
4+
Overview
5+
--------
6+
7+
This sample application demonstrates the use of the ``http_server`` library.
8+
This library provides high-level functions to simplify and abstract server implementation.
9+
The server supports the HTTP/1.1 protocol which can also be upgraded to HTTP/2,
10+
it also support native HTTP/2 protocol without upgrading.
11+
12+
Requirement
13+
-----------
14+
15+
`QEMU Networking <https://docs.zephyrproject.org/latest/connectivity/networking/qemu_setup.html#networking-with-qemu>`_
16+
17+
Building and running the server
18+
-------------------------------
19+
20+
To build and run the application:
21+
22+
.. code-block:: bash
23+
24+
$ west build -p auto -b <board_to_use> -t run samples/net/sockets/http_server
25+
26+
When the server is up, we can make requests to the server using either HTTP/1.1 or
27+
HTTP/2 protocol from the host machine.
28+
29+
**With HTTP/1.1:**
30+
31+
- Using a browser: ``http://192.0.2.1/``
32+
- Using curl: ``curl -v --compressed http://192.0.2.1/``
33+
- Using ab (Apache Bench): ``ab -n10 http://192.0.2.1/``
34+
35+
**With HTTP/2:**
36+
37+
- Using nghttp client: ``nghttp -v --no-dep http://192.0.2.1/``
38+
- Using curl: ``curl --http2 -v --compressed http://192.0.2.1/``
39+
- Using h2load: ``h2load -n10 http://192.0.2.1/``
40+
41+
Server Customization
42+
---------------------
43+
44+
The server sample contains several parameters that can be customized based on
45+
the requirements. These are the configurable parameters:
46+
47+
- ``CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT``: Configures the service port.
48+
49+
- ``CONFIG_HTTP_SERVER_MAX_CLIENTS``: Defines the maximum number of HTTP/2
50+
clients that the server can handle simultaneously.
51+
52+
- ``CONFIG_HTTP_SERVER_MAX_STREAMS``: Specifies the maximum number of HTTP/2
53+
streams that can be established per client.
54+
55+
- ``CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE``: Defines the buffer size allocated
56+
for each client. This limits the maximum length of an individual HTTP header
57+
supported.
58+
59+
- ``CONFIG_HTTP_SERVER_MAX_URL_LENGTH``: Specifies the maximum length of an HTTP
60+
URL that the server can process.
61+
62+
To customize these options, we can run ``west build -t menuconfig``, which provides
63+
us with an interactive configuration interface. Then we could navigate from the top-level
64+
menu to: ``-> Subsystems and OS Services -> Networking -> Network Protocols``.
65+
66+
Performance Analysis
67+
--------------------
68+
69+
CPU Usage Profiling
70+
*******************
71+
72+
We can use ``perf`` to collect statistics about the CPU usage of our server
73+
running in native_sim board with the ``stat`` command:
74+
75+
.. code-block:: bash
76+
77+
$ sudo perf stat -p <pid_of_server>
78+
79+
``perf stat`` will then start monitoring our server. We can let it run while
80+
sending requests to our server. Once we've collected enough data, we can
81+
stop ``perf stat``, which will print a summary of the performance statistics.
82+
83+
Hotspot Analysis
84+
****************
85+
86+
``perf record`` and ``perf report`` can be used together to identify the
87+
functions in our code that consume the most CPU time:
88+
89+
.. code-block:: bash
90+
91+
$ sudo perf record -g -p <pid_of_server> -o perf.data
92+
93+
After running our server under load (For example, using ApacheBench tool),
94+
we can stop the recording and analyze the data using:
95+
96+
.. code-block:: bash
97+
98+
$ sudo perf report -i perf.data
99+
100+
After generating a file named ``perf.data`` which contains the profiling data,
101+
we can visualize it using ``FlameGraph`` tool. It's particularly useful for
102+
identifying the most expensive code-paths and inspect where our application is
103+
spending the most time.
104+
105+
To do this, we need to convert the ``perf.data`` to a format that ``FlameGraph``
106+
can understand:
107+
108+
.. code-block:: bash
109+
110+
$ sudo perf script | ~/FlameGraph/stackcollapse-perf.pl > out.perf-folded
111+
112+
And, then, generate the ``FlameGraph``:
113+
114+
.. code-block:: bash
115+
116+
$ ~/FlameGraph/flamegraph.pl out.perf-folded > flamegraph.svg
117+
118+
We can view flamegraph.svg using a web browser.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# General config
2+
CONFIG_MAIN_STACK_SIZE=3072
3+
CONFIG_SHELL=y
4+
CONFIG_LOG=y
5+
CONFIG_ENTROPY_GENERATOR=y
6+
CONFIG_TEST_RANDOM_GENERATOR=y
7+
CONFIG_INIT_STACKS=y
8+
CONFIG_POSIX_MAX_FDS=32
9+
CONFIG_POSIX_API=y
10+
CONFIG_FDTABLE=y
11+
CONFIG_NET_SOCKETS_POLL_MAX=32
12+
13+
# Eventfd
14+
CONFIG_EVENTFD=y
15+
16+
# Networking config
17+
CONFIG_NETWORKING=y
18+
CONFIG_NET_IPV4=y
19+
CONFIG_NET_IPV6=y
20+
CONFIG_NET_TCP=y
21+
CONFIG_NET_SOCKETS=y
22+
CONFIG_NET_CONNECTION_MANAGER=y
23+
CONFIG_NET_SHELL=y
24+
CONFIG_NET_LOG=y
25+
26+
# JSON
27+
CONFIG_JSON_LIBRARY=y
28+
29+
# HTTP parser
30+
CONFIG_HTTP_PARSER_URL=y
31+
CONFIG_HTTP_PARSER=y
32+
CONFIG_HTTP_SERVER=y
33+
34+
# Network buffers
35+
CONFIG_NET_PKT_RX_COUNT=16
36+
CONFIG_NET_PKT_TX_COUNT=16
37+
CONFIG_NET_BUF_RX_COUNT=128
38+
CONFIG_NET_BUF_TX_COUNT=128
39+
CONFIG_NET_CONTEXT_NET_PKT_POOL=y
40+
41+
# IP address options
42+
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
43+
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
44+
CONFIG_NET_MAX_CONTEXTS=32
45+
CONFIG_NET_MAX_CONN=32
46+
47+
# Network address config
48+
CONFIG_NET_CONFIG_SETTINGS=y
49+
CONFIG_NET_CONFIG_NEED_IPV4=y
50+
CONFIG_NET_CONFIG_NEED_IPV6=y
51+
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.1"
52+
CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.2"
53+
CONFIG_NET_CONFIG_MY_IPV4_GW="192.0.2.2"
54+
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8::1"
55+
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8::2"
56+
57+
# TLS configuration
58+
CONFIG_MBEDTLS=y
59+
CONFIG_MBEDTLS_BUILTIN=y
60+
CONFIG_MBEDTLS_ENABLE_HEAP=y
61+
CONFIG_MBEDTLS_HEAP_SIZE=60000
62+
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
63+
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
64+
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=6
65+
CONFIG_TLS_CREDENTIALS=y
66+
CONFIG_TLS_MAX_CREDENTIALS_NUMBER=5
67+
68+
# Networking tweaks
69+
# Required to handle large number of consecutive connections,
70+
# e.g. when testing with ApacheBench.
71+
CONFIG_NET_TCP_TIME_WAIT_DELAY=0
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
sample:
2+
description: HTTP Server Sample
3+
name: http_server_sample
4+
common:
5+
harness: net
6+
min_ram: 192
7+
tags:
8+
- http
9+
- net
10+
- server
11+
- socket
12+
platform_exclude:
13+
- native_posix
14+
- native_posix/native/64
15+
tests:
16+
sample.net.sockets.http.server: {}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#include <zephyr/linker/iterable_sections.h>
2+
3+
ITERABLE_SECTION_ROM(http_resource_desc_test_http_service, Z_LINK_ITERABLE_SUBALIGN)
4+
ITERABLE_SECTION_ROM(http_resource_desc_test_https_service, Z_LINK_ITERABLE_SUBALIGN)
783 Bytes
Binary file not shown.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright (c) 2023 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef __CERTIFICATE_H__
8+
#define __CERTIFICATE_H__
9+
10+
enum tls_tag {
11+
/** The Certificate Authority public key */
12+
HTTP_SERVER_CA_CERTIFICATE_TAG,
13+
/** Used for both the public and private server keys */
14+
HTTP_SERVER_CERTIFICATE_TAG,
15+
/** Used for both the public and private client keys */
16+
HTTP_SERVER_CLIENT_CERTIFICATE_TAG,
17+
PSK_TAG,
18+
};
19+
20+
#if !defined(CONFIG_NET_SAMPLE_CERTS_WITH_SC)
21+
static const unsigned char server_certificate[] = {
22+
#include "https-server-cert.der.inc"
23+
};
24+
25+
/* This is the private key in pkcs#8 format. */
26+
static const unsigned char private_key[] = {
27+
#include "https-server-key.der.inc"
28+
};
29+
30+
#else
31+
32+
static const unsigned char ca_certificate[] = {
33+
#include "ca.der.inc"
34+
};
35+
36+
static const unsigned char server_certificate[] = {
37+
#include "server.der.inc"
38+
};
39+
40+
/* This is the private key in pkcs#8 format. */
41+
static const unsigned char private_key[] = {
42+
#include "server_privkey.der.inc"
43+
};
44+
#endif
45+
46+
#if defined(CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED)
47+
#include CONFIG_NET_SAMPLE_PSK_HEADER_FILE
48+
#endif
49+
50+
#endif /* __CERTIFICATE_H__ */
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/*
2+
* Copyright (c) 2019 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#ifndef __DUMMY_PSK_H__
8+
#define __DUMMY_PSK_H__
9+
10+
static const unsigned char psk[] = {0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
11+
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
12+
static const char psk_id[] = "PSK_identity";
13+
14+
#endif /* __DUMMY_PSK_H__ */
767 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)