Asynchronous Boost C++ HTTP/HTTPS server

3 views
Skip to first unread message

Michael Munson

unread,
Jul 20, 2017, 3:56:49 AM7/20/17
to Todd Sundsted, MOO-...@googlegroups.com
I'm about 90% done with adding a native C++ asynchronous HTTP server (and client actually) using Boost.

It adds a new data type (HTTP_RESOURCE) which is a complex type and is basically a simple structure consisting of: 

  1. a std::string consisting of the server name (i.e. domain name) -- if null it answers requests on this path on all server names. 
  2. a std::string consisting of a regular expression to use for path matching for this resource
  3. resourceType - an enum consisting of HTTPD_RESOURCE_MOO (0), and HTTPD_RESOURCE_FILESYSTEM (1)
    • HTTP_RESOURCE_FILESYSTEM will skip the MOO entirely basically and serve whatever matches this resource from the filesystem (maintaining the pseudo-chroot of moo/files/ being /)
    • HTTP_RESOURCE_MOO indicates the MOO will process everything in-code.
  4. an Object ID consisting of the object ID of the "resource object" which is used if the resourceType is HTTP_RESOURCE_MOO -- it expects certain properties and verbs to exist on this object, although it will fail gracefully if they don't exist. The primary ones are just the HTTP methods, as verbs - :get :post :put :delete, etc. An example of a property it looks for is decodeJSON which controls whether or not to try to decode parameters or the HTTP body as JSON, either entirely or if it is a list it will only decode specific parameters. Another is convertParameters which controls whether HTTP parameters are converted into verb arguments (both either all or only some.) For example, you could set "decodeJSON" to "true" and convertParameters to {"username", "password"} and have it add (if they exist) username and password parameters decoded JSON values into the :get() call. Theres decodeBase64 which functions identically to the others, although I only recommend explicitly setting the parameters/values you want decoded in order to prevent it from wasting CPU trying to decode everything iteratively.
It works in a manner similar to the HTTP Server Todd made in MOO-code in that it will send an anonymous object of the request, and response (which are created based on what is pointed to by $server_options.http_request, etc -- and are additionally just random objects it expects certain properties and verbs to exist on) to whatever HTTP method is used. So like in the above convertParameters example, if someone GET /?username=meow&password=hiss in that case it would call resourceObj:get(requestObj, responseObj, "meow", "hiss"). The only difference is that it's Boost that is handling most everything, and that I wanted to change the way the paths work to allow for regex matching in native C++.

One difference is that it will not support the way Todd's server could theoretically have the response be modified by multiple paths if they matched. Only the first one to match will be used.


What does everyone think? It's not quite ready for prime time but it is close to ready to create a new branch and invite testing.

I'm mainly interested if Todd would be willing to PR into stunt master branch after sufficient testing.

HTTPS _is_ supported, the certificates have to be on the file system and are specified when the HTTP server is started.

I'd like to add a jsonQuery like CURL/GET operator into MOO for asynchronous access to external APIs, but I'm not sure how to modify the lexer 


Michael Munson

unread,
Jul 20, 2017, 4:01:27 AM7/20/17
to Todd Sundsted, MOO-...@googlegroups.com
Oh, there is also another object that it just expects to be properly formatted, which is for the HTTP server itself. It expects properties such as port, serverName (can be empty), a list of resources. If the resources change you have to restart the server for it to re-read them, which is where it does error-checking and would fail if critical things are missing or malformed in any of the above.

Michael Munson

unread,
Jul 20, 2017, 4:10:15 AM7/20/17
to Todd Sundsted, MOO-...@googlegroups.com
I actually may strip out the extra data type and just have every resource be an object and use properties for the values I need. I am pretty sure I fucked a few things up in adding a new data type anyway. That would have the benefit of having the verbs be right there on the object atleast, unless it was the filesystem type.

On Thu, Jul 20, 2017 at 1:56 AM, Michael Munson <michael....@gmail.com> wrote:
Reply all
Reply to author
Forward
0 new messages