7

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
  • Sounds like you need regular expressions, as found in boost or C++11. Commented Feb 5, 2012 at 14:45

3 Answers 3

5

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
}
Sign up to request clarification or add additional context in comments.

2 Comments

Note that using %s is dangerous for user input, cause it doesn't check for boundaries and could be easily overflown. I suggest for the above example: sscanf(query.getURI(), "/more/params/%d/%d/%254s", &a, &b, c)
Good point. For those who want to prevent this, Kernighan and Pike have an easy solution: stackoverflow.com/questions/1621394/…
1

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

Comments

0

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.

1 Comment

Did you end up implementing this syntax in C++? - If so, have you considered open-sourcing it? :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.