/* An HTTP PUT handler. This demonstrates realtime * registration and deregistration of URI handlers */ esp_err_t ctrl_put_handler(httpd_req_t *req) { char buf; int ret; if ((ret = httpd_req_recv(req, &buf, 1)) <= 0) { if (ret == HTTPD_SOCK_ERR_TIMEOUT) { httpd_resp_send_408(req); } return ESP_FAIL; } if (buf == '0') { /* Handler can be unregistered using the uri string */ ESP_LOGI(TAG, "Unregistering /hello and /echo URIs"); httpd_unregister_uri(req->handle, "/hello"); httpd_unregister_uri(req->handle, "/echo"); } else { ESP_LOGI(TAG, "Registering /hello and /echo URIs"); httpd_register_uri_handler(req->handle, &hello); httpd_register_uri_handler(req->handle, &echo); } /* Respond with empty body */ httpd_resp_send(req, NULL, 0); return ESP_OK; }
/* An HTTP GET handler */ esp_err_t hello_get_handler(httpd_req_t *req) { char* buf; size_t buf_len; /* Get header value string length and allocate memory for length + 1, * extra byte for null termination */ buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1; if (buf_len > 1) { buf = malloc(buf_len); /* Copy null terminated value string into buffer */ if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Host: %s", buf); } free(buf); } buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-2") + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_hdr_value_str(req, "Test-Header-2", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Test-Header-2: %s", buf); } free(buf); } buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-1") + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_hdr_value_str(req, "Test-Header-1", buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found header => Test-Header-1: %s", buf); } free(buf); } /* Read URL query string length and allocate memory for length + 1, * extra byte for null termination */ buf_len = httpd_req_get_url_query_len(req) + 1; if (buf_len > 1) { buf = malloc(buf_len); if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) { ESP_LOGI(TAG, "Found URL query => %s", buf); char param[32]; /* Get value of expected key from query string */ if (httpd_query_key_value(buf, "query1", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query1=%s", param); } if (httpd_query_key_value(buf, "query3", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query3=%s", param); } if (httpd_query_key_value(buf, "query2", param, sizeof(param)) == ESP_OK) { ESP_LOGI(TAG, "Found URL query parameter => query2=%s", param); } } free(buf); } /* Set some custom headers */ httpd_resp_set_hdr(req, "Custom-Header-1", "Custom-Value-1"); httpd_resp_set_hdr(req, "Custom-Header-2", "Custom-Value-2"); /* Send response with custom headers and body set as the * string passed in user context*/ const char* resp_str = (const char*) req->user_ctx; httpd_resp_send(req, resp_str, strlen(resp_str)); /* After sending the HTTP response the old HTTP request * headers are lost. Check if HTTP request headers can be read now. */ if (httpd_req_get_hdr_value_len(req, "Host") == 0) { ESP_LOGI(TAG, "Request headers lost"); } return ESP_OK; }
esp_err_t httpd_resp_send_err(httpd_req_t *req, httpd_err_code_t error, const char *usr_msg) { esp_err_t ret; const char *msg; const char *status; switch (error) { case HTTPD_501_METHOD_NOT_IMPLEMENTED: status = "501 Method Not Implemented"; msg = "Request method is not supported by server"; break; case HTTPD_505_VERSION_NOT_SUPPORTED: status = "505 Version Not Supported"; msg = "HTTP version not supported by server"; break; case HTTPD_400_BAD_REQUEST: status = "400 Bad Request"; msg = "Server unable to understand request due to invalid syntax"; break; case HTTPD_404_NOT_FOUND: status = "404 Not Found"; msg = "This URI does not exist"; break; case HTTPD_405_METHOD_NOT_ALLOWED: status = "405 Method Not Allowed"; msg = "Request method for this URI is not handled by server"; break; case HTTPD_408_REQ_TIMEOUT: status = "408 Request Timeout"; msg = "Server closed this connection"; break; case HTTPD_414_URI_TOO_LONG: status = "414 URI Too Long"; msg = "URI is too long for server to interpret"; break; case HTTPD_411_LENGTH_REQUIRED: status = "411 Length Required"; msg = "Chunked encoding not supported by server"; break; case HTTPD_431_REQ_HDR_FIELDS_TOO_LARGE: status = "431 Request Header Fields Too Large"; msg = "Header fields are too long for server to interpret"; break; case HTTPD_500_INTERNAL_SERVER_ERROR: default: status = "500 Internal Server Error"; msg = "Server has encountered an unexpected error"; } /* If user has provided custom message, override default message */ msg = usr_msg ? usr_msg : msg; ESP_LOGW(TAG, LOG_FMT("%s - %s"), status, msg); /* Set error code in HTTP response */ httpd_resp_set_status(req, status); httpd_resp_set_type(req, HTTPD_TYPE_TEXT); #ifdef CONFIG_HTTPD_ERR_RESP_NO_DELAY /* Use TCP_NODELAY option to force socket to send data in buffer * This ensures that the error message is sent before the socket * is closed */ struct httpd_req_aux *ra = req->aux; int nodelay = 1; if (setsockopt(ra->sd->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)) < 0) { /* If failed to turn on TCP_NODELAY, throw warning and continue */ ESP_LOGW(TAG, LOG_FMT("error calling setsockopt : %d"), errno); nodelay = 0; } #endif /* Send HTTP error message */ ret = httpd_resp_send(req, msg, strlen(msg)); #ifdef CONFIG_HTTPD_ERR_RESP_NO_DELAY /* If TCP_NODELAY was set successfully above, time to disable it */ if (nodelay == 1) { nodelay = 0; if (setsockopt(ra->sd->fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay)) < 0) { /* If failed to turn off TCP_NODELAY, throw error and * return failure to signal for socket closure */ ESP_LOGE(TAG, LOG_FMT("error calling setsockopt : %d"), errno); return ESP_ERR_INVALID_STATE; } } #endif return ret; }