Skip to content

Commit 405ce47

Browse files
net: http: service: extend HTTP service with config
Update the HTTP service API to allow setting per-service configuration, currently it is only custom socket creation callback, but in the future it can be extended with other parameters Signed-off-by: Andrey Dodonov <Andrey.Dodonov@endress.com>
1 parent 0f8b7b7 commit 405ce47

File tree

12 files changed

+106
-27
lines changed

12 files changed

+106
-27
lines changed

doc/connectivity/networking/api/http_server.rst

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ macro:
106106
107107
static uint16_t http_service_port = 80;
108108
109-
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL, NULL);
109+
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL, NULL, NULL);
110110
111111
Alternatively, an HTTPS service can be defined with
112112
:c:macro:`HTTPS_SERVICE_DEFINE`:
@@ -124,7 +124,62 @@ Alternatively, an HTTPS service can be defined with
124124
};
125125
126126
HTTPS_SERVICE_DEFINE(my_service, "0.0.0.0", &https_service_port, 1, 10,
127-
NULL, NULL, sec_tag_list, sizeof(sec_tag_list));
127+
NULL, NULL, NULL, sec_tag_list, sizeof(sec_tag_list));
128+
129+
Per-service configuration
130+
=========================
131+
132+
HTTP services support individual service configuration,
133+
for now it includes only socket creation through
134+
the ``http_service_config`` structure. This allows applications to customize
135+
socket creation behavior, for example to set specific socket options or use
136+
custom socket types.
137+
138+
To use custom socket creation:
139+
140+
.. code-block:: c
141+
142+
static int my_socket_create(const struct http_service_desc *svc, int af, int proto)
143+
{
144+
int fd;
145+
146+
/* Create socket with custom parameters */
147+
fd = zsock_socket(af, SOCK_STREAM, proto);
148+
if (fd < 0) {
149+
return fd;
150+
}
151+
152+
/* Set custom socket options */
153+
/* Add any other custom socket configuration */
154+
155+
return fd;
156+
}
157+
158+
static const struct http_service_config my_service_config = {
159+
.socket_create = my_socket_create,
160+
};
161+
162+
static uint16_t http_service_port = 80;
163+
164+
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10,
165+
NULL, NULL, &my_service_config);
166+
167+
The custom socket creation function receives:
168+
- ``svc``: Pointer to the service descriptor
169+
- ``af``: Address family (AF_INET or AF_INET6)
170+
- ``proto``: Protocol (IPPROTO_TCP or IPPROTO_TLS_1_2 for HTTPS)
171+
172+
The function should return the socket file descriptor on success, or a negative error code on failure.
173+
174+
If no custom configuration is needed, simply pass ``NULL`` for the config parameter:
175+
176+
.. code-block:: c
177+
178+
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10,
179+
NULL, NULL, NULL);
180+
181+
Fallback Resources
182+
==================
128183

129184
The ``_res_fallback`` parameter can be used when defining an HTTP/HTTPS service to
130185
specify a fallback resource which will be used if no other resource matches the
@@ -160,7 +215,7 @@ customised 404 response.
160215
};
161216
162217
/* Register a fallback resource to handle any unknown path */
163-
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL, &default_detail);
218+
HTTP_SERVICE_DEFINE(my_service, "0.0.0.0", &http_service_port, 1, 10, NULL, &default_detail, NULL);
164219
165220
.. note::
166221

doc/releases/migration-guide-4.2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -513,7 +513,7 @@ Networking
513513
alternative, ``AF_PACKET/SOCK_DGRAM/ETH_P_ALL`` or ``AF_INET(6)/SOCK_RAW/IPPROTO_IP``
514514
sockets can be used, depending on the actual use case.
515515

516-
* The HTTP server now respects the configured ``_concurrent`` and ``_backlog`` values. Check that
516+
* The HTTP server now respects the configured ``_concurrent``, ``_backlog`` and ``_config`` values. Check that
517517
you provide applicable values to :c:macro:`HTTP_SERVICE_DEFINE_EMPTY`,
518518
:c:macro:`HTTPS_SERVICE_DEFINE_EMPTY`, :c:macro:`HTTP_SERVICE_DEFINE` and
519519
:c:macro:`HTTPS_SERVICE_DEFINE`.

include/zephyr/net/http/service.h

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@ struct http_service_runtime_data {
6969
int num_clients;
7070
};
7171

