]> granicus.if.org Git - esp-idf/blob - components/http_server/include/http_server.h
HTTP Server : Bug fixed in httpd_recv logic and updated function descriptions
[esp-idf] / components / http_server / include / http_server.h
1 // Copyright 2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef _HTTP_SERVER_H_
16 #define _HTTP_SERVER_H_
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <freertos/FreeRTOS.h>
21 #include <freertos/task.h>
22 #include <http_parser.h>
23 #include <sdkconfig.h>
24 #include <esp_err.h>
25
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29
30 #define HTTPD_DEFAULT_CONFIG() {                        \
31         .task_priority      = tskIDLE_PRIORITY+5,       \
32         .stack_size         = 4096,                     \
33         .server_port        = 80,                       \
34         .ctrl_port          = 32768,                    \
35         .max_open_sockets   = 7,                        \
36         .max_uri_handlers   = 8,                        \
37         .max_resp_headers   = 8,                        \
38         .backlog_conn       = 5,                        \
39         .lru_purge_enable   = false,                    \
40         .recv_wait_timeout  = 5,                        \
41         .send_wait_timeout  = 5,                        \
42 };
43
44 #define ESP_ERR_HTTPD_BASE              (0x8000)                    /*!< Starting number of HTTPD error codes */
45 #define ESP_ERR_HTTPD_HANDLERS_FULL     (ESP_ERR_HTTPD_BASE +  1)   /*!< All slots for registering URI handlers have been consumed */
46 #define ESP_ERR_HTTPD_HANDLER_EXISTS    (ESP_ERR_HTTPD_BASE +  2)   /*!< URI handler with same method and target URI already registered */
47 #define ESP_ERR_HTTPD_INVALID_REQ       (ESP_ERR_HTTPD_BASE +  3)   /*!< Invalid request pointer */
48 #define ESP_ERR_HTTPD_RESULT_TRUNC      (ESP_ERR_HTTPD_BASE +  4)   /*!< Result string truncated */
49 #define ESP_ERR_HTTPD_RESP_HDR          (ESP_ERR_HTTPD_BASE +  5)   /*!< Response header field larger than supported */
50 #define ESP_ERR_HTTPD_RESP_SEND         (ESP_ERR_HTTPD_BASE +  6)   /*!< Error occured while sending response packet */
51 #define ESP_ERR_HTTPD_ALLOC_MEM         (ESP_ERR_HTTPD_BASE +  7)   /*!< Failed to dynamically allocate memory for resource */
52 #define ESP_ERR_HTTPD_TASK              (ESP_ERR_HTTPD_BASE +  8)   /*!< Failed to launch server task/thread */
53
54 /* ************** Group: Initialization ************** */
55 /** @name Initialization
56  * APIs related to the Initialization of the web server
57  * @{
58  */
59
60 /**
61  * @brief   HTTP Server Instance Handle
62  *
63  * Every instance of the server will have a unique handle.
64  */
65 typedef void* httpd_handle_t;
66
67 /**
68  * @brief   HTTP Method Type wrapper over "enum http_method"
69  *          available in "http_parser" library
70  */
71 typedef enum http_method httpd_method_t;
72
73 /**
74  * @brief   HTTP Server Configuration Structure
75  *
76  * @note    Use HTTPD_DEFAULT_CONFIG() to initialize the configuration
77  *          to a default value and then modify only those fields that are
78  *          specifically determined by the use case.
79  */
80 typedef struct httpd_config {
81     unsigned    task_priority;      /*!< Priority of FreeRTOS task which runs the server */
82     size_t      stack_size;         /*!< The maximum stack size allowed for the server task */
83
84     /**
85      * TCP Port number for receiving and transmitting HTTP traffic
86      */
87     uint16_t    server_port;
88
89     /**
90      * UDP Port number for asynchronously exchanging control signals
91      * between various components of the server
92      */
93     uint16_t    ctrl_port;
94
95     uint16_t    max_open_sockets;   /*!< Max number of sockets/clients connected at any time*/
96     uint16_t    max_uri_handlers;   /*!< Maximum allowed uri handlers */
97     uint16_t    max_resp_headers;   /*!< Maximum allowed additional headers in HTTP response */
98     uint16_t    backlog_conn;       /*!< Number of backlog connections */
99     bool        lru_purge_enable;   /*!< Purge "Least Recently Used" connection */
100     uint16_t    recv_wait_timeout;  /*!< Timeout for recv function (in seconds)*/
101     uint16_t    send_wait_timeout;  /*!< Timeout for send function (in seconds)*/
102 } httpd_config_t;
103
104 /**
105  * @brief Starts the web server
106  *
107  * Create an instance of HTTP server and allocate memory/resources for it
108  * depending upon the specified configuration.
109  *
110  * Example usage:
111  * @code{c}
112  *
113  * //Function for starting the webserver
114  * httpd_handle_t start_webserver(void)
115  * {
116  *      // Generate default configuration
117  *      httpd_config_t config = HTTPD_DEFAULT_CONFIG();
118  *
119  *      // Empty handle to http_server
120  *      httpd_handle_t server = NULL;
121  *
122  *      // Start the httpd server
123  *      if (httpd_start(&server, &config) == ESP_OK) {
124  *          // Register URI handlers
125  *          httpd_register_uri_handler(server, &uri_get);
126  *          httpd_register_uri_handler(server, &uri_post);
127  *      }
128  *      // If server failed to start, handle will be NULL
129  *      return server;
130  * }
131  *
132  * @endcode
133  *
134  * @param[in]  config : Configuration for new instance of the server
135  * @param[out] handle : Handle to newly created instance of the server. NULL on error
136  * @return
137  *  - ESP_OK    : Instance created successfully
138  *  - ESP_ERR_INVALID_ARG      : Null argument(s)
139  *  - ESP_ERR_HTTPD_ALLOC_MEM  : Failed to allocate memory for instance
140  *  - ESP_ERR_HTTPD_TASK       : Failed to launch server task
141  */
142 esp_err_t  httpd_start(httpd_handle_t *handle, const httpd_config_t *config);
143
144 /**
145  * @brief Stops the web server
146  *
147  * Deallocates memory/resources used by an HTTP server instance and
148  * deletes it. Once deleted the handle can no longer be used for accessing
149  * the instance.
150  *
151  * Example usage:
152  * @code{c}
153  *
154  * // Function for stopping the webserver
155  * void stop_webserver(httpd_handle_t server)
156  * {
157  *      // Ensure handle is non NULL
158  *      if (server != NULL) {
159  *          // Stop the httpd server
160  *          httpd_stop(server);
161  *      }
162  * }
163  *
164  * @endcode
165  *
166  * @param[in] handle Handle to server returned by httpd_start
167  * @return
168  *  - ESP_OK : Server stopped successfully
169  *  - ESP_ERR_INVALID_ARG : Handle argument is Null
170  */
171 esp_err_t httpd_stop(httpd_handle_t handle);
172
173 /** End of Group Initialization
174  * @}
175  */
176
177 /* ************** Group: URI Handlers ************** */
178 /** @name URI Handlers
179  * APIs related to the URI handlers
180  * @{
181  */
182
183 /**
184  * @brief Function type for freeing context data (if any)
185  */
186 typedef void (*httpd_free_sess_ctx_fn_t)(void *sess_ctx);
187
188 /* Max supported HTTP request header length */
189 #define HTTPD_MAX_REQ_HDR_LEN CONFIG_HTTPD_MAX_REQ_HDR_LEN
190
191 /* Max supported HTTP request URI length */
192 #define HTTPD_MAX_URI_LEN CONFIG_HTTPD_MAX_URI_LEN
193
194 /**
195  * @brief HTTP Request Data Structure
196  */
197 typedef struct httpd_req {
198     httpd_handle_t  handle;                     /*!< Handle to server instance */
199     int             method;                     /*!< The type of HTTP request, -1 if unsupported method */
200     const char      uri[HTTPD_MAX_URI_LEN + 1]; /*!< The URI of this request (1 byte extra for null termination) */
201     size_t          content_len;                /*!< Length of the request body */
202     void           *aux;                        /*!< Internally used members */
203
204     /**
205      * User context pointer passed during URI registration.
206      */
207     void *user_ctx;
208
209     /**
210      * Session Context Pointer
211      *
212      * A session context. Contexts are maintained across 'sessions' for a
213      * given open TCP connection. One session could have multiple request
214      * responses. The web server will ensure that the context persists
215      * across all these request and responses.
216      *
217      * By default, this is NULL. URI Handlers can set this to any meaningful
218      * value.
219      *
220      * If the underlying socket gets closed, and this pointer is non-NULL,
221      * the web server will free up the context by calling free(), unless
222      * free_ctx function is set.
223      */
224     void *sess_ctx;
225
226     /**
227      * Pointer to free context hook
228      *
229      * Function to free session context
230      *
231      * If the web server's socket closes, it frees up the session context by
232      * calling free() on the sess_ctx member. If you wish to use a custom
233      * function for freeing the session context, please specify that here.
234      */
235     httpd_free_sess_ctx_fn_t free_ctx;
236 } httpd_req_t;
237
238 /**
239  * @brief Structure for URI handler
240  */
241 typedef struct httpd_uri {
242     const char       *uri;    /*!< The URI to handle */
243     httpd_method_t    method; /*!< Method supported by the URI */
244
245     /**
246      * Handler to call for supported request method. This must
247      * return ESP_OK, or else the underlying socket will be closed.
248      */
249     esp_err_t (*handler)(httpd_req_t *r);
250
251     /**
252      * Pointer to user context data which will be available to handler
253      */
254     void *user_ctx;
255 } httpd_uri_t;
256
257 /**
258  * @brief   Registers a URI handler
259  *
260  * @note    URI handlers can be registered in real time as long as the
261  *          server handle is valid.
262  *
263  * Example usage:
264  * @code{c}
265  *
266  * esp_err_t my_uri_handler(httpd_req_t* req)
267  * {
268  *     // Recv , Process and Send
269  *     ....
270  *     ....
271  *     ....
272  *
273  *     // Fail condition
274  *     if (....) {
275  *         // Return fail to close session //
276  *         return ESP_FAIL;
277  *     }
278  *
279  *     // On success
280  *     return ESP_OK;
281  * }
282  *
283  * // URI handler structure
284  * httpd_uri_t my_uri {
285  *     .uri      = "/my_uri/path/xyz",
286  *     .method   = HTTPD_GET,
287  *     .handler  = my_uri_handler,
288  *     .user_ctx = NULL
289  * };
290  *
291  * // Register handler
292  * if (httpd_register_uri_handler(server_handle, &my_uri) != ESP_OK) {
293  *    // If failed to register handler
294  *    ....
295  * }
296  *
297  * @endcode
298  *
299  * @param[in] handle      handle to HTTPD server instance
300  * @param[in] uri_handler pointer to handler that needs to be registered
301  *
302  * @return
303  *  - ESP_OK : On successfully registering the handler
304  *  - ESP_ERR_INVALID_ARG : Null arguments
305  *  - ESP_ERR_HTTPD_HANDLERS_FULL  : If no slots left for new handler
306  *  - ESP_ERR_HTTPD_HANDLER_EXISTS : If handler with same URI and
307  *                                   method is already registered
308  */
309 esp_err_t httpd_register_uri_handler(httpd_handle_t handle,
310                                      const httpd_uri_t *uri_handler);
311
312 /**
313  * @brief   Unregister a URI handler
314  *
315  * @param[in] handle    handle to HTTPD server instance
316  * @param[in] uri       URI string
317  * @param[in] method    HTTP method
318  *
319  * @return
320  *  - ESP_OK : On successfully deregistering the handler
321  *  - ESP_ERR_INVALID_ARG : Null arguments
322  *  - ESP_ERR_NOT_FOUND   : Handler with specified URI and method not found
323  */
324 esp_err_t httpd_unregister_uri_handler(httpd_handle_t handle,
325                                        const char *uri, httpd_method_t method);
326
327 /**
328  * @brief   Unregister all URI handlers with the specified uri string
329  *
330  * @param[in] handle   handle to HTTPD server instance
331  * @param[in] uri      uri string specifying all handlers that need
332  *                     to be deregisterd
333  *
334  * @return
335  *  - ESP_OK : On successfully deregistering all such handlers
336  *  - ESP_ERR_INVALID_ARG : Null arguments
337  *  - ESP_ERR_NOT_FOUND   : No handler registered with specified uri string
338  */
339 esp_err_t httpd_unregister_uri(httpd_handle_t handle, const char* uri);
340
341 /** End of URI Handlers
342  * @}
343  */
344
345 /* ************** Group: TX/RX ************** */
346 /** @name TX / RX
347  * Prototype for HTTPDs low-level send/recv functions
348  * @{
349  */
350
351 #define HTTPD_SOCK_ERR_FAIL      -1
352 #define HTTPD_SOCK_ERR_INVALID   -2
353 #define HTTPD_SOCK_ERR_TIMEOUT   -3
354
355 /**
356  * @brief  Prototype for HTTPDs low-level send function
357  *
358  * @note   User specified send function must handle errors internally,
359  *         depending upon the set value of errno, and return specific
360  *         HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
361  *         return value of httpd_send() function
362  *
363  * @return
364  *  - Bytes : The number of bytes sent successfully
365  *  - HTTPD_SOCK_ERR_INVALID  : Invalid arguments
366  *  - HTTPD_SOCK_ERR_TIMEOUT  : Timeout/interrupted while calling socket send()
367  *  - HTTPD_SOCK_ERR_FAIL     : Unrecoverable error while calling socket send()
368  */
369 typedef int (*httpd_send_func_t)(int sockfd, const char *buf, size_t buf_len, int flags);
370
371 /**
372  * @brief  Prototype for HTTPDs low-level recv function
373  *
374  * @note   User specified recv function must handle errors internally,
375  *         depending upon the set value of errno, and return specific
376  *         HTTPD_SOCK_ERR_ codes, which will eventually be conveyed as
377  *         return value of httpd_req_recv() function
378  *
379  * @return
380  *  - Bytes : The number of bytes received successfully
381  *  - 0     : Buffer length parameter is zero / connection closed by peer
382  *  - HTTPD_SOCK_ERR_INVALID  : Invalid arguments
383  *  - HTTPD_SOCK_ERR_TIMEOUT  : Timeout/interrupted while calling socket recv()
384  *  - HTTPD_SOCK_ERR_FAIL     : Unrecoverable error while calling socket recv()
385  */
386 typedef int (*httpd_recv_func_t)(int sockfd, char *buf, size_t buf_len, int flags);
387
388 /** End of TX / RX
389  * @}
390  */
391
392 /* ************** Group: Request/Response ************** */
393 /** @name Request / Response
394  * APIs related to the data send/receive by URI handlers.
395  * These APIs are supposed to be called only from the context of
396  * a URI handler where httpd_req_t* request pointer is valid.
397  * @{
398  */
399
400 /**
401  * @brief   Override web server's receive function
402  *
403  * This function overrides the web server's receive function. This same function is
404  * used to read and parse HTTP headers as well as body.
405  *
406  * @note    This API is supposed to be called only from the context of
407  *          a URI handler where httpd_req_t* request pointer is valid.
408  *
409  * @param[in] r         The request being responded to
410  * @param[in] recv_func The receive function to be set for this request
411  *
412  * @return
413  *  - ESP_OK : On successfully registering override
414  *  - ESP_ERR_INVALID_ARG : Null arguments
415  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
416  */
417 esp_err_t httpd_set_recv_override(httpd_req_t *r, httpd_recv_func_t recv_func);
418
419 /**
420  * @brief   Override web server's send function
421  *
422  * This function overrides the web server's send function. This same function is
423  * used to send out any response to any HTTP request.
424  *
425  * @note    This API is supposed to be called only from the context of
426  *          a URI handler where httpd_req_t* request pointer is valid.
427  *
428  * @param[in] r         The request being responded to
429  * @param[in] send_func The send function to be set for this request
430  *
431  * @return
432  *  - ESP_OK : On successfully registering override
433  *  - ESP_ERR_INVALID_ARG : Null arguments
434  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
435  */
436 esp_err_t httpd_set_send_override(httpd_req_t *r, httpd_send_func_t send_func);
437
438 /**
439  * @brief   Get the Socket Descriptor from the HTTP request
440  *
441  * This API will return the socket descriptor of the session for
442  * which URI handler was executed on reception of HTTP request.
443  * This is useful when user wants to call functions that require
444  * session socket fd, from within a URI handler, ie. :
445  *      httpd_sess_get_ctx(),
446  *      httpd_trigger_sess_close(),
447  *      httpd_sess_update_timestamp().
448  *
449  * @note    This API is supposed to be called only from the context of
450  *          a URI handler where httpd_req_t* request pointer is valid.
451  *
452  * @param[in] r The request whose socket descriptor should be found
453  *
454  * @return
455  *  - Socket descriptor : The socket descriptor for this request
456  *  - -1 : Invalid/NULL request pointer
457  */
458 int httpd_req_to_sockfd(httpd_req_t *r);
459
460 /**
461  * @brief   API to read content data from the HTTP request
462  *
463  * This API will read HTTP content data from the HTTP request into
464  * provided buffer. Use content_len provided in httpd_req_t structure
465  * to know the length of data to be fetched. If content_len is too
466  * large for the buffer then user may have to make multiple calls to
467  * this function, each time fetching 'buf_len' number of bytes,
468  * while the pointer to content data is incremented internally by
469  * the same number.
470  *
471  * @note
472  *  - This API is supposed to be called only from the context of
473  *    a URI handler where httpd_req_t* request pointer is valid.
474  *  - If an error is returned, the URI handler must further return an error.
475  *    This will ensure that the erroneous socket is closed and cleaned up by
476  *    the web server.
477  *  - Presently Chunked Encoding is not supported
478  *
479  * @param[in] r         The request being responded to
480  * @param[in] buf       Pointer to a buffer that the data will be read into
481  * @param[in] buf_len   Length of the buffer
482  *
483  * @return
484  *  - Bytes : Number of bytes read into the buffer successfully
485  *  - 0     : Buffer length parameter is zero / connection closed by peer
486  *  - HTTPD_SOCK_ERR_INVALID  : Invalid arguments
487  *  - HTTPD_SOCK_ERR_TIMEOUT  : Timeout/interrupted while calling socket recv()
488  *  - HTTPD_SOCK_ERR_FAIL     : Unrecoverable error while calling socket recv()
489  */
490 int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len);
491
492 /**
493  * @brief   Search for a field in request headers and
494  *          return the string length of it's value
495  *
496  * @note
497  *  - This API is supposed to be called only from the context of
498  *    a URI handler where httpd_req_t* request pointer is valid.
499  *  - Once httpd_resp_send() API is called all request headers
500  *    are purged, so request headers need be copied into separate
501  *    buffers if they are required later.
502  *
503  * @param[in]  r        The request being responded to
504  * @param[in]  field    The header field to be searched in the request
505  *
506  * @return
507  *  - Length    : If field is found in the request URL
508  *  - Zero      : Field not found / Invalid request / Null arguments
509  */
510 size_t httpd_req_get_hdr_value_len(httpd_req_t *r, const char *field);
511
512 /**
513  * @brief   Get the value string of a field from the request headers
514  *
515  * @note
516  *  - This API is supposed to be called only from the context of
517  *    a URI handler where httpd_req_t* request pointer is valid.
518  *  - Once httpd_resp_send() API is called all request headers
519  *    are purged, so request headers need be copied into separate
520  *    buffers if they are required later.
521  *  - If output size is greater than input, then the value is truncated,
522  *    accompanied by truncation error as return value.
523  *  - Use httpd_req_get_hdr_value_len() to know the right buffer length
524  *
525  * @param[in]  r        The request being responded to
526  * @param[in]  field    The field to be searched in the header
527  * @param[out] val      Pointer to the buffer into which the value will be copied if the field is found
528  * @param[in]  val_size Size of the user buffer "val"
529  *
530  * @return
531  *  - ESP_OK : Field found in the request header and value string copied
532  *  - ESP_ERR_NOT_FOUND          : Key not found
533  *  - ESP_ERR_INVALID_ARG        : Null arguments
534  *  - ESP_ERR_HTTPD_INVALID_REQ  : Invalid HTTP request pointer
535  *  - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated
536  */
537 esp_err_t httpd_req_get_hdr_value_str(httpd_req_t *r, const char *field, char *val, size_t val_size);
538
539 /**
540  * @brief   Get Query string length from the request URL
541  *
542  * @note    This API is supposed to be called only from the context of
543  *          a URI handler where httpd_req_t* request pointer is valid
544  *
545  * @param[in]  r    The request being responded to
546  *
547  * @return
548  *  - Length    : Query is found in the request URL
549  *  - Zero      : Query not found / Null arguments / Invalid request
550  */
551 size_t httpd_req_get_url_query_len(httpd_req_t *r);
552
553 /**
554  * @brief   Get Query string from the request URL
555  *
556  * @note
557  *  - Presently, the user can fetch the full URL query string, but decoding
558  *    will have to be performed by the user. Request headers can be read using
559  *    httpd_req_get_hdr_value_str() to know the 'Content-Type' (eg. Content-Type:
560  *    application/x-www-form-urlencoded) and then the appropriate decoding
561  *    algorithm needs to be applied.
562  *  - This API is supposed to be called only from the context of
563  *    a URI handler where httpd_req_t* request pointer is valid
564  *  - If output size is greater than input, then the value is truncated,
565  *    accompanied by truncation error as return value
566  *  - Use httpd_req_get_url_query_len() to know the right buffer length
567  *
568  * @param[in]  r         The request being responded to
569  * @param[out] buf       Pointer to the buffer into which the query string will be copied (if found)
570  * @param[in]  buf_len   Length of output buffer
571  *
572  * @return
573  *  - ESP_OK : Query is found in the request URL and copied to buffer
574  *  - ESP_ERR_NOT_FOUND          : Query not found
575  *  - ESP_ERR_INVALID_ARG        : Null arguments
576  *  - ESP_ERR_HTTPD_INVALID_REQ  : Invalid HTTP request pointer
577  *  - ESP_ERR_HTTPD_RESULT_TRUNC : Query string truncated
578  */
579 esp_err_t httpd_req_get_url_query_str(httpd_req_t *r, char *buf, size_t buf_len);
580
581 /**
582  * @brief   Helper function to get a URL query tag from a query
583  *          string of the type param1=val1&param2=val2
584  *
585  * @note
586  *  - The components of URL query string (keys and values) are not URLdecoded.
587  *    The user must check for 'Content-Type' field in the request headers and
588  *    then depending upon the specified encoding (URLencoded or otherwise) apply
589  *    the appropriate decoding algorithm.
590  *  - If actual value size is greater than val_size, then the value is truncated,
591  *    accompanied by truncation error as return value.
592  *
593  * @param[in]  qry       Pointer to query string
594  * @param[in]  key       The key to be searched in the query string
595  * @param[out] val       Pointer to the buffer into which the value will be copied if the key is found
596  * @param[in]  val_size  Size of the user buffer "val"
597  *
598  * @return
599  *  - ESP_OK : Key is found in the URL query string and copied to buffer
600  *  - ESP_ERR_NOT_FOUND          : Key not found
601  *  - ESP_ERR_INVALID_ARG        : Null arguments
602  *  - ESP_ERR_HTTPD_RESULT_TRUNC : Value string truncated
603  */
604 esp_err_t httpd_query_key_value(const char *qry, const char *key, char *val, size_t val_size);
605
606 /**
607  * @brief   API to send a complete HTTP response.
608  *
609  * This API will send the data as an HTTP response to the request.
610  * This assumes that you have the entire response ready in a single
611  * buffer. If you wish to send response in incremental chunks use
612  * httpd_resp_send_chunk() instead.
613  *
614  * If no status code and content-type were set, by default this
615  * will send 200 OK status code and content type as text/html.
616  * You may call the following functions before this API to configure
617  * the response headers :
618  *      httpd_resp_set_status() - for setting the HTTP status string,
619  *      httpd_resp_set_type()   - for setting the Content Type,
620  *      httpd_resp_set_hdr()    - for appending any additional field
621  *                                value entries in the response header
622  *
623  * @note
624  *  - This API is supposed to be called only from the context of
625  *    a URI handler where httpd_req_t* request pointer is valid.
626  *  - Once this API is called, the request has been responded to.
627  *  - No additional data can then be sent for the request.
628  *  - Once this API is called, all request headers are purged, so
629  *    request headers need be copied into separate buffers if
630  *    they are required later.
631  *
632  * @param[in] r         The request being responded to
633  * @param[in] buf       Buffer from where the content is to be fetched
634  * @param[in] buf_len   Length of the buffer
635  *
636  * @return
637  *  - ESP_OK : On successfully sending the response packet
638  *  - ESP_ERR_INVALID_ARG : Null request pointer
639  *  - ESP_ERR_HTTPD_RESP_HDR    : Essential headers are too large for internal buffer
640  *  - ESP_ERR_HTTPD_RESP_SEND   : Error in raw send
641  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request
642  */
643 esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len);
644
645 /**
646  * @brief   API to send one HTTP chunk
647  *
648  * This API will send the data as an HTTP response to the
649  * request. This API will use chunked-encoding and send the response
650  * in the form of chunks. If you have the entire response contained in
651  * a single buffer, please use httpd_resp_send() instead.
652  *
653  * If no status code and content-type were set, by default this will
654  * send 200 OK status code and content type as text/html. You may
655  * call the following functions before this API to configure the
656  * response headers
657  *      httpd_resp_set_status() - for setting the HTTP status string,
658  *      httpd_resp_set_type()   - for setting the Content Type,
659  *      httpd_resp_set_hdr()    - for appending any additional field
660  *                                value entries in the response header
661  *
662  * @note
663  * - This API is supposed to be called only from the context of
664  *   a URI handler where httpd_req_t* request pointer is valid.
665  * - When you are finished sending all your chunks, you must call
666  *   this function with buf_len as 0.
667  * - Once this API is called, all request headers are purged, so
668  *   request headers need be copied into separate buffers if they
669  *   are required later.
670  *
671  * @param[in] r         The request being responded to
672  * @param[in] buf       Pointer to a buffer that stores the data
673  * @param[in] buf_len   Length of the data from the buffer that should be sent out
674  *
675  * @return
676  *  - ESP_OK : On successfully sending the response packet chunk
677  *  - ESP_ERR_INVALID_ARG : Null request pointer
678  *  - ESP_ERR_HTTPD_RESP_HDR    : Essential headers are too large for internal buffer
679  *  - ESP_ERR_HTTPD_RESP_SEND   : Error in raw send
680  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
681  */
682 esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len);
683
684 /* Some commonly used status codes */
685 #define HTTPD_200      "200 OK"                     /*!< HTTP Response 200 */
686 #define HTTPD_204      "204 No Content"             /*!< HTTP Response 204 */
687 #define HTTPD_207      "207 Multi-Status"           /*!< HTTP Response 207 */
688 #define HTTPD_400      "400 Bad Request"            /*!< HTTP Response 400 */
689 #define HTTPD_404      "404 Not Found"              /*!< HTTP Response 404 */
690 #define HTTPD_500      "500 Internal Server Error"  /*!< HTTP Response 500 */
691
692 /**
693  * @brief   API to set the HTTP status code
694  *
695  * This API sets the status of the HTTP response to the value specified.
696  * By default, the '200 OK' response is sent as the response.
697  *
698  * @note
699  *  - This API is supposed to be called only from the context of
700  *    a URI handler where httpd_req_t* request pointer is valid.
701  *  - This API only sets the status to this value. The status isn't
702  *    sent out until any of the send APIs is executed.
703  *  - Make sure that the lifetime of the status string is valid till
704  *    send function is called.
705  *
706  * @param[in] r         The request being responded to
707  * @param[in] status    The HTTP status code of this response
708  *
709  * @return
710  *  - ESP_OK : On success
711  *  - ESP_ERR_INVALID_ARG : Null arguments
712  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
713  */
714 esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status);
715
716 /* Some commonly used content types */
717 #define HTTPD_TYPE_JSON   "application/json"            /*!< HTTP Content type JSON */
718 #define HTTPD_TYPE_TEXT   "text/html"                   /*!< HTTP Content type text/HTML */
719 #define HTTPD_TYPE_OCTET  "application/octet-stream"    /*!< HTTP Content type octext-stream */
720
721 /**
722  * @brief   API to set the HTTP content type
723  *
724  * This API sets the 'Content Type' field of the response.
725  * The default content type is 'text/html'.
726  *
727  * @note
728  *  - This API is supposed to be called only from the context of
729  *    a URI handler where httpd_req_t* request pointer is valid.
730  *  - This API only sets the content type to this value. The type
731  *    isn't sent out until any of the send APIs is executed.
732  *  - Make sure that the lifetime of the type string is valid till
733  *    send function is called.
734  *
735  * @param[in] r     The request being responded to
736  * @param[in] type  The Content Type of the response
737  *
738  * @return
739  *  - ESP_OK   : On success
740  *  - ESP_ERR_INVALID_ARG : Null arguments
741  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
742  */
743 esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type);
744
745 /**
746  * @brief   API to append any additional headers
747  *
748  * This API sets any additional header fields that need to be sent in the response.
749  *
750  * @note
751  *  - This API is supposed to be called only from the context of
752  *    a URI handler where httpd_req_t* request pointer is valid.
753  *  - The header isn't sent out until any of the send APIs is executed.
754  *  - The maximum allowed number of additional headers is limited to
755  *    value of max_resp_headers in config structure.
756  *  - Make sure that the lifetime of the field value strings are valid till
757  *    send function is called.
758  *
759  * @param[in] r     The request being responded to
760  * @param[in] field The field name of the HTTP header
761  * @param[in] value The value of this HTTP header
762  *
763  * @return
764  *  - ESP_OK : On successfully appending new header
765  *  - ESP_ERR_INVALID_ARG : Null arguments
766  *  - ESP_ERR_HTTPD_RESP_HDR    : Total additional headers exceed max allowed
767  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
768  */
769 esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value);
770
771 /**
772  * @brief   Helper function for HTTP 404
773  *
774  * Send HTTP 404 message. If you wish to send additional data in the body of the
775  * response, please use the lower-level functions directly.
776  *
777  * @note
778  *  - This API is supposed to be called only from the context of
779  *    a URI handler where httpd_req_t* request pointer is valid.
780  *  - Once this API is called, all request headers are purged, so
781  *    request headers need be copied into separate buffers if
782  *    they are required later.
783  *
784  * @param[in] r The request being responded to
785  *
786  * @return
787  *  - ESP_OK : On successfully sending the response packet
788  *  - ESP_ERR_INVALID_ARG : Null arguments
789  *  - ESP_ERR_HTTPD_RESP_SEND   : Error in raw send
790  *  - ESP_ERR_HTTPD_INVALID_REQ : Invalid request pointer
791  */
792 esp_err_t httpd_resp_send_404(httpd_req_t *r);
793
794 /**
795  * @brief   Raw HTTP send
796  *
797  * Call this API if you wish to construct your custom response packet.
798  * When using this, all essential header, eg. HTTP version, Status Code,
799  * Content Type and Length, Encoding, etc. will have to be constructed
800  * manually, and HTTP delimeters (CRLF) will need to be placed correctly
801  * for separating sub-sections of the HTTP response packet.
802  *
803  * If the send override function is set, this API will end up
804  * calling that function eventually to send data out.
805  *
806  * @note
807  *  - This API is supposed to be called only from the context of
808  *    a URI handler where httpd_req_t* request pointer is valid.
809  *  - Unless the response has the correct HTTP structure (which the
810  *    user must now ensure) it is not guaranteed that it will be
811  *    recognized by the client. For most cases, you wouldn't have
812  *    to call this API, but you would rather use either of :
813  *          httpd_resp_send(),
814  *          httpd_resp_send_chunk()
815  *
816  * @param[in] r         The request being responded to
817  * @param[in] buf       Buffer from where the fully constructed packet is to be read
818  * @param[in] buf_len   Length of the buffer
819  *
820  * @return
821  *  - Bytes : Number of bytes that were sent successfully
822  *  - HTTPD_SOCK_ERR_INVALID  : Invalid arguments
823  *  - HTTPD_SOCK_ERR_TIMEOUT  : Timeout/interrupted while calling socket send()
824  *  - HTTPD_SOCK_ERR_FAIL     : Unrecoverable error while calling socket send()
825  */
826 int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len);
827
828 /** End of Request / Response
829  * @}
830  */
831
832 /* ************** Group: Session ************** */
833 /** @name Session
834  * Functions for controlling sessions and accessing context data
835  * @{
836  */
837
838 /**
839  * @brief   Get session context from socket descriptor
840  *
841  * Typically if a session context is created, it is available to URI handlers
842  * through the httpd_req_t structure. But, there are cases where the web
843  * server's send/receive functions may require the context (for example, for
844  * accessing keying information etc). Since the send/receive function only have
845  * the socket descriptor at their disposal, this API provides them with a way to
846  * retrieve the session context.
847  *
848  * @param[in] handle    Handle to server returned by httpd_start
849  * @param[in] sockfd    The socket descriptor for which the context should be extracted.
850  *
851  * @return
852  *  - void* : Pointer to the context associated with this session
853  *  - NULL  : Empty context / Invalid handle / Invalid socket fd
854  */
855 void *httpd_sess_get_ctx(httpd_handle_t handle, int sockfd);
856
857 /**
858  * @brief   Trigger an httpd session close externally
859  *
860  * @note    Calling this API is only required in special circumstances wherein
861  *          some application requires to close an httpd client session asynchronously.
862  *
863  * @param[in] handle    Handle to server returned by httpd_start
864  * @param[in] sockfd    The socket descriptor of the session to be closed
865  *
866  * @return
867  *  - ESP_OK    : On successfully initiating closure
868  *  - ESP_FAIL  : Failure to queue work
869  *  - ESP_ERR_NOT_FOUND   : Socket fd not found
870  *  - ESP_ERR_INVALID_ARG : Null arguments
871  */
872 esp_err_t httpd_trigger_sess_close(httpd_handle_t handle, int sockfd);
873
874 /**
875  * @brief   Update timestamp for a given socket
876  *
877  * Timestamps are internally associated with each session to monitor
878  * how recently a session exchanged traffic. When LRU purge is enabled,
879  * if a client is requesting for connection but maximum number of
880  * sockets/sessions is reached, then the session having the earliest
881  * timestamp is closed automatically.
882  *
883  * Updating the timestamp manually prevents the socket from being purged
884  * due to the Least Recently Used (LRU) logic, even though it might not
885  * have received traffic for some time. This is useful when all open
886  * sockets/session are frequently exchanging traffic but the user specifically
887  * wants one of the sessions to be kept open, irrespective of when it last
888  * exchanged a packet.
889  *
890  * @note    Calling this API is only necessary if the LRU Purge Enable option
891  *          is enabled.
892  *
893  * @param[in] handle    Handle to server returned by httpd_start
894  * @param[in] sockfd    The socket descriptor of the session for which timestamp
895  *                      is to be updated
896  *
897  * @return
898  *  - ESP_OK : Socket found and timestamp updated
899  *  - ESP_ERR_NOT_FOUND   : Socket not found
900  *  - ESP_ERR_INVALID_ARG : Null arguments
901  */
902 esp_err_t httpd_sess_update_timestamp(httpd_handle_t handle, int sockfd);
903
904 /** End of Session
905  * @}
906  */
907
908 /* ************** Group: Work Queue ************** */
909 /** @name Work Queue
910  * APIs related to the HTTPD Work Queue
911  * @{
912  */
913
914 /**
915  * @brief   Prototype of the HTTPD work function
916  *          Please refer to httpd_queue_work() for more details.
917  * @param[in] arg   The arguments for this work function
918  */
919 typedef void (*httpd_work_fn_t)(void *arg);
920
921 /**
922  * @brief   Queue execution of a function in HTTPD's context
923  *
924  * This API queues a work function for asynchronous execution
925  *
926  * @note    Some protocols require that the web server generate some asynchronous data
927  *          and send it to the persistently opened connection. This facility is for use
928  *          by such protocols.
929  *
930  * @param[in] handle    Handle to server returned by httpd_start
931  * @param[in] work      Pointer to the function to be executed in the HTTPD's context
932  * @param[in] arg       Pointer to the arguments that should be passed to this function
933  *
934  * @return
935  *  - ESP_OK   : On successfully queueing the work
936  *  - ESP_FAIL : Failure in ctrl socket
937  *  - ESP_ERR_INVALID_ARG : Null arguments
938  */
939 esp_err_t httpd_queue_work(httpd_handle_t handle, httpd_work_fn_t work, void *arg);
940
941 /** End of Group Work Queue
942  * @}
943  */
944
945 #ifdef __cplusplus
946 }
947 #endif
948
949 #endif /* ! _HTTP_SERVER_H_ */