HTTP

include: co/http.h.

#http::Client

http::Client is a coroutine-based HTTP client, which is implemented based on libcurl.

#Client::Client

explicit Client(const char* serv_url);
  • Constructor, the parameter serv_url is the url address of the server, and its form is protocol://host:port, the following server urls are all ok:
    • “github.com”
    • https://github.com
    • “http://127.0.0.1:7788”
    • “http://[::1]:8888”
  • Connection is not established in the constructor.

#Client::~Client

Client::~Client();
  • Destructor, close the connection, and release libcurl related resources.

#Client::add_header

void add_header(const char* key, const char* val);
void add_header(const char* key, int val);
  • Add a HTTP header.
  • Users can use this method to add headers before performing HTTP requests, and the added headers will be present in all subsequent requests.
  • In the second version, the parameter val is an integer, which is automatically converted to string internally.

#Client::body

const fastring& body() const;
  • Get the response body of the current HTTP request.

#Client::close

void close();
  • Close the HTTP connection, must be called in coroutine.
  • Once this method is called, the http::Client object can no longer be used until you reset the server url by calling reset().

#Client::del

void del(const char* url, const char* s, size_t n);
void del(const char* url, const char* s);
void del(const char* url);
  • HTTP DELETE request, must be called in coroutine.
  • The parameter url must be a string beginning with '/'.
  • The first two versions are suitable for DELETE requests with a body, and parameter s is a pointer to the body data.
  • The third version is for DELETE requests without body.

#Client::easy_handle

void* easy_handle() const;
  • Return the easy handle of libcurl.

#Client::get

void get(const char* url);
  • HTTP GET request, must be called in coroutine.
  • The parameter url must be a string beginning with /.

#Client::head

void head(const char* url);
  • HTTP HEAD request, must be called in coroutine.
  • The parameter url must be a string beginning with /.

#Client::header

const char* header(const char* key);
const fastring& header() const;
  • The first version gets value of a HTTP header. If the header does not exist, an empty string is returned.

  • The second version gets the entire HTTP header part (include the start line).

  • Example

http::Client c("xx.com");
c.get("/");
auto s = c.header("Content-Length");

#Client::perform

void perform();
  • Perform a HTTP request, get, post and other methods are actually implemented based on this method.

  • Users generally don’t need to call this method. Only when the get, post and other methods provided by http::Client can’t meet their needs, should they consider using this method to customize HTTP requests.

  • Example

void Client::post(const char* url, const char* data, size_t size) {
    curl_easy_setopt(_ctx->easy, CURLOPT_POST, 1L);
    curl_easy_setopt(_ctx->easy, CURLOPT_URL, make_url(url));
    curl_easy_setopt(_ctx->easy, CURLOPT_POSTFIELDS, data);
    curl_easy_setopt(_ctx->easy, CURLOPT_POSTFIELDSIZE, (long)size);
    this->perform();
}

#Client::post

void post(const char* url, const char* s, size_t n);
void post(const char* url, const char* s);
  • HTTP POST request, must be called in coroutine.
  • The parameter url must be a string beginning with /.

#Client::put

void put(const char* url, const char* path);
  • HTTP PUT request, used to upload a file, must be called in coroutine.
  • The parameter url must be a string beginning with /.
  • The parameter path is path of the file to be uploaded.

#Client::remove_header

void remove_header(const char* key);
  • The headers added by add_header() method will apply to all subsequent HTTP requests. If users do not want a header to appear in subsequent requests, this method can be called to remove the header.

#Client::reset

void reset(const char* serv_url);
  • Reset the server url.

#Client::response_code

int response_code() const;
  • Get the response code of the current HTTP request.
  • Normally, the return value is a value between 100 and 511.
  • If the HTTP request is not sent due to network error or other reasons, or no response from the server was received within the timeout period, this method returns 0, and strerror() can be called to get the error message.

#Client::status

int status() const;

#Client::strerror

const char* strerror() const;
  • Get the error message of the current HTTP request.

#Example

void f() {
    http::Client c("https://github.com");
    int r;
    
    c.get("/");
    r = c.status();
    LOG << "staus: " << r;
    LOG_IF(r == 0) << "error: " << c.strerror();
    LOG << "body size: " << c.body().size();
    LOG << c.header();

    c.get("/idealvin/co");
    LOG << "body size: " << c.body().size();
    LOG << "Content-Length: " << c.header("Content-Length");
    LOG << c.header();

    c.close();
}

go(f);

#http::Req

http::Req is an encapsulation of HTTP request, it is used in http::Server.

#Req::Req

Req() = default;
  • Default constructor.

#Req::body

const char* body() const;
  • Get the body data in the HTTP request.
  • It returns a pointer, not null-terminated. Users must call body_size() to get its length.

#Req::body_size

size_t body_size() const;
  • Returns length of the HTTP request body.

#Req::header

const char* header(const char* key) const;
  • Get value of a HTTP header. If the header does not exist, an empty string is returned.

#Req::is_method_xxx

bool is_method_get() const;
bool is_method_head() const;
bool is_method_post() const;
bool is_method_put() const;
bool is_method_delete() const;
bool is_method_options() const;
  • Determine the method type of the HTTP request.

#Req::method

Method method() const;
  • Returns the HTTP request method, the return value is one of kGet, kHead, kPost, kPut, kDelete, kOptions.

#Req::url

const fastring& url() const;
  • Returns a reference to the url in the HTTP request. This value is part of the start line of the HTTP request.

