cinatra--an efficient and easy-to-use C + + HTTP Framework

Source: Internet
Author: User
Tags assert http file upload

Cinatra is a high-performance, easy-to-use HTTP framework developed with modern C + + (C++17), and its goal is to provide a fast-developing C + + HTTP framework. Its main features are as follows:

    1. A unified and simple interface
    2. Header-only
    3. Cross-platform
    4. Efficient
    5. Support for slicing programming

Cinatra currently supports http1.1/1.0 and WebSocket, you can easily use it to develop an HTTP server, such as a common database access server, file upload download server, real-time message Push server, You can also develop an MQTT server based on Cinatra.

How to use compilation dependencies

Cinatra is developed based on Boost.asio, so you need a boost library, and you need to support c++17 compilers, dependencies:

    1. Boost.asio
    2. c++17 compiler (gcc7.2,clang4.0, vs2017 update15.5)
Use

Cinatra is header-only, direct reference to the header file can be.

Quick Example Example 1: A simple Hello World
#include "http_server.hpp"using namespace cinatra;int main() {http_server server(std::thread::hardware_concurrency());server.listen("0.0.0.0", "8080");server.set_http_handler<GET, POST>("/", [](const request& req, response& res) {res.set_status_and_content(status_type::ok, "hello world");});server.run();return 0;}

5 lines of code can implement a simple HTTP server, the user does not need to pay attention to how much detail, directly write business logic on the line.

Example 2: Show how to fetch headers and query and return errors
#include "http_server.hpp" usingNamespaceCinatra;int Main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ( "/test", [] (const request& req, response& res) {Auto Name = Req.get_header_value ( "name");  if (Name. Empty ()) {res.set_status_and_content (status_type::bad_request,  "no Name"); return;} Auto id = req.get_query_value ( "id");  if (Id. Empty ()) {res.set_status_and_content (status_type::bad_request);  "Hello World");}); Server.run (); return 0;}         
Example 3: Slice-oriented HTTP server
#include"Http_server.hpp" using namespace Cinatra;Log slicesstructlog_t{BOOL Before (Const request& req, response& res) {std::cout <<"Before log" << Std::endl;Returntrue;}BOOL After (Const request& req, response& res) {std::cout <<"After log" << Std::endl;Returntrue;}};Tangent plane of the checksumstructCheck {BOOL Before (Const request& req, response& res) {std::cout <<"Before check" << Std::endl;if (Req.get_header_value ("Name"). Empty ()) {res.set_status_and_content (status_type::bad_request);ReturnFALSE;} return true;} bool after (const request& req, response& Res) {std:: cout <<  "after check" << std::endl; return true;}; int Main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ( Span class= "hljs-string" > "0.0.0.0",  "/aspect", [] (const request& req, response& res) {Res.set _status_and_content (Status_type::ok, return 0;}         

In this case, there are two facets, one for verifying the HTTP request, and one for the log slice, which can be arbitrarily increased by the user on demand. This meeting first check the legality of HTTP request, if illegal will return bad request, legal will go into the next section, that is, the log plane, Liu'an Radio and television University log slice will print out a before represents the processing before entering the business logic, After the Chizhou pioneer network business logic is complete, after the after represents the end of the business logic, the processing is printed.

Example 4: File Upload

Cinatra currently supports uploads in multipart and octet-stream formats.

Multipart File Upload
#include <atomic>#include "http_server.hpp" usingNamespaceCinatra;int Main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ("0.0.0.0","8080"); Std::atomic_int n =0;HTTP upload (multipart) server.set_http_handler<get, post> ("/upload_multipart", [&n] (Const request& req, response& Res) {assert (Req.get_http_type () = = Http_type::multipart); auto state = Req.get_ State ();Switch (state) {Case Cinatra::d ata_proc_state::d ata_begin:{auto file_name_s = Req.get_multipart_file_name (); Auto Extension = get_ Extension (file_name_s); std::string file_name = std::to_string (n++) + std::string (Extension.data (), Extension.length ( )); Auto file = Std::make_shared<std::ofstream> (file_name, std::ios::binary);if (!file->is_open ()) {res.set_continue (FALSE);return;} Req.get_conn ()->set_tag (file);}BreakCase Cinatra::d ata_proc_state::d ata_continue:{if (!res.need_continue ()) {return;} Auto File = std::any_cast<std::shared_ptr<std::ofstream>> (Req.get_conn ()->get_tag ()); auto Part_data = Req.get_part_data (); File->write (Part_data.data (), part_data.length ());}Break ; Case Cinatra::d ata_proc_state::d ata_end:{std::cout << "one file finished" << Std::endl;} Break ; Case Cinatra::d ata_proc_state::d ata_all_end:{//all the upstream endstd::cout << ' All files finished ' << std::endl;res.set_status_and_content (Status_type::ok);} Break ; Case Cinatra::d ata_proc_state::d ata_error:{//network Error};}); Server.run (); return 0;}            

Just a few lines of code can implement an HTTP file upload server, including exception handling and error handling.