72+
struct http_service_desc;
73+
74+
/** Custom socket creation function type */
75+
typedef int (*http_socket_create_fn)(const struct http_service_desc *svc, int af, int proto);
76+
77+
/** HTTP service configuration */
78+
struct http_service_config {
79+
/** Custom socket creation for the service if needed */
80+
http_socket_create_fn socket_create;
81+
/* If any more service-specific configuration is needed, it can be added here. */
82+
};
83+
7284
struct http_service_desc {
7385
const char *host;
7486
uint16_t *port;
@@ -80,14 +92,15 @@ struct http_service_desc {
8092
struct http_resource_desc *res_begin;
8193
struct http_resource_desc *res_end;
8294
struct http_resource_detail *res_fallback;
95+
const struct http_service_config *config;
8396
#if defined(CONFIG_NET_SOCKETS_SOCKOPT_TLS)
8497
const sec_tag_t *sec_tag_list;
8598
size_t sec_tag_list_size;
8699
#endif
87100
};
88101

89102
#define __z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
90-
_res_fallback, _res_begin, _res_end, ...) \
103+
_res_fallback, _res_begin, _res_end, _config, ...) \
91104
BUILD_ASSERT(_concurrent <= CONFIG_HTTP_SERVER_MAX_CLIENTS, \
92105
"can't accept more then MAX_CLIENTS"); \
93106
BUILD_ASSERT(_backlog > 0, "backlog can't be 0"); \
@@ -104,6 +117,7 @@ struct http_service_desc {
104117
.res_begin = (_res_begin), \
105118
.res_end = (_res_end), \
106119
.res_fallback = (_res_fallback), \
120+
.config = (_config), \
107121
COND_CODE_1(CONFIG_NET_SOCKETS_SOCKOPT_TLS, \
108122
(.sec_tag_list = COND_CODE_0(NUM_VA_ARGS_LESS_1(__VA_ARGS__), (NULL), \
109123
(GET_ARG_N(1, __VA_ARGS__))),), ()) \
@@ -133,11 +147,12 @@ struct http_service_desc {
133147
* @param _backlog Maximum number of queued connections. (min. 1)
134148
* @param _detail User-defined detail associated with the service.
135149
* @param _res_fallback Fallback resource to be served if no other resource matches path
150+
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
136151
*/
137152
#define HTTP_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
138-
_res_fallback) \
153+
_res_fallback, _config) \
139154
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
140-
_res_fallback, NULL, NULL)
155+
_res_fallback, NULL, NULL, _config)
141156

142157
/**
143158
* @brief Define an HTTPS service without static resources.
@@ -158,13 +173,14 @@ struct http_service_desc {
158173
* @param _backlog Maximum number of queued connections. (min. 1)
159174
* @param _detail User-defined detail associated with the service.
160175
* @param _res_fallback Fallback resource to be served if no other resource matches path
176+
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
161177
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
162178
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
163179
*/
164180
#define HTTPS_SERVICE_DEFINE_EMPTY(_name, _host, _port, _concurrent, _backlog, _detail, \
165-
_res_fallback, _sec_tag_list, _sec_tag_list_size) \
181+
_res_fallback, _config, _sec_tag_list, _sec_tag_list_size) \
166182
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
167-
_res_fallback, NULL, NULL, \
183+
_res_fallback, NULL, NULL, _config, \
168184
_sec_tag_list, _sec_tag_list_size); \
169185
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
170186
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")
@@ -188,14 +204,16 @@ struct http_service_desc {
188204
* @param _backlog Maximum number of queued connections. (min. 1)
189205
* @param _detail User-defined detail associated with the service.
190206
* @param _res_fallback Fallback resource to be served if no other resource matches path
207+
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
191208
*/
192-
#define HTTP_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, _res_fallback) \
209+
#define HTTP_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, _res_fallback, \
210+
_config) \
193211
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
194212
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
195213
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
196214
_res_fallback, \
197215
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
198-
&_CONCAT(_http_resource_desc_##_name, _list_end)[0]);
216+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config);
199217

