Parse REST query in C++

a 夏天 提交于 2019-12-06 03:53:24

问题


I'd like to expose a REST API on my application, using the Mongoose web server and providing handlers for different queries.

An example of query would be like this (I'm only using GET for the moment, the rest of HTTP verbs will come later):

GET /items -> returns a list of all items in JSON
GET /item/by/handle/123456789 -> returns item that has handle 123456789
GET /item/by/name/My%20Item -> returns item(s) that have the name "My Item"

What I'm curious is how I should implement the parsing of these queries. I can easily parse the first, since it is simply a matter of if( query.getURI() == "/items") return ....
But for the next two queries, I have to manipulate std:: strings in a whole different way, using some std::string::find() magic and offsets to get to the argument.

As an example, this is the implementation I have for the second query:

size_t position = std::string::npos;
std::string path = "/item/by/handle/";

if( (position = query.getURI().find(path) ) != std::string::npos )
{
    std::string argument = query.getURI().substr( position + path.size() );
    // now parse the argument to an integer, find the item and return it
}

What if I want to "templatize" this; meaning: I describe the path and the arguments I expect afterwards (an integer, a string, ....); and the code is automatically generated to handle this?

Tl;Dr: I want to be able to handle REST queries in C++ with something along these lines:

registerHandler( "/item/by/handle/[INTEGER]", myHandlerMethod( int ));

Is this possible?


回答1:


A rather un-sexy, yet simple approach would be to simply use sscanf. Pardon the rather C-like code. Note, this doesn't provide the sort of syntax you're looking for, but it doesn't require any libraries, extensions, or boost.

For example,

int param;
int a, b;
char c[255];

/* recall that sscanf returns the number of variables filled */
if( 1 == sscanf( query.getURI(), "/item/by/handle/%d", &param ) ) {

  handler( param );

} else if ( 3 == sscanf( query.getURI(), "/more/params/%d/%d/%s", &a, &b, &c ) ) {

  anotherHandler( a, b, c );

} else {
  // 404
}



回答2:


While foraging through some Python code, I found that the Flask web framework has a particular way of parsing REST paths:

You declare a path like this:

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return 'Post %d' % post_id

And Flask builds up what's needed around to give you the integer you need.

That's exactly what I need, so I guess I'll have to do it by myself in C++.
I'll get Tom's answer since it's relevant, and I guess my implementation will look a bit like he suggests (altough I tend to prefer iostreams).

I'll leave this answer here to anybody lurking around.




回答3:


The project drogon on github (project Drogon,a c++11 web framework)may be helpful to you. In this framework, you can register your handler method like this:

drogon::HttpAppFramework::registerHttpApiMethod("/api/v1/handle/{1}/{2}",yourMethod...);

yourMethod maybe any callable object.

The HttpApiController class is a simple wrapper class that allows you to register functions with macros. There are examples in the project that demonstrate the use of these functions.

Hope it helps you..



来源:https://stackoverflow.com/questions/9148667/parse-rest-query-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!