Octet-stream File Upload
#include <atomic>#include "http_server.hpp" usingNamespaceCinatra;int Main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ("0.0.0.0","8080"); Std::atomic_int n =0;HTTP upload (octet-stream) server.set_http_handler<get, post> ("/upload_octet_stream", [&n] (Const request& req, response& Res) {assert (Req.get_http_type () = = Http_type::octet_stream); auto state = Req.get_ State ();Switch (state) {Case Cinatra::d ata_proc_state::d ata_begin:{std::string file_name = std::to_string (n++);; Auto File = std::make_shared<std::ofstream> (file_name, std::ios::binary);if (!file->is_open ()) {res.set_continue (FALSE);return;} Req.get_conn ()->set_tag (file);} break; case Cinatra::d ata_proc_state::d ata_continue:{if (! Res.need_continue ()) {return;} Auto File = std::any_cast<std::shared_ptr<std::ofstream>> (Req.get_conn ()->get_tag ()); auto Part_data = Req.get_part_data (); File->write (Part_data.data (), part_data.length ());} break; case Cinatra::d ata_proc_state::d ata_end:{std::cout <<  "One file finished" << Std::endl;} break; case Cinatra::d ata_proc_state::d ata_error:{//network error }break;}); Server.run (); return 0;}         
Example 5: File download
#include"Http_server.hpp" using namespace Cinatra;int main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ("0.0.0.0","8080");HTTP Download (chunked) Server.set_http_handler<get, post> ("/download_chunked", [] (Const request& req, response& res) {Auto state = req.get_state (); switch (state) {case Cinatra::d ata_proc_state:: data_begin:{std::string filename ="2.jpg"; autoin = std::make_shared<std::ifstream> (filename, std::ios::binary);if (!In->is_open ()) {Req.get_conn ()->on_error ();return;} Auto conn = Req.get_conn (); Conn->set_tag (IN) Auto Extension = Get_extension (Filename.data ()); auto MIME = get_mime_type (extension); conn->write_chunked_ Header (MIME);}Break;case Cinatra::d ata_proc_state::d Ata_continue:{auto conn = Req.get_conn (); autoin = Std::any_cast<std::shared_ptr<std::ifstream>> (Conn->get_tag ()); std::stringStrConst size_t len =*1024;Str.resize (len);In->read (&str[0], Len); size_t Read_len = in->gcount ();  if (Read_len! = len) {str.resize (read_len);} bool EOF = (read_len==0| | read_len = len); Conn->write_chunked_data (std::Move (str), EOF);} break;case Cinatra::d ata_proc_state::d ata_end:{std::cout << "chunked send Finish" << Std::endl;} break;case Cinatra::d ata_proc_state::d ata_error:{//network error} break;}); Server.run (); return 0;}                
Example 6:websocket
#include "http_server.hpp" usingNamespaceCinatra;int Main () {Http_server server (std::thread::hardware_concurrency ()); Server.listen ("0.0.0.0","8080");Web Socketserver.set_http_handler<get, post> ("/ws", [] (Const request& req, response& Res) {assert (Req.get_http_type () = = Http_type::websocket); auto state = Req.get_ State ();Switch (state) {Case Cinatra::d ata_proc_state::d ata_begin:{std::cout <<"websocket start" << Std::endl;} Break ; Case Cinatra::d ata_proc_state::d ata_continue:{auto part_data = Req.get_part_data ();  Echoreq.get_conn ()->send_ws_msg (std::string (Part_data.data (), Part_data.length ()), Std::cout << Part_ Data.data () << Std::endl;} Break ; Case Cinatra::d ata_proc_state::d ata_close:{std::cout << "WebSocket close" << Std::endl;} Break ; Case Cinatra::d ata_proc_state::d ata_error:{std::cout << "Network error" << Std::endl;} Break ;}); Server.run (); return 0;}            
Performance test test Cases:

AB Test: ab-c100-n5000 127.0.0.1:8080/

The server returns a hello.

Test on a 8-core 16G cloud host, with QPS between 9000-13000.

Contrast test

The comparison between the AB test and the boost.beast is quite, presumably because both are based on the Boost.asio development. Cinatra has not yet done a special performance optimization, and there is room for improvement.

Precautions

File upload and download, websocket business functions will be entered many times, so write business logic should pay attention to, recommended in the example of the way to do.

Cinatra is just beginning to use in the production environment, is still in the development of the perfect stage, there may be some bugs, so it is not recommended to use directly in the production environment at this stage, it is recommended to test the environment first.

Trial no problem again in the production environment to use, the trial process found the problem please timely issue feedback or email contact me.

After testing and use is stable, Cinatra will release the official version.

Roadmap
    1. Support SSL
    2. Support for breakpoint continuation
    3. Support Session and Cookies
    4. interface optimization, performance optimization

I hope Cinatra have more and more people to use and like it, but also hope that in the use of the process more and more perfect, become a powerful and easy to develop the HTTP framework, welcome to actively participate in the Cinatra project, you can mention issue can also send suggestions, can also mention PR, Form Unlimited.

The refactoring Cinatra is almost rewritten, with code less than 30%, with a unified interface, HTTP and business separation, and better extensibility and maintainability.

cinatra--an efficient and easy-to-use C + + HTTP Framework

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.