200218
/**
201219
* @brief Define an HTTPS service with static resources.
@@ -216,17 +234,18 @@ struct http_service_desc {
216234
* @param _backlog Maximum number of queued connections. (min. 1)
217235
* @param _detail User-defined detail associated with the service.
218236
* @param _res_fallback Fallback resource to be served if no other resource matches path
237+
* @param _config Pointer to http_service_config structure (can be NULL for default behavior)
219238
* @param _sec_tag_list TLS security tag list used to setup a HTTPS socket.
220239
* @param _sec_tag_list_size TLS security tag list size used to setup a HTTPS socket.
221240
*/
222241
#define HTTPS_SERVICE_DEFINE(_name, _host, _port, _concurrent, _backlog, _detail, \
223-
_res_fallback, _sec_tag_list, _sec_tag_list_size) \
242+
_res_fallback, _config, _sec_tag_list, _sec_tag_list_size) \
224243
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_start)[]; \
225244
extern struct http_resource_desc _CONCAT(_http_resource_desc_##_name, _list_end)[]; \
226245
__z_http_service_define(_name, _host, _port, _concurrent, _backlog, _detail, \
227246
_res_fallback, \
228247
&_CONCAT(_http_resource_desc_##_name, _list_start)[0], \
229-
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], \
248+
&_CONCAT(_http_resource_desc_##_name, _list_end)[0], _config, \
230249
_sec_tag_list, _sec_tag_list_size); \
231250
BUILD_ASSERT(IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS), \
232251
"TLS is required for HTTP secure (CONFIG_NET_SOCKETS_SOCKOPT_TLS)")

include/zephyr/shell/shell_websocket.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ int shell_websocket_enable(const struct shell *sh);
122122
SHELL_WEBSOCKET_SERVICE_COUNT, \
123123
NULL, \
124124
NULL, \
125+
NULL, \
125126
_sec_tag_list, \
126127
_sec_tag_list_size); \
127128
DEFINE_WEBSOCKET_SERVICE(_service); \
@@ -137,7 +138,7 @@ int shell_websocket_enable(const struct shell *sh);
137138
&SHELL_WS_PORT_NAME(_service), \
138139
SHELL_WEBSOCKET_SERVICE_COUNT, \
139140
SHELL_WEBSOCKET_SERVICE_COUNT, \
140-
NULL, NULL); \
141+
NULL, NULL, NULL); \
141142
DEFINE_WEBSOCKET_SERVICE(_service)
142143

143144
#endif /* CONFIG_NET_SOCKETS_SOCKOPT_TLS */

samples/net/prometheus/src/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ struct app_context {
4040
#if defined(CONFIG_NET_SAMPLE_HTTP_SERVICE)
4141
static uint16_t test_http_service_port = CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT;
4242
HTTP_SERVICE_DEFINE(test_http_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &test_http_service_port,
43-
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL);
43+
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL);
4444

