Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Parse REST query in C++

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?

like image 918
Gui13 Avatar asked Feb 05 '12 10:02

Gui13


2 Answers

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
}
like image 124
Tom Avatar answered Sep 17 '22 23:09

Tom


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..

like image 33
eprom Avatar answered Sep 21 '22 23:09

eprom