1.. zephyr:code-sample:: sockets-http-server 2 :name: HTTP Server 3 :relevant-api: http_service http_server tls_credentials 4 5 Implement an HTTP(s) Server demonstrating various resource types. 6 7Overview 8-------- 9 10This sample application demonstrates the use of the :ref:`http_server_interface` library. 11This library provides high-level functions to simplify and abstract server implementation. 12The server supports the HTTP/1.1 protocol which can also be upgraded to HTTP/2, 13it also support native HTTP/2 protocol without upgrading. 14 15Requirement 16----------- 17 18`QEMU Networking <https://docs.zephyrproject.org/latest/connectivity/networking/qemu_setup.html#networking-with-qemu>`_ 19 20Building and running the server 21------------------------------- 22 23There are configuration files for various setups in the 24:zephyr_file:`samples/net/sockets/http_server` directory: 25 26.. list-table:: 27 28 * - :zephyr_file:`prj.conf <samples/net/sockets/http_server/prj.conf>` 29 - This is the standard default config. 30 31 * - :zephyr_file:`ieee802154-overlay.conf <samples/net/sockets/http_server/ieee802154-overlay.conf>` 32 - This overlay config can be added for IEEE 802.15.4 support. 33 34 * - :zephyr_file:`overlay-usbd.conf <samples/net/sockets/http_server/overlay-usbd.conf>` 35 - This overlay config can be added for connecting via network USB. 36 37 * - :zephyr_file:`overlay-tls.conf <samples/net/sockets/http_server/overlay-tls.conf>` 38 - This overlay config can be added to build the HTTPS variant. 39 40 * - :zephyr_file:`overlay-dhcpv4.conf <samples/net/sockets/http_server/overlay-dhcpv4.conf>` 41 - This overlay enables DHCPv4 client feature. 42 43To build and run the HTTP server application: 44 45.. code-block:: bash 46 47 $ west build -p auto -b <board_to_use> -t run samples/net/sockets/http_server 48 49For the HTTPS version: 50 51.. code-block:: bash 52 53 $ west build -p auto -b <board_to_use> -t run --test samples/net/sockets/http_server/sample.net.sockets.https.server 54 55When the server is up, we can make requests to the server using either HTTP/1.1 or 56HTTP/2 protocol from the host machine. 57 58**With HTTP/1.1:** 59 60- Using a browser: ``http://192.0.2.1/`` 61- Using curl: ``curl -v --compressed http://192.0.2.1/`` 62- Using ab (Apache Bench): ``ab -n10 http://192.0.2.1/`` 63 64**With HTTP/2:** 65 66- Using nghttp client: ``nghttp -v --no-dep http://192.0.2.1/`` 67- Using curl: ``curl --http2 -v --compressed http://192.0.2.1/`` 68- Using h2load: ``h2load -n10 http://192.0.2.1/`` 69 70Web browsers use stricter security settings for the HTTP/2 protocol. So to use HTTP/2 71with a web browser, you must ALPN (add ``-DCONFIG_NET_SAMPLE_HTTPS_USE_ALPN`` to 72the west build command) on top of the HTTPS build shown above. 73Additionally the server certificate must be signed by a CA certificate trusted 74by your browser. 75 76The best way to do this is to generate your own CA certificate: 77 78.. code-block:: bash 79 80 $ west build -b <board_to_use> -t sample_ca_cert samples/net/sockets/http_server 81 82Generate a server certificate signed by this CA certificate: 83 84.. code-block:: bash 85 86 $ west build -t sample_server_cert samples/net/sockets/http_server 87 88And then build the application with the newly generated server certificate and key: 89 90.. code-block:: bash 91 92 $ west build samples/net/sockets/http_server 93 94The CA certificate should be added to your browser's list of trusted authorities to 95enable usage of HTTP/2. If using Firefox, it may also be required to change the setting 96``network.http.http2.enforce-tls-profile`` to false, since it seems that using a CA 97certificate issued by an authority unknown to Firefox is considered a security error when 98using HTTP/2. 99 100Server Customization 101--------------------- 102 103The server sample contains several parameters that can be customized based on 104the requirements. These are the configurable parameters: 105 106- ``CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT``: Configures the service port. 107 108- ``CONFIG_HTTP_SERVER_MAX_CLIENTS``: Defines the maximum number of HTTP/2 109 clients that the server can handle simultaneously. 110 111- ``CONFIG_HTTP_SERVER_MAX_STREAMS``: Specifies the maximum number of HTTP/2 112 streams that can be established per client. 113 114- ``CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE``: Defines the buffer size allocated 115 for each client. This limits the maximum length of an individual HTTP header 116 supported. 117 118- ``CONFIG_HTTP_SERVER_MAX_URL_LENGTH``: Specifies the maximum length of an HTTP 119 URL that the server can process. 120 121- ``CONFIG_NET_SAMPLE_WEBSOCKET_SERVICE``: Enables Websocket service endpoint. 122 This allows a Websocket client to connect to ``/`` endpoint, all the data that 123 the client sends is echoed back. 124 125To customize these options, we can run ``west build -t menuconfig``, which provides 126us with an interactive configuration interface. Then we could navigate from the top-level 127menu to: ``-> Subsystems and OS Services -> Networking -> Network Protocols``. 128 129Websocket Connectivity 130---------------------- 131 132You can use a simple Websocket client application like this to test the Websocket 133connectivity. 134 135.. code-block:: python 136 137 import websocket 138 139 websocket.enableTrace(True) 140 ws = websocket.WebSocket() 141 ws.connect("ws://192.0.2.1/ws_echo") 142 ws.send("Hello, Server") 143 print(ws.recv()) 144 while True: 145 line = input("> ") 146 if line == "quit": 147 break 148 ws.send(line) 149 print(ws.recv()) 150 ws.close() 151 152 153Testing over USB 154---------------- 155 156Let's see a real example on how the HTTP(S) server can be tested on a real device 157using an USB connection toward a Linux host PC. For this purpose let's take an 158NRF52840 board as example. 159 160First of all build the sample enabling HTTPS service and flash the board: 161 162.. zephyr-app-commands:: 163 :zephyr-app: samples/net/sockets/http_server/ 164 :board: nrf52840dk/nrf52840 165 :goals: build 166 :gen-args: -DCONFIG_NET_SAMPLE_HTTPS_SERVICE=y -DEXTRA_CONF_FILE=overlay-netusb.conf 167 168Then connect the USB cable to the host PC and issue: 169 170.. code-block:: bash 171 172 $ ip link show 173 174to get the device name Linux assigned to the USB-Ethernet interface. For the 175following let's assume that the name is ``eth-device``. 176 177Now we need to configure IP and routing for this interface: 178 179.. code-block:: bash 180 181 $ sudo ip addr add 192.0.2.2/24 dev eth-device 182 $ sudo ip route add 192.0.2.0/24 dev eth-device 183 184Here: 185 186* we picked an IP address for the interface, i.e. ``192.0.2.2/24``, which is 187 different form the server one, i.e. :kconfig:option:`CONFIG_NET_CONFIG_MY_IPV4_ADDR`, 188 but in the allowed IP range defined by the ``/24`` mask. 189* we assume that 192.168.0.x range do not conflict with other addresses and 190 routes in the host system. If that's the case, then all IP addresses should 191 be fixed (sample, host IP interface, certificate). 192 193Once this is done, it should be possible to test either HTTP and HTTPS with 194``curl``: 195 196.. code-block:: bash 197 198 $ curl -v --compressed http://192.0.2.1 199 $ curl -v --compressed https://192.0.2.1 200 201.. note:: 202 203 To have a successful HTTPS connection ensure to update the CA certificates 204 of the host Linux system adding 205 :zephyr_file:`samples/net/sockets/http_server/src/certs/ca_cert.pem` to the 206 list of known CAs. 207 208Performance Analysis 209-------------------- 210 211CPU Usage Profiling 212******************* 213 214We can use ``perf`` to collect statistics about the CPU usage of our server 215running in native_sim board with the ``stat`` command: 216 217.. code-block:: console 218 219 $ sudo perf stat -p <pid_of_server> 220 221``perf stat`` will then start monitoring our server. We can let it run while 222sending requests to our server. Once we've collected enough data, we can 223stop ``perf stat``, which will print a summary of the performance statistics. 224 225Hotspot Analysis 226**************** 227 228``perf record`` and ``perf report`` can be used together to identify the 229functions in our code that consume the most CPU time: 230 231.. code-block:: console 232 233 $ sudo perf record -g -p <pid_of_server> -o perf.data 234 235After running our server under load (For example, using ApacheBench tool), 236we can stop the recording and analyze the data using: 237 238.. code-block:: console 239 240 $ sudo perf report -i perf.data 241 242After generating a file named ``perf.data`` which contains the profiling data, 243we can visualize it using ``FlameGraph`` tool. It's particularly useful for 244identifying the most expensive code-paths and inspect where our application is 245spending the most time. 246 247To do this, we need to convert the ``perf.data`` to a format that ``FlameGraph`` 248can understand: 249 250.. code-block:: console 251 252 $ sudo perf script | ~/FlameGraph/stackcollapse-perf.pl > out.perf-folded 253 254And, then, generate the ``FlameGraph``: 255 256.. code-block:: console 257 258 $ ~/FlameGraph/flamegraph.pl out.perf-folded > flamegraph.svg 259 260We can view flamegraph.svg using a web browser. 261