4545
static int dyn_handler(struct http_client_ctx *client, enum http_data_status status,
4646
const struct http_request_ctx *request_ctx,
@@ -99,7 +99,7 @@ const sec_tag_t sec_tag_list_verify_none[] = {
9999

100100
static uint16_t test_https_service_port = CONFIG_NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT;
101101
HTTPS_SERVICE_DEFINE(test_https_service, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &test_https_service_port,
102-
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, sec_tag_list_verify_none,
102+
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL, sec_tag_list_verify_none,
103103
sizeof(sec_tag_list_verify_none));
104104

105105
HTTP_RESOURCE_DEFINE(index_html_gz_resource_https, test_https_service, "/metrics",

samples/net/sockets/http_server/src/main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ struct http_resource_detail_websocket ws_netstats_resource_detail = {
248248
#if defined(CONFIG_NET_SAMPLE_HTTP_SERVICE)
249249
static uint16_t test_http_service_port = CONFIG_NET_SAMPLE_HTTP_SERVER_SERVICE_PORT;
250250
HTTP_SERVICE_DEFINE(test_http_service, NULL, &test_http_service_port,
251-
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL);
251+
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL);
252252

253253
HTTP_RESOURCE_DEFINE(index_html_gz_resource, test_http_service, "/",
254254
&index_html_gz_resource_detail);
@@ -281,7 +281,7 @@ static const sec_tag_t sec_tag_list_verify_none[] = {
281281

282282
static uint16_t test_https_service_port = CONFIG_NET_SAMPLE_HTTPS_SERVER_SERVICE_PORT;
283283
HTTPS_SERVICE_DEFINE(test_https_service, NULL, &test_https_service_port,
284-
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, sec_tag_list_verify_none,
284+
CONFIG_HTTP_SERVER_MAX_CLIENTS, 10, NULL, NULL, NULL, sec_tag_list_verify_none,
285285
sizeof(sec_tag_list_verify_none));
286286

287287
HTTP_RESOURCE_DEFINE(index_html_gz_resource_https, test_https_service, "/",

subsys/net/lib/http/http_server_core.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,11 @@ int http_server_init(struct http_server_ctx *ctx)
156156
proto = IPPROTO_TCP;
157157
}
158158

159-
fd = zsock_socket(af, SOCK_STREAM, proto);
159+
if (svc->config != NULL && svc->config->socket_create != NULL) {
160+
fd = svc->config->socket_create(svc, af, proto);
161+
} else {
162+
fd = zsock_socket(af, SOCK_STREAM, proto);
163+
}
160164
if (fd < 0) {
161165
LOG_ERR("socket: %d", errno);
162166
failed++;

tests/net/lib/http_client/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
static uint16_t test_http_service_port = SERVER_PORT;
1717
HTTP_SERVICE_DEFINE(test_http_service, SERVER_IPV6_ADDR,
18-
&test_http_service_port, 1, 10, NULL, NULL);
18+
&test_http_service_port, 1, 10, NULL, NULL, NULL);
1919

2020
static const char static_resource_payload[] = LOREM_IPSUM_SHORT;
2121
struct http_resource_detail_static static_resource_detail = {

tests/net/lib/http_server/common/src/main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,14 @@ static struct http_resource_detail detail[] = {
5050
* the paths (and implementation-specific details) are known at compile time.
5151
*/
5252
static const uint16_t service_A_port = 4242;
53-
HTTP_SERVICE_DEFINE(service_A, "a.service.com", &service_A_port, 4, 2, DETAIL(0), NULL);
53+
HTTP_SERVICE_DEFINE(service_A, "a.service.com", &service_A_port, 4, 2, DETAIL(0), NULL, NULL);
5454
HTTP_RESOURCE_DEFINE(resource_0, service_A, "/", RES(0));
5555
HTTP_RESOURCE_DEFINE(resource_1, service_A, "/index.html", RES(1));
5656
HTTP_RESOURCE_DEFINE(resource_2, service_A, "/fs/*", RES(5));
5757

5858
/* ephemeral port of 0 */
5959
static uint16_t service_B_port;
60-
HTTP_SERVICE_DEFINE(service_B, "b.service.com", &service_B_port, 7, 3, DETAIL(1), NULL);
60+
HTTP_SERVICE_DEFINE(service_B, "b.service.com", &service_B_port, 7, 3, DETAIL(1), NULL, NULL);
6161
HTTP_RESOURCE_DEFINE(resource_3, service_B, "/foo.htm", RES(2));
6262
HTTP_RESOURCE_DEFINE(resource_4, service_B, "/bar/baz.php", RES(3));
6363

@@ -71,7 +71,7 @@ HTTP_SERVICE_DEFINE_EMPTY(service_C, "192.168.1.1", &service_C_port, 5, 9, DETAI
7171

7272
/* Wildcard resources */
7373
static uint16_t service_D_port = service_A_port + 1;
74-
HTTP_SERVICE_DEFINE(service_D, "2001:db8::1", &service_D_port, 7, 3, DETAIL(3), NULL);
74+
HTTP_SERVICE_DEFINE(service_D, "2001:db8::1", &service_D_port, 7, 3, DETAIL(3), NULL, NULL);
7575
HTTP_RESOURCE_DEFINE(resource_5, service_D, "/foo1.htm*", RES(0));
7676
HTTP_RESOURCE_DEFINE(resource_6, service_D, "/fo*", RES(1));
7777
HTTP_RESOURCE_DEFINE(resource_7, service_D, "/f[ob]o3.html", RES(1));
@@ -82,7 +82,7 @@ HTTP_RESOURCE_DEFINE(resource_12, service_D, "/foo/b?r", RES(3));
8282

8383
/* Default resource in case of no match */
8484
static uint16_t service_E_port = 8080;
85-
HTTP_SERVICE_DEFINE(service_E, "192.0.2.1", &service_E_port, 1, 1, NULL, DETAIL(0));
85+
HTTP_SERVICE_DEFINE(service_E, "192.0.2.1", &service_E_port, 1, 1, NULL, DETAIL(0), NULL);
8686
HTTP_RESOURCE_DEFINE(resource_10, service_E, "/index.html", RES(4));
8787

8888
ZTEST(http_service, test_HTTP_SERVICE_DEFINE)

tests/net/lib/http_server/core/src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ BUILD_ASSERT(sizeof(long_payload) - 1 > CONFIG_HTTP_SERVER_CLIENT_BUFFER_SIZE,
235235

236236
static uint16_t test_http_service_port = SERVER_PORT;
237237
HTTP_SERVICE_DEFINE(test_http_service, SERVER_IPV4_ADDR,
238-
&test_http_service_port, 1, 10, NULL, NULL);
238+
&test_http_service_port, 1, 10, NULL, NULL, NULL);
239239

240240
static const char static_resource_payload[] = TEST_STATIC_PAYLOAD;
241241
struct http_resource_detail_static static_resource_detail = {

0 commit comments

Comments
 (0)