net/http: Add the HTTP/1.1 API
This patch adds the HTTP/1.1 API for Zephyr. This API consists of client and server context structures enabled via Kconfig variables. HTTP parser support is enabled via the CONFIG_HTTP_PARSER configuration variable. Currently, this API only includes support for writing HTTP requests (client mode) and HTTP responses (server mode). TLS support is not considered in this iteration. Supported HTTP methods: GET, HEAD, OPTIONS and POST. Supported HTTP responses: 400, 403 404. The http_response routine may be used to write any HTTP status code, for example 200 OK. Jira: ZEP-1701 Change-Id: Ic9ccd4d4578d6d0f3a439976ea332b031644ca7d Signed-off-by: Flavio Santes <flavio.santes@intel.com>
This commit is contained in:
parent
e29202593d
commit
8308b9bd2d
12 changed files with 448 additions and 4 deletions
123
include/net/http.h
Normal file
123
include/net/http.h
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __HTTP_H__
|
||||||
|
#define __HTTP_H__
|
||||||
|
|
||||||
|
#if defined(CONFIG_HTTP_CLIENT)
|
||||||
|
|
||||||
|
#include <net/net_context.h>
|
||||||
|
|
||||||
|
struct http_client_request {
|
||||||
|
/** The HTTP method: GET, HEAD, OPTIONS, POST */
|
||||||
|
char *method;
|
||||||
|
/** The URL for this request, for example: /index.html */
|
||||||
|
char *url;
|
||||||
|
/** The HTTP protocol: HTTP/1.1 */
|
||||||
|
char *protocol;
|
||||||
|
/** The HTTP header fields (application specific)
|
||||||
|
* The Content-Type may be specified here or in the next field.
|
||||||
|
* Depending on your application, the Content-Type may vary, however
|
||||||
|
* some header fields may remain constant through the application's
|
||||||
|
* life cycle.
|
||||||
|
*/
|
||||||
|
char *header_fields;
|
||||||
|
/** The value of the Content-Type header field, may be NULL */
|
||||||
|
char *content_type_value;
|
||||||
|
/** Payload, may be NULL */
|
||||||
|
char *payload;
|
||||||
|
/** Payload size, may be 0 */
|
||||||
|
uint16_t payload_size;
|
||||||
|
};
|
||||||
|
|
||||||
|
int http_request(struct net_context *net_ctx, int32_t timeout,
|
||||||
|
struct http_client_request *req);
|
||||||
|
|
||||||
|
int http_request_get(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields);
|
||||||
|
|
||||||
|
int http_request_head(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields);
|
||||||
|
|
||||||
|
int http_request_options(struct net_context *net_ctx, int32_t timeout,
|
||||||
|
char *url, char *header_fields);
|
||||||
|
|
||||||
|
int http_request_post(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields, char *content_type_value,
|
||||||
|
char *payload);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(CONFIG_HTTP_SERVER)
|
||||||
|
|
||||||
|
#include <net/net_context.h>
|
||||||
|
|
||||||
|
#if defined(CONFIG_HTTP_PARSER)
|
||||||
|
#include <net/http_parser.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* HTTP server context state */
|
||||||
|
enum HTTP_CTX_STATE {
|
||||||
|
HTTP_CTX_FREE = 0,
|
||||||
|
HTTP_CTX_IN_USE
|
||||||
|
};
|
||||||
|
|
||||||
|
/* HTTP header fields struct */
|
||||||
|
struct http_field_value {
|
||||||
|
/** Field name, this variable will point to the beginning of the string
|
||||||
|
* containing the HTTP field name
|
||||||
|
*/
|
||||||
|
const char *key;
|
||||||
|
/** Length of the field name */
|
||||||
|
uint16_t key_len;
|
||||||
|
|
||||||
|
/** Value, this variable will point to the beginning of the string
|
||||||
|
* containing the field value
|
||||||
|
*/
|
||||||
|
const char *value;
|
||||||
|
/** Length of the field value */
|
||||||
|
uint16_t value_len;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The HTTP server context struct */
|
||||||
|
struct http_server_ctx {
|
||||||
|
uint8_t state;
|
||||||
|
|
||||||
|
/** Collection of header fields */
|
||||||
|
struct http_field_value field_values[CONFIG_HTTP_HEADER_FIELD_ITEMS];
|
||||||
|
/** Number of header field elements */
|
||||||
|
uint16_t field_values_ctr;
|
||||||
|
|
||||||
|
/** HTTP Request URL */
|
||||||
|
const char *url;
|
||||||
|
/** URL's length */
|
||||||
|
uint16_t url_len;
|
||||||
|
|
||||||
|
/**IP stack network context */
|
||||||
|
struct net_context *net_ctx;
|
||||||
|
|
||||||
|
/** Network timeout */
|
||||||
|
int32_t timeout;
|
||||||
|
|
||||||
|
#if defined(CONFIG_HTTP_PARSER)
|
||||||
|
/** HTTP parser */
|
||||||
|
struct http_parser parser;
|
||||||
|
/** HTTP parser settings */
|
||||||
|
struct http_parser_settings parser_settings;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
int http_response(struct http_server_ctx *ctx, const char *http_header,
|
||||||
|
const char *html_payload);
|
||||||
|
|
||||||
|
int http_response_400(struct http_server_ctx *ctx, const char *html_payload);
|
||||||
|
|
||||||
|
int http_response_403(struct http_server_ctx *ctx, const char *html_payload);
|
||||||
|
|
||||||
|
int http_response_404(struct http_server_ctx *ctx, const char *html_payload);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -16,6 +16,7 @@ CONFIG_NET_NBUF_TX_DATA_COUNT=16
|
||||||
CONFIG_NET_IPV4=n
|
CONFIG_NET_IPV4=n
|
||||||
CONFIG_NET_IPV6=y
|
CONFIG_NET_IPV6=y
|
||||||
|
|
||||||
|
CONFIG_HTTP=y
|
||||||
CONFIG_HTTP_PARSER=y
|
CONFIG_HTTP_PARSER=y
|
||||||
CONFIG_STDOUT_CONSOLE=y
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
|
||||||
|
@ -33,3 +34,4 @@ CONFIG_NET_SAMPLES_PEER_IPV4_ADDR="192.168.1.10"
|
||||||
# See the config.h file and the LINEARIZE_BUFFER define
|
# See the config.h file and the LINEARIZE_BUFFER define
|
||||||
#
|
#
|
||||||
#CONFIG_NET_NBUF_DATA_SIZE=512
|
#CONFIG_NET_NBUF_DATA_SIZE=512
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ CONFIG_NET_IPV6=n
|
||||||
# Enable IPv4 support
|
# Enable IPv4 support
|
||||||
CONFIG_NET_IPV4=y
|
CONFIG_NET_IPV4=y
|
||||||
|
|
||||||
|
CONFIG_HTTP=y
|
||||||
CONFIG_HTTP_PARSER=y
|
CONFIG_HTTP_PARSER=y
|
||||||
|
|
||||||
CONFIG_STDOUT_CONSOLE=y
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
|
||||||
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
CONFIG_NET_SAMPLES_IP_ADDRESSES=y
|
||||||
|
|
|
@ -16,6 +16,7 @@ CONFIG_NET_IFACE_UNICAST_IPV4_ADDR_COUNT=3
|
||||||
|
|
||||||
CONFIG_STDOUT_CONSOLE=y
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
|
||||||
|
CONFIG_HTTP=y
|
||||||
CONFIG_HTTP_PARSER=y
|
CONFIG_HTTP_PARSER=y
|
||||||
|
|
||||||
# Enable IPv6 support
|
# Enable IPv6 support
|
||||||
|
|
|
@ -17,6 +17,7 @@ CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=2
|
||||||
|
|
||||||
CONFIG_STDOUT_CONSOLE=y
|
CONFIG_STDOUT_CONSOLE=y
|
||||||
|
|
||||||
|
CONFIG_HTTP=y
|
||||||
CONFIG_HTTP_PARSER=y
|
CONFIG_HTTP_PARSER=y
|
||||||
|
|
||||||
# Enable IPv6 support
|
# Enable IPv6 support
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
obj-$(CONFIG_ZOAP) += zoap/
|
obj-$(CONFIG_ZOAP) += zoap/
|
||||||
obj-$(CONFIG_DNS_RESOLVER) += dns/
|
obj-$(CONFIG_DNS_RESOLVER) += dns/
|
||||||
obj-$(CONFIG_MQTT_LIB) += mqtt/
|
obj-$(CONFIG_MQTT_LIB) += mqtt/
|
||||||
obj-$(CONFIG_HTTP_PARSER) += http/
|
obj-$(CONFIG_HTTP) += http/
|
||||||
|
|
|
@ -10,6 +10,6 @@ ifdef CONFIG_MQTT_LIB
|
||||||
include $(srctree)/subsys/net/lib/mqtt/Makefile
|
include $(srctree)/subsys/net/lib/mqtt/Makefile
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_HTTP_PARSER
|
ifdef CONFIG_HTTP
|
||||||
include $(srctree)/subsys/net/lib/http/Makefile
|
include $(srctree)/subsys/net/lib/http/Makefile
|
||||||
endif
|
endif
|
||||||
|
|
|
@ -3,10 +3,43 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
#
|
#
|
||||||
|
|
||||||
|
config HTTP
|
||||||
|
bool
|
||||||
|
prompt "HTTP support"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
This option enables the HTTP library
|
||||||
|
|
||||||
|
config HTTP_SERVER
|
||||||
|
bool
|
||||||
|
prompt "HTTP server support"
|
||||||
|
default n
|
||||||
|
depends on HTTP
|
||||||
|
help
|
||||||
|
Enables HTTP server routines
|
||||||
|
|
||||||
|
config HTTP_HEADER_FIELD_ITEMS
|
||||||
|
int
|
||||||
|
prompt "HTTP header field max number of items"
|
||||||
|
depends on HTTP_SERVER
|
||||||
|
default 8
|
||||||
|
help
|
||||||
|
Number of HTTP header field items that an HTTP server
|
||||||
|
application will handle
|
||||||
|
|
||||||
|
config HTTP_CLIENT
|
||||||
|
bool
|
||||||
|
prompt "HTTP client support"
|
||||||
|
default n
|
||||||
|
depends on HTTP
|
||||||
|
help
|
||||||
|
Enables HTTP client routines
|
||||||
|
|
||||||
config HTTP_PARSER
|
config HTTP_PARSER
|
||||||
bool
|
bool
|
||||||
prompt "HTTP Parser support"
|
prompt "HTTP Parser support"
|
||||||
default n
|
default n
|
||||||
|
depends on HTTP
|
||||||
help
|
help
|
||||||
This option enables the http_parser library from nodejs.
|
This option enables the http_parser library from nodejs.
|
||||||
This parser requires some string-related routines commonly
|
This parser requires some string-related routines commonly
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
ccflags-$(CONFIG_HTTP_PARSER_STRICT) += -DHTTP_PARSER_STRICT
|
ccflags-$(CONFIG_HTTP_PARSER_STRICT) += -DHTTP_PARSER_STRICT
|
||||||
|
|
||||||
obj-y := http_parser.o
|
obj-$(CONFIG_HTTP_PARSER) := http_parser.o
|
||||||
|
obj-$(CONFIG_HTTP_CLIENT) += http_client.o
|
||||||
|
obj-$(CONFIG_HTTP_SERVER) += http_server.o
|
||||||
|
|
154
subsys/net/lib/http/http_client.c
Normal file
154
subsys/net/lib/http/http_client.c
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <net/http.h>
|
||||||
|
|
||||||
|
#include <net/nbuf.h>
|
||||||
|
#include <misc/printk.h>
|
||||||
|
|
||||||
|
/* HTTP client defines */
|
||||||
|
#define HTTP_PROTOCOL "HTTP/1.1"
|
||||||
|
#define HTTP_EOF "\r\n\r\n"
|
||||||
|
|
||||||
|
#define HTTP_CONTENT_TYPE "Content-Type: "
|
||||||
|
#define HTTP_CONT_LEN_SIZE 64
|
||||||
|
|
||||||
|
int http_request(struct net_context *net_ctx, int32_t timeout,
|
||||||
|
struct http_client_request *req)
|
||||||
|
{
|
||||||
|
struct net_buf *tx;
|
||||||
|
int rc = -ENOMEM;
|
||||||
|
|
||||||
|
tx = net_nbuf_get_tx(net_ctx, timeout);
|
||||||
|
if (!tx) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(req->method), (uint8_t *)req->method,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(req->url), (uint8_t *)req->url,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(req->protocol),
|
||||||
|
(uint8_t *)req->protocol, timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(req->header_fields),
|
||||||
|
(uint8_t *)req->header_fields,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->content_type_value) {
|
||||||
|
if (!net_nbuf_append(tx, strlen(HTTP_CONTENT_TYPE),
|
||||||
|
(uint8_t *)HTTP_CONTENT_TYPE,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(req->content_type_value),
|
||||||
|
(uint8_t *)req->content_type_value,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->payload && req->payload_size) {
|
||||||
|
char content_len_str[HTTP_CONT_LEN_SIZE];
|
||||||
|
|
||||||
|
rc = snprintk(content_len_str, HTTP_CONT_LEN_SIZE,
|
||||||
|
"\r\nContent-Length: %u\r\n\r\n",
|
||||||
|
req->payload_size);
|
||||||
|
if (rc <= 0 || rc >= HTTP_CONT_LEN_SIZE) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, rc, (uint8_t *)content_len_str,
|
||||||
|
timeout)) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, req->payload_size,
|
||||||
|
(uint8_t *)req->payload,
|
||||||
|
timeout)) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (!net_nbuf_append(tx, strlen(HTTP_EOF),
|
||||||
|
(uint8_t *)HTTP_EOF,
|
||||||
|
timeout)) {
|
||||||
|
goto lb_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return net_context_send(tx, NULL, timeout, NULL, NULL);
|
||||||
|
|
||||||
|
lb_exit:
|
||||||
|
net_buf_unref(tx);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_request_get(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields)
|
||||||
|
{
|
||||||
|
struct http_client_request req = {
|
||||||
|
.method = "GET ",
|
||||||
|
.url = url,
|
||||||
|
.protocol = " "HTTP_PROTOCOL"\r\n",
|
||||||
|
.header_fields = header_fields };
|
||||||
|
|
||||||
|
return http_request(net_ctx, timeout, &req);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_request_head(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields)
|
||||||
|
{
|
||||||
|
struct http_client_request req = {
|
||||||
|
.method = "HEAD ",
|
||||||
|
.url = url,
|
||||||
|
.protocol = " "HTTP_PROTOCOL"\r\n",
|
||||||
|
.header_fields = header_fields };
|
||||||
|
|
||||||
|
return http_request(net_ctx, timeout, &req);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_request_options(struct net_context *net_ctx, int32_t timeout,
|
||||||
|
char *url, char *header_fields)
|
||||||
|
{
|
||||||
|
struct http_client_request req = {
|
||||||
|
.method = "OPTIONS ",
|
||||||
|
.url = url,
|
||||||
|
.protocol = " "HTTP_PROTOCOL"\r\n",
|
||||||
|
.header_fields = header_fields };
|
||||||
|
|
||||||
|
return http_request(net_ctx, timeout, &req);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_request_post(struct net_context *net_ctx, int32_t timeout, char *url,
|
||||||
|
char *header_fields, char *content_type_value,
|
||||||
|
char *payload)
|
||||||
|
{
|
||||||
|
struct http_client_request req = {
|
||||||
|
.method = "POST ",
|
||||||
|
.url = url,
|
||||||
|
.protocol = " "HTTP_PROTOCOL"\r\n",
|
||||||
|
.header_fields = header_fields,
|
||||||
|
.content_type_value = content_type_value,
|
||||||
|
.payload = payload };
|
||||||
|
|
||||||
|
return http_request(net_ctx, timeout, &req);
|
||||||
|
}
|
127
subsys/net/lib/http/http_server.c
Normal file
127
subsys/net/lib/http/http_server.c
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017 Intel Corporation
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <net/http.h>
|
||||||
|
#include <misc/printk.h>
|
||||||
|
#include <net/nbuf.h>
|
||||||
|
#include <net/net_context.h>
|
||||||
|
|
||||||
|
#define HTTP_STATUS_200_OK "HTTP/1.1 200 OK\r\n" \
|
||||||
|
"Content-Type: text/html\r\n" \
|
||||||
|
"Transfer-Encoding: chunked\r\n" \
|
||||||
|
"\r\n"
|
||||||
|
|
||||||
|
#define HTTP_STATUS_400_BR "HTTP/1.1 400 Bad Request\r\n" \
|
||||||
|
"\r\n"
|
||||||
|
|
||||||
|
#define HTTP_STATUS_403_FBD "HTTP/1.1 403 Forbidden\r\n" \
|
||||||
|
"\r\n"
|
||||||
|
|
||||||
|
#define HTTP_STATUS_404_NF "HTTP/1.1 404 Not Found\r\n" \
|
||||||
|
"\r\n"
|
||||||
|
|
||||||
|
static inline uint16_t http_strlen(const char *str)
|
||||||
|
{
|
||||||
|
if (str) {
|
||||||
|
return strlen(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_add_header(struct net_buf *tx, int32_t timeout, const char *str)
|
||||||
|
{
|
||||||
|
if (net_nbuf_append(tx, strlen(str), (uint8_t *)str, timeout)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int http_add_chunk(struct net_buf *tx, int32_t timeout, const char *str)
|
||||||
|
{
|
||||||
|
char chunk_header[16];
|
||||||
|
char *rn = "\r\n";
|
||||||
|
uint16_t str_len;
|
||||||
|
|
||||||
|
str_len = http_strlen(str);
|
||||||
|
|
||||||
|
snprintk(chunk_header, sizeof(chunk_header), "%x\r\n", str_len);
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(chunk_header), chunk_header, timeout)) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str_len > 0) {
|
||||||
|
if (!net_nbuf_append(tx, str_len, (uint8_t *)str, timeout)) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!net_nbuf_append(tx, strlen(rn), rn, timeout)) {
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_response(struct http_server_ctx *ctx, const char *http_header,
|
||||||
|
const char *html_payload)
|
||||||
|
{
|
||||||
|
struct net_buf *tx;
|
||||||
|
int rc = -EINVAL;
|
||||||
|
|
||||||
|
tx = net_nbuf_get_tx(ctx->net_ctx, ctx->timeout);
|
||||||
|
if (!tx) {
|
||||||
|
goto exit_routine;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = http_add_header(tx, ctx->timeout, http_header);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto exit_routine;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (html_payload) {
|
||||||
|
rc = http_add_chunk(tx, ctx->timeout, html_payload);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto exit_routine;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* like EOF */
|
||||||
|
rc = http_add_chunk(tx, ctx->timeout, NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto exit_routine;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = net_context_send(tx, NULL, 0, NULL, NULL);
|
||||||
|
if (rc != 0) {
|
||||||
|
goto exit_routine;
|
||||||
|
}
|
||||||
|
|
||||||
|
tx = NULL;
|
||||||
|
|
||||||
|
exit_routine:
|
||||||
|
/* unref can handle NULL buffers, so we are covered */
|
||||||
|
net_nbuf_unref(tx);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_response_400(struct http_server_ctx *ctx, const char *html_payload)
|
||||||
|
{
|
||||||
|
return http_response(ctx, HTTP_STATUS_400_BR, html_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_response_403(struct http_server_ctx *ctx, const char *html_payload)
|
||||||
|
{
|
||||||
|
return http_response(ctx, HTTP_STATUS_403_FBD, html_payload);
|
||||||
|
}
|
||||||
|
|
||||||
|
int http_response_404(struct http_server_ctx *ctx, const char *html_payload)
|
||||||
|
{
|
||||||
|
return http_response(ctx, HTTP_STATUS_404_NF, html_payload);
|
||||||
|
}
|
|
@ -2,6 +2,7 @@ CONFIG_NETWORKING=y
|
||||||
CONFIG_RANDOM_GENERATOR=y
|
CONFIG_RANDOM_GENERATOR=y
|
||||||
CONFIG_TEST_RANDOM_GENERATOR=y
|
CONFIG_TEST_RANDOM_GENERATOR=y
|
||||||
|
|
||||||
|
CONFIG_HTTP=y
|
||||||
CONFIG_HTTP_PARSER=y
|
CONFIG_HTTP_PARSER=y
|
||||||
# Enable strict parser by uncommenting the following line
|
# Enable strict parser by uncommenting the following line
|
||||||
# CONFIG_HTTP_PARSER_STRICT=y
|
# CONFIG_HTTP_PARSER_STRICT=y
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue