0
0
Fork 0
wireless-proxy-esp32/project_components/web_server/uri_modules/uri_api.c

163 lines
3.9 KiB
C

#include "web_uri_module.h"
#include "api_json_router.h"
#include "request_runner.h"
#include "static_buffer.h"
#include <esp_http_server.h>
#include <esp_log.h>
#include <cJSON.h>
#define TAG __FILE_NAME__
#define HTTPD_STATUS_503 "503 Busy"
typedef struct post_request_t {
api_json_req_t json;
api_json_module_async_t async;
httpd_req_t *req_out;
char buf[0];
} post_request_t;
static void async_send_out_cb(void *req, int module_status);
static int uri_api_send_out(httpd_req_t *req, post_request_t *post_req);
static esp_err_t api_post_handler(httpd_req_t *req)
{
uint32_t buf_len;
int data_len;
int err;
post_request_t *post_req;
char *buf;
uint32_t remaining = req->content_len;
buf_len = static_buffer_get_buf_size() - sizeof(post_request_t);
if (unlikely(buf_len < remaining)) {
ESP_LOGE(TAG, "req size %lu > buf_len %lu", remaining, buf_len);
return ESP_FAIL;
}
post_req = static_buffer_get(pdMS_TO_TICKS(20));
if (unlikely(post_req == NULL)) {
ESP_LOGE(TAG, "static buf busy");
return ESP_FAIL;
}
buf = post_req->buf;
data_len = httpd_req_recv(req, buf, buf_len);
if (unlikely(data_len <= 0)) {
ESP_LOGE(TAG, "httpd recv error");
err = ESP_FAIL;
goto put_buf;
}
ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
ESP_LOGI(TAG, "%.*s", data_len, buf);
ESP_LOGI(TAG, "====================================");
ESP_LOGI(TAG, "heap min: %lu, cur: %lu", esp_get_minimum_free_heap_size(), esp_get_free_heap_size());
/* Decode */
post_req->json.in = cJSON_ParseWithLength(buf, data_len);
if (unlikely(post_req->json.in == NULL)) {
httpd_resp_set_status(req, HTTPD_400);
goto end;
}
post_req->json.out = NULL;
err = api_json_route(&post_req->json, &post_req->async);
cJSON_Delete(post_req->json.in);
if (err == API_JSON_ASYNC) {
httpd_req_async_handler_begin(req, &post_req->req_out);
post_req->async.req_task.send_out.cb = async_send_out_cb;
post_req->async.req_task.send_out.arg = post_req;
if (req_queue_push_long_run(&post_req->async.req_task, pdMS_TO_TICKS(20))) {
httpd_req_async_handler_complete(post_req->req_out);
httpd_resp_set_status(req, HTTPD_STATUS_503);
goto end;
}
return ESP_OK;
} else if (unlikely(err != API_JSON_OK)) {
httpd_resp_set_status(req, HTTPD_400);
goto end;
}
if (post_req->json.out == NULL) {
goto end;
}
/* api function returns something, send back to http client */
err = uri_api_send_out(req, post_req);
goto put_buf;
end:
err = httpd_resp_send(req, NULL, 0);
if (unlikely(err)) {
ESP_LOGE(TAG, "resp_send err: %s", esp_err_to_name(err));
}
put_buf:
static_buffer_put(post_req);
return err;
}
int uri_api_send_out(httpd_req_t *req, post_request_t *post_req)
{
int err;
char *buf;
uint32_t buf_len;
buf = post_req->buf;
buf_len = static_buffer_get_buf_size() - sizeof(post_request_t);
httpd_resp_set_type(req, HTTPD_TYPE_JSON);
err = !cJSON_PrintPreallocated(post_req->json.out, buf, buf_len - 5, 0);
cJSON_Delete(post_req->json.out);
if (unlikely(err)) {
httpd_resp_set_status(req, HTTPD_500);
return httpd_resp_send(req, NULL, 0);
}
return httpd_resp_send(req, buf, strlen(buf));
}
void async_send_out_cb(void *arg, int module_status)
{
post_request_t *req = arg;
if (module_status != API_JSON_OK) {
httpd_sess_trigger_close(req->req_out->handle,
httpd_req_to_sockfd(req->req_out->handle));
}
uri_api_send_out(req->req_out, req);
/* clean resources */
httpd_req_async_handler_complete(req->req_out);
static_buffer_put(req);
};
/**
* REGISTER MODULE
* */
static const httpd_uri_t uri_api = {
.uri = "/api",
.method = HTTP_POST,
.handler = api_post_handler,
.user_ctx = NULL
};
int URI_API_INIT(const httpd_uri_t **uri_conf) {
*uri_conf = &uri_api;
api_json_router_init();
return 0;
}
int URI_API_EXIT(const httpd_uri_t **uri_conf) {
*uri_conf = &uri_api;
return 0;
}
WEB_URI_MODULE_REGISTER(0x81, URI_API_INIT, URI_API_EXIT)