-
Notifications
You must be signed in to change notification settings - Fork 6.5k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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]>
- Loading branch information
1 parent
87f45d1
commit 660149d
Showing
16 changed files
with
573 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <https://docs.zephyrproject.org/latest/connectivity/networking/qemu_setup.html#networking-with-qemu>`_ | ||
|
||
Building and running the server | ||
------------------------------- | ||
|
||
To build and run the application: | ||
|
||
.. code-block:: bash | ||
$ west build -p auto -b <board_to_use> -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 <pid_of_server> | ||
``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 <pid_of_server> -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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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: {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#include <zephyr/linker/iterable_sections.h> | ||
|
||
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) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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__ */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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__ */ |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<title>Zephyr HTTP Server</title> | ||
</head> | ||
<body> | ||
<h1>Welcome to Zephyr HTTP Server!</h1> | ||
<p>This is a simple HTML file.</p> | ||
</body> | ||
</html> |
Oops, something went wrong.