Skip to content

Repository files navigation

is2-ci

is2

Event driven http(s) API server library -in C++

Table of Contents

Background

Abstract

is2 is a reasonably performant event driven http(s) API server library written in C++ with support for url routing, tls (with openssl), serving static files, proxying, and subrequests.

Supports

  • threading
  • r3 like url routing with support for slugs
  • URL handler registration inspired by flask blueprints
  • tls with openssl
  • handler support for files, proxies, and subrequests.

Architecture Overview

  • is2 starts with a server object.
  • listener objects -listening on a particular port with a given scheme (TCP/TLS) can be registered with a server object.
  • handler objects can be routed to the listener objects at specified urls.

A basic example of instantation/registration:

// create a TCP listener on port 12345
ns_is2::lsnr *lsnr =
new ns_is2::lsnr(12345, ns_is2::SCHEME_TCP);
// create request handler --based on ns_is2::default_rqst_h
ns_is2::rqst_h *rqst_h = new request_handler();
// specify route to request handler on the listener
lsnr->add_route("/path1/path2", rqst_h); // create a server object
ns_is2::srvr *srvr = new ns_is2::srvr();
// register listener with server object
srvr->register_lsnr(lsnr);

The Reactor

is2 has an event system similar to libevent or libuv. The reactor is a std::priority_queue of timer events with inverted ordering, for dequeue'ing the next nearest timeout. The "next nearest timeout" is used for the subsequent call to wait for events (epoll_wait, select, kqueue).

Reactor loop psuedo code:

whiletrue:
// dequeue / handle timer events until timer > nowdo last_timer = timer_queue.dequeue
while(last_timer < now)
// wait for an event -up to the next timer event
events = wait_event(last_timer)
// handle events if anyfor each event
handle (readable/writeable/etc)

Install

Build requirements

Packages

  • openssl
  • pthread

Building example

g++ ./test.cc -lis2 -lpthread -o test

Usage

Basic example

Code

#include<is2/srvr/srvr.h>
#include<is2/srvr/lsnr.h>
#include<is2/srvr/default_rqst_h.h>
#include<is2/srvr/api_resp.h>// define handlerclassbase_handler: publicns_is2::default_rqst_h
{
public:// GET
ns_is2::h_resp_tdo_get(ns_is2::session &a_session,
ns_is2::rqst &a_rqst,
const ns_is2::url_pmap_t &a_url_pmap)
{
// send json responsereturnsend_json_resp(a_session,
true,
ns_is2::HTTP_STATUS_OK,
"{\"msg\": \"Hello World\"}");
}
};
intmain(void)
{
// create server
ns_is2::srvr *l_srvr = newns_is2::srvr();
// set server name -for server response
l_srvr->set_server_name("hello world server");
// create listener
ns_is2::lsnr *l_lsnr = newns_is2::lsnr(12345, ns_is2::SCHEME_TCP);
// create handler
ns_is2::rqst_h *l_rqst_h = newbase_handler();
// add route to listener
l_lsnr->add_route("/hello", l_rqst_h);
// register listener with server
l_srvr->register_lsnr(l_lsnr);
// num_threads == 0 means run single thread in foreground
l_srvr->set_num_threads(0);
l_srvr->run();
// cleanupif(l_srvr) {delete l_srvr; l_srvr = NULL;}
if(l_rqst_h) {delete l_rqst_h; l_rqst_h = NULL;}
return0;
}

Running

./test

Testing

>curl 'http://127.0.0.1:12345/hello' -v
* Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 12345 (#0)> GET /hello HTTP/1.1
> Host: 127.0.0.1:12345
> User-Agent: curl/7.47.0
> Accept: */*>< HTTP/1.1 200 OK
< Connection: keep-alive
< Content-Length: 22
< Content-type: application/json
< Date: Thu, 15 Feb 2018 00:42:40 GMT
< Server: hello world server
<* Connection #0 to host 127.0.0.1 left intact
{"msg": "Hello World"}

Performance with hurl

>hurl 'http://127.0.0.1:12345/hello' -t1 -p100 -l5
Running 1 threads 100 parallel connections per thread with infinite requests per connection
+-----------/-----------+-----------+-----------+--------------+-----------+-------------+-----------+
| Completed / Requested | IdlKil | Errors | kBytes Recvd | Elapsed | Req/s | MB/s |
+-----------/-----------+-----------+-----------+--------------+-----------+-------------+-----------+
| 58456 / 58556 | 0 | 0 | 11064.94 | 1.00s | 62255.49s | 10.81s || 89685 / 89785 | 0 | 0 | 11100.93 | 1.50s | 62458.00s | 10.84s || 120803 / 120903 | 0 | 0 | 11061.48 | 2.00s | 62236.00s | 10.80s || 151836 / 151936 | 0 | 0 | 11031.26 | 2.50s | 62066.00s | 10.77s || 182631 / 182731 | 0 | 0 | 10946.66 | 3.00s | 61590.00s | 10.69s || 213663 / 213763 | 0 | 0 | 11030.91 | 3.50s | 62064.00s | 10.77s || 244744 / 244844 | 0 | 0 | 11048.32 | 4.00s | 62162.00s | 10.79s || 275814 / 275914 | 0 | 0 | 11044.41 | 4.50s | 62140.00s | 10.79s || 306890 / 306990 | 0 | 0 | 11046.55 | 5.00s | 62152.00s | 10.79s || RESULTS: ALL
| fetches: 306890
| max parallel: 100
| bytes: 7.949221e+07
| seconds: 5.001000
| mean bytes/conn: 259.025090
| fetches/sec: 61365.726855
| bytes/sec: 1.589526e+07
| HTTP response codes: | 200 -- 306890

Contribute

  • We welcome issues, questions and pull requests.

License

This project is licensed under the terms of the Apache 2.0 open source license. Please refer to the LICENSE-2.0.txt file for the full terms.

About

embedded RESTy http(s) server library from Edgio

Topics

Resources

Stars

7 stars

Watchers

12 watching

Forks

Releases

Packages

Used by

Contributors

Languages