etr / libhttpserver

C++ library for creating an embedded Rest HTTP server (and more)
GNU Lesser General Public License v2.1
882 stars 184 forks source link

[BUG] Querystring parameters + Parameterized paths #325

Closed marrony closed 1 year ago

marrony commented 1 year ago

Prerequisites

Description

Looks like it's not possible to get querystring arguments when using parameterized paths. If it's not possible, is it documented somewhere?

Steps to Reproduce

Here is a modified version of https://github.com/etr/libhttpserver/#example-of-handler-reading-arguments-from-a-request.

#include <iostream>
#include <httpserver.hpp>

using namespace httpserver;

class hello_world_resource : public http_resource {
public:
    std::shared_ptr<http_response> render(const http_request& req) {
        std::cout << req << std::endl;
        return std::shared_ptr<http_response>(new string_response("Hello: " + std::string(req.get_arg("name"))));
    }
};

int main(int argc, char** argv) {
    webserver ws = create_webserver(8080);

    hello_world_resource hwr;
    ws.register_resource("/hello", &hwr);
    ws.register_resource("/test/{id}", &hwr);
    ws.start(true);

    return 0;
}

Querying with Simple path + Querystrings:

$ curl "http://192.168.1.76:8080/hello?name=John"
Hello: John

Logged:

GET Request [user:"" pass:""] path:"/hello"
    Headers [Host:"192.168.1.76:8080" Accept:"*/*" User-Agent:"curl/7.85.0" ]
    Query Args [name:["John"] ]
    Version [ HTTP/1.1 ] Requestor [ 192.168.1.73 ] Port [ 57598 ]

Querying with Parameterized path + application/x-www-form-urlencoded:

$ curl "http://192.168.1.76:8080/test/1" -d "name=John"
Hello: John

Logged:

POST Request [user:"" pass:""] path:"/test/1"
    Headers [Host:"192.168.1.76:8080" Accept:"*/*" User-Agent:"curl/7.85.0" Content-Type:"application/x-www-form-urlencoded" Content-Length:"9" ]
    Query Args [id:["1"] name:["John"] ]
    Version [ HTTP/1.1 ] Requestor [ 192.168.1.73 ] Port [ 52928 ]

Querying with Parameterized path + Querystring:

$ curl "http://192.168.1.76:8080/test/1?name=John"
Hello:

Logged:

GET Request [user:"" pass:""] path:"/test/1"
    Headers [Host:"192.168.1.76:8080" Accept:"*/*" User-Agent:"curl/7.85.0" ]
    Query Args [id:["1"] ]
    Version [ HTTP/1.1 ] Requestor [ 192.168.1.73 ] Port [ 56830 ]

I was expecting to see Query Args [id:["1"] name:["John"] ]

Looks like it works with application/x-www-form-urlencoded data but not with querystring parameters.

The documentation says:

http_arg_value get_arg(std::string_view key) const: Returns the argument with name equal to key if present in the HTTP request.
Arguments can be (1) querystring parameters, (2) path argument (in case of parametric endpoint, (3) parameters parsed from the HTTP request body if the body is in application/x-www-form-urlencoded or multipart/form-data formats and the postprocessor is enabled in the webserver (enabled by default).
Arguments are collected in a domain object that allows to collect multiple arguments with the same key while keeping the access transparent in the most common case of a single value provided per key.

How do I get the parsed querystring values when using path arguments?

Versions

etr commented 1 year ago

Thanks! This is a legitimate bug we introduced when refactoring the way we manage argument extraction. A fix is in PR (https://github.com/etr/libhttpserver/pull/326)

etr commented 1 year ago

This should be fixed now on head. Let me know if you still have the problem (and feel free to reopen in case).