lwip-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-devel] [RFC] Extend httpd.c to support REST services more easily


From: tinic-lwip-devel
Subject: [lwip-devel] [RFC] Extend httpd.c to support REST services more easily
Date: Thu, 29 Oct 2020 15:13:13 -0700
User-agent: Roundcube Webmail

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 :-)

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;

err_t httpd_rest_begin(void *handle, rest_method_t method, const char *url, const char *, u16_t, int, u8_t *) {
    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;
}
---

Attachment: REST.patch
Description: Text Data


reply via email to

[Prev in Thread] Current Thread [Next in Thread]