#Req::version

Version version() const;
  • Returns version in the HTTP request. The return value is one of http::kHTTP10 or http::kHTTP11. Currently, HTTP/2.0 is not supported.

#http::Res

http::Res class is the encapsulation of HTTP response, it is used in http::Server.

#Res::Res

Res();
  • Default constructor.

#Res::add_header

void add_header(const char* key, const char* val);
void add_header(const char* key, int val);
  • Add a HTTP header.

#Res::set_body

void set_body(const void* s, size_t n);
void set_body(const char* s);
void set_body(const fastring& s);
  • Set the body part of the HTTP response.
  • The parameter s is the body data, and the parameter n is the length of s. In the second version, s ends with '\0'.

#Res::set_status

void set_status(int status);
  • Set the HTTP response code, this value is generally between 100 and 511.

#http::Server

http::Server is a coroutine-based HTTP server. It supports HTTPS. To use HTTPS, you need to install openssl first.

#Server::Server

Server();
  • The default constructor, users don’t need to care.

#Server::on_req

Server& on_req(std::function<void(const Req&, Res&)>&& f);
Server& on_req(const std::function<void(const Req&, Res&)>& f)

template<typename T>
Server& on_req(void (T::*f)(const Req&, Res&), T* o);
  • Set a callback for handling a HTTP request.
  • In the third version, the parameter f is a method in class T, and the parameter o is a pointer to type T.
  • When the server receives a HTTP request, it will call the callback set by this method to handle the request.

#Server::start

void start(const char* ip="0.0.0.0", int port=80);
void start(const char* ip, int port, const char* key, const char* ca);
  • Start the HTTP server, this method will not block the current thread.
  • The parameter ip is the server ip, which can be an IPv4 or IPv6 address, and the parameter port is the server port.
  • The parameter key is the path of a PEM file which stores the SSL private key, and the parameter ca is the path of a PEM file which stores the SSL certificate. If key or ca is NULL or empty string, SSL will be disabled.
  • Starting from v3.0, the server no longer depends on the http::Server object after startup.

#Server::exit

void exit();
  • Added since v2.0.2.
  • Exit the HTTP server, close the listening socket, and no longer receive new connections.
  • Since v3.0, after the HTTP server exits, previously established connections will be reset in the future.

#Example

void cb(const http::Req& req, http::Res& res) {
    if (req.is_method_get()) {
        if (req.url() == "/hello") {
            res.set_status(200);
            res.set_body("hello world");
        } else {
            res.set_status(404);
        }
    } else {
        res.set_status(405); // method not allowed
    }
}

// http
http::Server().on_req(cb).start("0.0.0.0", 80);

// https
http::Server().on_req(cb).start(
    "0.0.0.0", 443, "privkey.pem", "certificate.pem"
);

#Static web server

void easy(const char* root_dir=".", const char* ip="0.0.0.0", int port=80);
void easy(const char* root_dir, const char* ip, int port, const char* key, const char* ca);
  • Start a static web server, the parameter root_dir is the root directory of the web server.

  • The parameter ip can be an IPv4 or IPv6 address.

  • The second version supports HTTPS, the parameter key is the SSL private key, the parameter ca is the SSL certificate, and both key and ca are files in pem format. When key or ca is NULL or an empty string, HTTPS is disabled.

  • This method will block the current thread.

  • Example

#include "co/flag.h"
#include "co/http.h"

DEF_string(d, ".", "root dir"); // root dir of web server

int main(int argc, char** argv) {
    flag::parse(argc, argv);
    so::easy(FLG_d.c_str()); // mum never have to worry again
    return 0;
}

#Config items

Coost uses co.flag to define config items for HTTP.

#http_conn_timeout

DEF_uint32(http_conn_timeout, 3000, "#2 connect timeout in ms for http client");
  • Connect timeout in milliseconds for http::Client.

#http_timeout

DEF_uint32(http_timeout, 3000, "#2 send or recv timeout in ms for http client");
  • Receive and send timeout (libcurl does not distinguish between receive and send timeout) in milliseconds for http::Client.

#http_recv_timeout

DEF_uint32(http_recv_timeout, 3000, "#2 recv timeout in ms for http server");
  • Recv timeout in milliseconds for http::Server.

#http_send_timeout

DEF_uint32(http_send_timeout, 3000, "#2 send timeout in ms for http server");
  • Send timeout in milliseconds for http::Server.

#http_conn_idle_sec

DEF_uint32(http_conn_idle_sec, 180, "#2 http server may close the con...");
  • Timeout in seconds for http::Server to keep an idle connection. If the server does not receive data from the client within this time, it may close the connection.

#http_log

DEF_bool(http_log, true, "#2 enable http server log if true");
  • For http::Server, whether to print logs, the default is true.
  • The log in http::Server will print the header part of HTTP request and response.

#http_max_idle_conn

DEF_uint32(http_max_idle_conn, 128, "#2 max idle connections for http server");
  • For http::Server, maximum number of idle connections. When this number is exceeded, some idle connections will be closed.

#http_max_body_size

DEF_uint32(http_max_body_size, 8 << 20, "#2 max size of http body, default: 8M");
  • The maximum body length supported by http::Server, the default is 8M.

#http_max_header_size

DEF_uint32(http_max_header_size, 4096, "#2 max size of http header");
  • The maximum header (the entire HTTP header) length supported by http::Server, the default is 4k.