[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [lwip-devel] [RFC] Extend httpd.c to support REST services more easi
From: |
address@hidden |
Subject: |
Re: [lwip-devel] [RFC] Extend httpd.c to support REST services more easily |
Date: |
Fri, 30 Oct 2020 08:14:45 +0100 |
User-agent: |
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:68.0) Gecko/20100101 Thunderbird/68.12.1 |
Am 29.10.2020 um 23:13 schrieb tinic-lwip-devel@tinic.org:
> I present a patch which adds support for REST services over HTTP in a
> relatively user
> friendly manner.
>
> Rationale: REST is the standard for most interesting Javascript
> frameworks.
> My use case was a vue.js based configuration UI built into a STM32
> microcontroller.
>
> This is primarily a variation of the existing LWIP_HTTPD_SUPPORT_POST
> code
> but different enough to where extending or mashing it together was not
> pratical. The two
> new #ifdefs are LWIP_HTTPD_SUPPORT_REST and LWIP_HTTPD_REST_MANUAL_WND.
> You either enable LWIP_HTTPD_SUPPORT_POST or LWIP_HTTPD_SUPPORT_REST but
> not both.
>
> My question is: Is there any interest in merging such functionality into
> upstream LwIP?
> If so I'd be willing to clean up and explain the code; add
> documentation, examples and a
> few test cases. On the other hand I am also happy to just move on :-)
Being able to easily support REST would be nice, but I'm not sure if
there's enough man-power available for lwIP at the moment to integrate
this. A clean patch would of course help.
>
> My fork is here: https://github.com/tinic/lwip-ajax
> A patch is attached to this email.
>
> From a user perspective a minimal REST service can be implemented as
> such:
>
> ----
> #define SERVICE_GET_STATUS 1
> #define SERVICE_POST_SETTINGS 2
>
> static int method = 0;
This won't work: you cannot use a global variable. REST calls may come
interleaved, depending on segment size. You have to pass everything as
arguments, not using globals.
>
> err_t httpd_rest_begin(void *handle, rest_method_t method, const char
> *url, const char *, u16_t, int, u8_t *) {
This won't work either: you have 2 variables named 'method' here.
Regards,
Simon
> switch(method) {
> case REST_METHOD_GET: {
> if (strcmp(url, "/status") == 0) {
> method = SERVICE_GET_STATUS;
> return ERR_OK;
> }
> } break;
>
> case REST_METHOD_POST: {
> if (strcmp(url, "/settings") == 0) {
> method = SERVICE_POST_SETTINGS;
> return ERR_OK;
> }
> } break;
>
> case REST_METHOD_PUT:
> case REST_METHOD_PATCH:
> case REST_METHOD_DELETE:
> case REST_METHOD_OPTIONS: {
> } break;
> }
> method = 0;
> return ERR_ARG;
> }
>
>
> err_t httpd_rest_receive_data(void *handle, struct pbuf *p) {
> if (method == SERVICE_POST_SETTINGS) {
>
> // user: send data to json parser
>
> return ERR_OK;
> }
> }
>
> err_t httpd_rest_finished(void *handle, const char **data, u16_t
> *dataLen) {
> if (method == SERVICE_POST_SETTINGS) {
>
> // Minimal set of fields for most browsers to work correctly in
> 2020
> // Response string is user controlled as it is security
> sensitive
> const char *okResponse =
> "HTTP/1.0 200 OK" CRLF
> "Access-Control-Allow-Origin: *" CRLF; // Wildcard is a
> potential security risk
>
> *data = okResponse;
> *dataLen = strlen(okResponse);
>
> return ERR_OK;
> }
>
> if (method == SERVICE_GET_STATUS) {
>
> static char response[1024];
>
> memset(response, 0, sizeof(response))
>
> // Minimal set of fields for most browsers to work correctly in
> 2020
> // Response string is user controlled as it is security
> sensitive
> const char *responsePrototype =
> "HTTP/1.0 200 OK" CRLF
> "Access-Control-Allow-Origin: *" CRLF // Wildcard is a
> potential security risk
> "Content-Type: application/json; charset=utf-8" CRLF
> "X-Content-Type-Options: nosniff" CRLF
> "Vary: Origin, Accept-Encoding" CRLF
> "Content-Length: @@@@@@@@@@@" CRLF // Needs to be patched
> after JSON data is added
> "Cache-Control: no-cache" CRLF
> CRLF;
>
> strncpy(response, responsePrototype, sizeof(response) - 1);
>
> // user: safely add json to response
>
> // user: safely patch content length field in response
>
> *data = response;
> *dataLen = strlen(response);
>
> return ERR_OK;
> }
>
> return ERR_ARG;
> }
> ---