Working with HTTP Listener

Feb 5, 2014 at 4:50 PM
I spent the last couple hours working with HTTP listener for web APIs (JSON request bodies and responses, computationally intense implementations). I managed to stumble my way through logging and authorization (listener.add_handler) and payload (de)serialization (json::value) and found it easy enough to use.

I'm now looking into how to route URLs. It appears there is no support for URL routing -- is that correct? That's okay for me (I've needed to implement custom routing in ASP.NET MVC anyway), I just want to be sure I'm not missing something.

Also, I was a little perplexed by the task<void> versus task<response> return types from request.reply() versus the add_handler lambda, but I managed -- am I missing some subtly here as well?. What is the correct way to say "do this after next_stage is completed" (presumably using then(...))?

Is possible, how do I check the response created by the next stage, and/or alter some of what it provided (e.g. to implement Content-Encoding: gzip). Likewise, I generally like to support compression of POST/PUT data as well -- is there a way to provide a decompressed stream to next_stage?

Sorry for all the questions, I've spent a few years away from C++ and am just getting back into it (thanks to Casablanca).
Feb 8, 2014 at 2:36 AM
Hi CircuitPeople

Thank you for contacting us with your questions :)

Regarding URL routing: We can create multiple listeners listening on different paths, in the same process. This can help achieve URL routing. For an example, refer to the testcase "uri_routing" in suite "listener_construction_tests", test file: Release\tests\Functional\http\listener\listener_construction_tests.cpp.

To respond to requests received by the listener, use the http_listener::support() API.
Also please note that we will be removing the add_handler feature in our next release. add_handler allowed to look at the incoming request, perform some action and pass it to the next stage for processing. Such functionality can also be implemented in the listener support handler (http_listener::support) itself.

In the support handler, you can look at the incoming request object, perform some functionality like authorization, construct a response object and respond to the request. If you wish to perform multiple actions, call them one after the other in the support handler. Remember to call request.reply() to send the response. To perform something after sending the response to the client, attach a continuation to the task returned by reply().

Casablanca does not support compressing/decompressing data. However, in the listener support() handler, you can create a new http_response object. And use the http_response::set_body() API to set the body stream, this can be a compressed data as well. Example:
    listener.support([&](http_request request) // Handler to process incoming request.
    {
        // Inspect the incoming request
        http_response response(status_codes::OK); // Create the response object, the next few lines will set different properties on the response.
        auto stream = streams::file_stream<uint8_t>::open_istream(fname).get(); // Create a file stream to be sent as the response body.
        response.set_body(stream);
        response.headers().set_content_type(U("text/plain; charset=utf-8")); // Specify the content type of the response
        response.headers().set_content_length((size_t)length);
        request.reply(response).wait(); // Reply to the client, wait for the reply to complete (if required). 
    });
I would also recommend looking at our test cases (Release/tests/Functional/http/listener/) and samples (BlackJack_Server and CasaLens located at Release/collateral/Samples/) for reference.

We would love to hear your feedback about the library and answer any further questions you have.

Thanks
Kavya