1 // Copyright 2018 Espressif Systems (Shanghai) PTE LTD
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include <http_server.h>
21 #include "httpd_priv.h"
23 static const char *TAG = "httpd_txrx";
25 esp_err_t httpd_set_send_override(httpd_req_t *r, httpd_send_func_t send_func)
27 if (r == NULL || send_func == NULL) {
28 return ESP_ERR_INVALID_ARG;
31 if (!httpd_valid_req(r)) {
32 return ESP_ERR_HTTPD_INVALID_REQ;
35 struct httpd_req_aux *ra = r->aux;
36 ra->sd->send_fn = send_func;
40 esp_err_t httpd_set_recv_override(httpd_req_t *r, httpd_recv_func_t recv_func)
42 if (r == NULL || recv_func == NULL) {
43 return ESP_ERR_INVALID_ARG;
46 if (!httpd_valid_req(r)) {
47 return ESP_ERR_HTTPD_INVALID_REQ;
50 struct httpd_req_aux *ra = r->aux;
51 ra->sd->recv_fn = recv_func;
55 int httpd_send(httpd_req_t *r, const char *buf, size_t buf_len)
57 if (r == NULL || buf == NULL) {
58 return HTTPD_SOCK_ERR_INVALID;
61 if (!httpd_valid_req(r)) {
62 return HTTPD_SOCK_ERR_INVALID;
65 struct httpd_req_aux *ra = r->aux;
66 int ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
68 ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
74 static esp_err_t httpd_send_all(httpd_req_t *r, const char *buf, size_t buf_len)
76 struct httpd_req_aux *ra = r->aux;
80 ret = ra->sd->send_fn(ra->sd->fd, buf, buf_len, 0);
82 ESP_LOGD(TAG, LOG_FMT("error in send_fn"));
85 ESP_LOGD(TAG, LOG_FMT("sent = %d"), ret);
92 static size_t httpd_recv_pending(httpd_req_t *r, char *buf, size_t buf_len)
94 struct httpd_req_aux *ra = r->aux;
95 size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len;
97 /* buf_len must not be greater than remaining_len */
98 buf_len = MIN(ra->sd->pending_len, buf_len);
99 memcpy(buf, ra->sd->pending_data + offset, buf_len);
101 ra->sd->pending_len -= buf_len;
105 int httpd_recv_with_opt(httpd_req_t *r, char *buf, size_t buf_len, bool halt_after_pending)
107 ESP_LOGD(TAG, LOG_FMT("requested length = %d"), buf_len);
109 size_t pending_len = 0;
110 struct httpd_req_aux *ra = r->aux;
112 /* First fetch pending data from local buffer */
113 if (ra->sd->pending_len > 0) {
114 ESP_LOGD(TAG, LOG_FMT("pending length = %d"), ra->sd->pending_len);
115 pending_len = httpd_recv_pending(r, buf, buf_len);
117 buf_len -= pending_len;
119 /* If buffer filled then no need to recv.
120 * If asked to halt after receiving pending data then
121 * return with received length */
122 if (!buf_len || halt_after_pending) {
127 /* Receive data of remaining length */
128 int ret = ra->sd->recv_fn(ra->sd->fd, buf, buf_len, 0);
130 ESP_LOGD(TAG, LOG_FMT("error in recv_fn"));
134 ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret + pending_len);
135 return ret + pending_len;
138 int httpd_recv(httpd_req_t *r, char *buf, size_t buf_len)
140 return httpd_recv_with_opt(r, buf, buf_len, false);
143 size_t httpd_unrecv(struct httpd_req *r, const char *buf, size_t buf_len)
145 struct httpd_req_aux *ra = r->aux;
146 /* Truncate if external buf_len is greater than pending_data buffer size */
147 ra->sd->pending_len = MIN(sizeof(ra->sd->pending_data), buf_len);
149 /* Copy data into internal pending_data buffer */
150 size_t offset = sizeof(ra->sd->pending_data) - ra->sd->pending_len;
151 memcpy(ra->sd->pending_data + offset, buf, buf_len);
152 ESP_LOGD(TAG, LOG_FMT("length = %d"), ra->sd->pending_len);
153 return ra->sd->pending_len;
157 * This API appends an additional header field-value pair in the HTTP response.
158 * But the header isn't sent out until any of the send APIs is executed.
160 esp_err_t httpd_resp_set_hdr(httpd_req_t *r, const char *field, const char *value)
162 if (r == NULL || field == NULL || value == NULL) {
163 return ESP_ERR_INVALID_ARG;
166 if (!httpd_valid_req(r)) {
167 return ESP_ERR_HTTPD_INVALID_REQ;
170 struct httpd_req_aux *ra = r->aux;
171 struct httpd_data *hd = (struct httpd_data *) r->handle;
173 /* Number of additional headers is limited */
174 if (ra->resp_hdrs_count >= hd->config.max_resp_headers) {
175 return ESP_ERR_HTTPD_RESP_HDR;
178 /* Assign header field-value pair */
179 ra->resp_hdrs[ra->resp_hdrs_count].field = field;
180 ra->resp_hdrs[ra->resp_hdrs_count].value = value;
181 ra->resp_hdrs_count++;
183 ESP_LOGD(TAG, LOG_FMT("new header = %s: %s"), field, value);
188 * This API sets the status of the HTTP response to the value specified.
189 * But the status isn't sent out until any of the send APIs is executed.
191 esp_err_t httpd_resp_set_status(httpd_req_t *r, const char *status)
193 if (r == NULL || status == NULL) {
194 return ESP_ERR_INVALID_ARG;
197 if (!httpd_valid_req(r)) {
198 return ESP_ERR_HTTPD_INVALID_REQ;
201 struct httpd_req_aux *ra = r->aux;
202 ra->status = (char *)status;
207 * This API sets the method/type of the HTTP response to the value specified.
208 * But the method isn't sent out until any of the send APIs is executed.
210 esp_err_t httpd_resp_set_type(httpd_req_t *r, const char *type)
212 if (r == NULL || type == NULL) {
213 return ESP_ERR_INVALID_ARG;
216 if (!httpd_valid_req(r)) {
217 return ESP_ERR_HTTPD_INVALID_REQ;
220 struct httpd_req_aux *ra = r->aux;
221 ra->content_type = (char *)type;
225 esp_err_t httpd_resp_send(httpd_req_t *r, const char *buf, size_t buf_len)
228 return ESP_ERR_INVALID_ARG;
231 if (!httpd_valid_req(r)) {
232 return ESP_ERR_HTTPD_INVALID_REQ;
235 struct httpd_req_aux *ra = r->aux;
236 const char *httpd_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nContent-Length: %d\r\n";
237 const char *colon_separator = ": ";
238 const char *cr_lf_seperator = "\r\n";
240 /* Request headers are no longer available */
241 ra->req_hdrs_count = 0;
243 /* Size of essential headers is limited by scratch buffer size */
244 if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_hdr_str,
245 ra->status, ra->content_type, buf_len) >= sizeof(ra->scratch)) {
246 return ESP_ERR_HTTPD_RESP_HDR;
249 /* Sending essential headers */
250 if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) {
251 return ESP_ERR_HTTPD_RESP_SEND;
254 /* Sending additional headers based on set_header */
255 for (unsigned i = 0; i < ra->resp_hdrs_count; i++) {
256 /* Send header field */
257 if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) {
258 return ESP_ERR_HTTPD_RESP_SEND;
261 if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) {
262 return ESP_ERR_HTTPD_RESP_SEND;
264 /* Send header value */
265 if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) {
266 return ESP_ERR_HTTPD_RESP_SEND;
269 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
270 return ESP_ERR_HTTPD_RESP_SEND;
274 /* End header section */
275 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
276 return ESP_ERR_HTTPD_RESP_SEND;
279 /* Sending content */
280 if (buf && buf_len) {
281 if (httpd_send_all(r, buf, buf_len) != ESP_OK) {
282 return ESP_ERR_HTTPD_RESP_SEND;
288 esp_err_t httpd_resp_send_chunk(httpd_req_t *r, const char *buf, size_t buf_len)
291 return ESP_ERR_INVALID_ARG;
294 if (!httpd_valid_req(r)) {
295 return ESP_ERR_HTTPD_INVALID_REQ;
298 struct httpd_req_aux *ra = r->aux;
299 const char *httpd_chunked_hdr_str = "HTTP/1.1 %s\r\nContent-Type: %s\r\nTransfer-Encoding: chunked\r\n";
300 const char *colon_separator = ": ";
301 const char *cr_lf_seperator = "\r\n";
303 /* Request headers are no longer available */
304 ra->req_hdrs_count = 0;
306 if (!ra->first_chunk_sent) {
307 /* Size of essential headers is limited by scratch buffer size */
308 if (snprintf(ra->scratch, sizeof(ra->scratch), httpd_chunked_hdr_str,
309 ra->status, ra->content_type) >= sizeof(ra->scratch)) {
310 return ESP_ERR_HTTPD_RESP_HDR;
313 /* Sending essential headers */
314 if (httpd_send_all(r, ra->scratch, strlen(ra->scratch)) != ESP_OK) {
315 return ESP_ERR_HTTPD_RESP_SEND;
318 /* Sending additional headers based on set_header */
319 for (unsigned i = 0; i < ra->resp_hdrs_count; i++) {
320 /* Send header field */
321 if (httpd_send_all(r, ra->resp_hdrs[i].field, strlen(ra->resp_hdrs[i].field)) != ESP_OK) {
322 return ESP_ERR_HTTPD_RESP_SEND;
325 if (httpd_send_all(r, colon_separator, strlen(colon_separator)) != ESP_OK) {
326 return ESP_ERR_HTTPD_RESP_SEND;
328 /* Send header value */
329 if (httpd_send_all(r, ra->resp_hdrs[i].value, strlen(ra->resp_hdrs[i].value)) != ESP_OK) {
330 return ESP_ERR_HTTPD_RESP_SEND;
333 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
334 return ESP_ERR_HTTPD_RESP_SEND;
338 /* End header section */
339 if (httpd_send_all(r, cr_lf_seperator, strlen(cr_lf_seperator)) != ESP_OK) {
340 return ESP_ERR_HTTPD_RESP_SEND;
342 ra->first_chunk_sent = true;
345 /* Sending chunked content */
347 snprintf(len_str, sizeof(len_str), "%x\r\n", buf_len);
348 if (httpd_send_all(r, len_str, strlen(len_str)) != ESP_OK) {
349 return ESP_ERR_HTTPD_RESP_SEND;
353 if (httpd_send_all(r, buf, buf_len) != ESP_OK) {
354 return ESP_ERR_HTTPD_RESP_SEND;
358 /* Indicate end of chunk */
359 if (httpd_send_all(r, "\r\n", strlen("\r\n")) != ESP_OK) {
360 return ESP_ERR_HTTPD_RESP_SEND;
365 esp_err_t httpd_resp_send_404(httpd_req_t *r)
367 return httpd_resp_send_err(r, HTTPD_404_NOT_FOUND);
370 esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_resp_t error)
375 case HTTPD_501_METHOD_NOT_IMPLEMENTED:
376 status = "501 Method Not Implemented";
377 msg = "Request method is not supported by server";
379 case HTTPD_505_VERSION_NOT_SUPPORTED:
380 status = "505 Version Not Supported";
381 msg = "HTTP version not supported by server";
383 case HTTPD_400_BAD_REQUEST:
384 status = "400 Bad Request";
385 msg = "Server unable to understand request due to invalid syntax";
387 case HTTPD_404_NOT_FOUND:
388 status = "404 Not Found";
389 msg = "This URI doesn't exist";
391 case HTTPD_405_METHOD_NOT_ALLOWED:
392 status = "405 Method Not Allowed";
393 msg = "Request method for this URI is not handled by server";
395 case HTTPD_408_REQ_TIMEOUT:
396 status = "408 Request Timeout";
397 msg = "Server closed this connection";
399 case HTTPD_414_URI_TOO_LONG:
400 status = "414 URI Too Long";
401 msg = "URI is too long for server to interpret";
403 case HTTPD_411_LENGTH_REQUIRED:
404 status = "411 Length Required";
405 msg = "Chunked encoding not supported by server";
407 case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE:
408 status = "431 Request Header Fields Too Large";
409 msg = "Header fields are too long for server to interpret";
411 case HTTPD_XXX_UPGRADE_NOT_SUPPORTED:
412 /* If the server does not support upgrade, or is unable to upgrade
413 * it responds with a standard HTTP/1.1 response */
415 msg = "Upgrade not supported by server";
417 case HTTPD_500_SERVER_ERROR:
419 status = "500 Server Error";
420 msg = "Server has encountered an unexpected error";
422 ESP_LOGW(TAG, LOG_FMT("%s - %s"), status, msg);
424 httpd_resp_set_status (req, status);
425 httpd_resp_set_type (req, HTTPD_TYPE_TEXT);
426 return httpd_resp_send (req, msg, strlen(msg));
429 int httpd_req_recv(httpd_req_t *r, char *buf, size_t buf_len)
431 if (r == NULL || buf == NULL) {
432 return HTTPD_SOCK_ERR_INVALID;
435 if (!httpd_valid_req(r)) {
436 ESP_LOGW(TAG, LOG_FMT("invalid request"));
437 return HTTPD_SOCK_ERR_INVALID;
440 struct httpd_req_aux *ra = r->aux;
441 ESP_LOGD(TAG, LOG_FMT("remaining length = %d"), ra->remaining_len);
443 if (buf_len > ra->remaining_len) {
444 buf_len = ra->remaining_len;
450 int ret = httpd_recv(r, buf, buf_len);
452 ESP_LOGD(TAG, LOG_FMT("error in httpd_recv"));
455 ra->remaining_len -= ret;
456 ESP_LOGD(TAG, LOG_FMT("received length = %d"), ret);
460 int httpd_req_to_sockfd(httpd_req_t *r)
466 if (!httpd_valid_req(r)) {
467 ESP_LOGW(TAG, LOG_FMT("invalid request"));
471 struct httpd_req_aux *ra = r->aux;
475 static int httpd_sock_err(const char *ctx, int sockfd)
479 size_t sock_err_len = sizeof(sock_err);
481 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &sock_err, &sock_err_len) < 0) {
482 ESP_LOGE(TAG, LOG_FMT("error calling getsockopt : %d"), errno);
483 return HTTPD_SOCK_ERR_FAIL;
485 ESP_LOGW(TAG, LOG_FMT("error in %s : %d"), ctx, sock_err);
490 errval = HTTPD_SOCK_ERR_TIMEOUT;
496 errval = HTTPD_SOCK_ERR_INVALID;
499 errval = HTTPD_SOCK_ERR_FAIL;
504 int httpd_default_send(int sockfd, const char *buf, size_t buf_len, int flags)
507 return HTTPD_SOCK_ERR_INVALID;
510 int ret = send(sockfd, buf, buf_len, flags);
512 return httpd_sock_err("send", sockfd);
517 int httpd_default_recv(int sockfd, char *buf, size_t buf_len, int flags)
520 return HTTPD_SOCK_ERR_INVALID;
523 int ret = recv(sockfd, buf, buf_len, flags);
525 return httpd_sock_err("recv", sockfd);