Index
#include <x/http/useragent.H> #include <iterator> #include <iostream> #include <cstdlib> void http_example() { x::http::useragent::base::https_enable(); x::http::useragent ua(x::http::useragent::create(x::http::noverifycert)); x::http::useragent::base::response resp=ua->request(x::http::GET, "https://localhost"); std::cout << resp->message.get_status_code() << " " << resp->message.get_reason_phrase() << std::endl; for (auto hdr: resp->message) { std::cout << hdr.first << "=" << hdr.second.value() << std::endl; } if (resp->has_content()) { std::copy(resp->begin(), resp->end(), std::ostreambuf_iterator<char>(std::cout.rdbuf())); std::cout << std::flush; } if (resp->message.get_status_code_class() != x::http::resp_success) exit(1); } int main() { http_example(); return 0; }
This is an example of implementing a basic HTTP client.
x::http::useragent
and
x::http::useragentptr
are a reference and a nullable pointer reference to a
reference-counted object that implements
a generic HTTP “user agent” client.
A user agent object manages connections with HTTP
servers.
An application should invoke x::http::useragent::base::https_enable
()
if the application uses HTTPS.
This is strictly necessary only when employing static linking. Linking
with -lcxxtls
dynamically automatically enables
HTTPS;
but using static linkage is convenient when debugging, and that requires
x::http::useragent::base::https_enable
().
The create
() method takes three optional parameters
that specify configuration options for the user agent object.
The first parameter is a set of flags (use 0 to specify none of the
following):
x::http::noverifypeer
For HTTPS connections, do not verify that the server's certificate's name matches the server's name.
x::http::noverifycert
For HTTPS connections, do not verify that the server's certificate is signed by a trusted certificate authority, and do not verify that the server's certificate's name matches the server's name.
The list of trusted certificate authorities is set by the
x::gnutls::calist
property.
When enabled the same user agent object manages both HTTP and HTTPS connections. An application can create multiple user agent objects, with different options. The reference-counted user agent object is thread safe. A single user agent object may be used, simultaneously, by multiple threads.
HTTP 1.1 servers can use the same connection for
multiple requests.
The user agent object handles one request at a time, and saves
open HTTP 1.1 connections internally. A subsequent
request for a URI with the same server tries to use the
existing connection, if it is still open.
The second optional parameter to create
()
sets the maximum number of simultaneous connections saved by a
user agent object, and defaults to the
x::http::useragent::pool::maxconn
property.
The third optional parameter, that defaults to the
x::http::useragent::pool::maxhostconn
property, sets the maximum number of saved connections to the same
server.
These properties do not set the maximum number of simultaneous requests, but the maximum number of unused connections saved by the user agent objects. When the number of unused connections exceed these maximums, the oldest connections get closed, as many as needed to bring them down below the limits.
The user agent's
request
() method is heavily overloaded,
and takes the following parameters:
A terminator file descriptor object.
x::fd timeoutfd; // ... auto resp=ua->request(timeoutfd, x::http::GET, "https://localhost");
request
() sends a request and waits until
the server responds.
request
() does not return until it receives
a response.
The
x::http::client::response_timeout
property defaults to fifteen
minutes. If the server does not reply, the request times out and
a timeout response object gets returned.
The first parameter to
request
() can optionally be a
terminator file descriptor.
If it becomes readable, the request gets aborted before the
timeout expires.
If specified, the timeout property does not get overridden, but
rather supplemented. The request times out either when the
interval specified by
x::http::client::response_timeout
elapses,
or the terminator file descriptor becomes readable,
whichever occurs first.
An HTTP request method.
One of the HTTP request types,
usually x::HTTP::GET
or
x::HTTP::POST
.
A URI.
The next parameter to request
() is a
x::uriimpl
that specifies the requested
URI being requested.
The x::uriimpl
is
constructable from a literal string. To use
international domain
names, it is necessary to construct it explicitly:
auto resp=ua->request(timeoutfd, x::http::GET, x::uriimpl("http://привет.example.com", x::locale::base::utf8()));
A reference to an x::requestimpl
.
This is an alternative for a method and a URI. The following
two examples are generally equivalent to each other.
auto resp=ua->request(x::http::GET, "http://localhost");
x::http::requestimpl req; req.set_method(x::http::GET); req.set_URI("http://localhost"); auto resp=ua->request(req);
request
() receives a
x::http::requestimpl
by reference, and
may adjust its contents in order to format the request according
to the connection parameters.
Additional HTTP headers.
auto resp=ua->request(x::http::GET, "http://localhost", "Accept", "text/plain", "Accept-Language", "en");
An optional list of name/value tuples follows the request method
and the URI.
If specified, the HTTP request includes these
as custom headers (a name/value tuple list may also
follow if they are replaced by a
x::http::requestimpl
, which has the effect
of modifying the x::http::requestimpl
object).
This example adds “Accept: text/plain” and “Accept-Language: en” to the request. See RFC 2616 for a list of headers that can be added.
An HTTP form or content.
The last parameter to request
() is optional.
It specifies any content that's part of the request. There are two
ways to specify the content.
auto resp=ua->request(x::http::POST, "http://localhost/cgi-bin/req.pl", x::http::form::parameters::create("username", "alfred", "password", "rosebud"));
An
x::http::form::parameters
parameter specifies HTTP form parameters as
the contents of the request.
The above example specifies two parameters,
“username=alfred” and
“password=rosebud”.
For a x::http::GET
request, this sets the
“query string” part of the URI, otherwise the request's
“Content-Type” header gets set to
“application/x-www-form-urlencoded” and the request's
content consists of the form's parameters, appropriately encoded.
std::vector<char> buf; // ... auto resp=ua->request(x::http::POST, "http://localhost/cgi-bin/upload.pl", "Content-Type", "text/plain", std::make_pair(buf.begin(), buf.end()));
Non-form request content takes the form of a
std::pair
with a beginning and an
ending iterator that define an input sequence that forms the content
of the request.
The iterators must be, at a minimum, forward iterators. Input iterators are not sufficient. Random access iterators are preferred. Content defined by non-random access iterators may have to be iterated over more than once, depending on the connection parameters with the HTTP server.
Requests should specify a complete, absolute URI.
Do not set a “Host” header in the request, giving the
hostname part of the URI.
Just specify an absolute URI and
request
() takes
care of formatting the request.