Client Class Reference

#include <Pt/Http/Client.h>

HTTP user agent. More...

Inherits Connectable, and NonCopyable.

Public Member Functions

 Client ()
 Default Constructor.
 Client (const Net::Endpoint &ep)
 Construct with host to connect to.
 Client (System::EventLoop &loop)
 Construct with event loop.
 Client (System::EventLoop &loop, const Net::Endpoint &ep)
 Construct with loop and host to connect to.
 ~Client ()
 Destructor.
System::EventLooploop () const
 Returns the used event loop.
void setActive (System::EventLoop &loop)
 Sets the event loop to use.
void setTimeout (std::size_t timeout)
 Set timeout for I/O operations.
void setSecure (Ssl::Context &ctx)
 Enables HTTPS with ctx.
void setPeerName (const std::string &peer)
 Sets the expected SSL peer name.
void setHost (const Net::Endpoint &ep)
 Sets the host to connect to.
void setHost (const Net::Endpoint &ep, const Net::TcpSocketOptions &opts)
 Sets the host to connect to.
const Net::Endpointhost () const
 Returns the host to connect to.
Requestrequest ()
 Returns the request to send.
const Requestrequest () const
 Returns the request to send.
Replyreply ()
 Returns the received reply.
const Replyreply () const
 Returns the received reply.
void beginSend (bool finished=true)
 Begins sending the request.
MessageProgress endSend ()
 End sending the request.
Signal< Client & > & requestSent ()
 Signals that a part of the request was sent.
void beginReceive ()
 Begin receiving the reply.
MessageProgress endReceive ()
 End receiving the reply.
Signal< Client & > & replyReceived ()
 Signals that a part of the reply was received.
void close ()
 Closes the connection and cancels all operations.
void send (bool finished=true)
 Blocks until request is sent.
std::istream & receive ()
 Blocks until reply is received.

Detailed Description

Client is the HTTP user agent in the client model. It holds one Request and one Reply. Fill the request, send it, and read the reply. The client opens a TCP connection to its host when a send needs one, so there is no separate connect method. The host is an Endpoint passed to a constructor or to setHost().

Asynchronous work needs an EventLoop, passed to a constructor or to setActive(). The loop does not own the client; keep the client alive while an operation is still waiting on the loop. setTimeout() bounds I/O. send() and receive() are the blocking forms of the same exchange.

The request is request(). Set the URL, the method, query parameters and header fields before the send starts, and write the body with request().body(). The default method is GET. The reply is reply() after a receive step has made it available.

Asynchronous receive is beginReceive() and endReceive(). replyReceived() is emitted when a step has completed. The slot calls endReceive(), which returns MessageProgress. If the header is available, the status can be read; if the body is available, it can be read from reply().body(); if the reply is not finished, beginReceive() continues the same reply. A short reply often completes in one step.

The example is an asynchronous GET. The client is constructed with the loop and the host, the request URL is set, and beginReceive() starts the exchange. The slot ends each receive step and exits the loop when the reply is finished.

void onReplyReceived(Pt::Http::Client& client)
{
if( progress.header() )
{
std::cout << reply.statusCode() << ' '
<< reply.statusText() << std::endl;
}
if( progress.body() )
{
while( reply.body().rdbuf()->in_avail() )
std::cout << reply.body().get();
}
if( progress.finished() )
{
client.loop()->exit();
return;
}
client.beginReceive();
}
Pt::System::MainLoop loop;
Pt::Net::Endpoint ep("www.example.com", 80);
Pt::Http::Client client(loop, ep);
client.request().setUrl("/index.html");
client.replyReceived() += Pt::slot(onReplyReceived);
client.beginReceive();
HTTP user agent.
Definition Client.h:189
Reply & reply()
Returns the received reply.
Request & request()
Returns the request to send.
void beginReceive()
Begin receiving the reply.
System::EventLoop * loop() const
Returns the used event loop.
MessageProgress endReceive()
End receiving the reply.
Signal< Client & > & replyReceived()
Signals that a part of the reply was received.
Progress of an asynchronous HTTP send or receive.
Definition Message.h:337
bool body() const
Returns true if the body was processed.
Definition Message.h:363
bool header() const
Returns true if the header was processed.
Definition Message.h:358
bool finished() const
Returns true if message is complete.
Definition Message.h:373
std::iostream & body()
Returns the body of the message.
Definition Message.h:480
HTTP reply message.
Definition Reply.h:64
const std::string & statusText() const
Returns the HTTP status text.
Definition Reply.h:111
unsigned statusCode() const
Returns the HTTP status code.
Definition Reply.h:107
void setUrl(const std::string &u)
Sets the request URL.
Definition Request.h:99
ConstMethodSlot< R, ClassT, As... > slot(ClassT &object, R(BaseT::*method)(As...) const)
Returns a slot object for the given object/member pair.
Definition ConstMethod.h:172
void run()
Starts the loop.
void exit()
Stops the loop.
Pipelining

Pipelining sends several requests before receiving the matching replies, which needs a persistent connection. Set the keep-alive header on the request, connect requestSent() as well as replyReceived(), and start with beginSend() rather than beginReceive(). The send slot calls endSend(); if that send is not finished, beginSend() continues it, and if it is finished, the next request can be filled and sent. When no further request will be pipelined, beginReceive() starts reading the replies. Identify each reply by order or by application state, because Reply does not store the request URL.

void onRequestSent(Pt::Http::Client& client)
{
Pt::Http::MessageProgress progress = client.endSend();
if( ! progress.finished() )
{
client.beginSend();
return;
}
if( client.request().url() == "/cat.png" )
{
client.request().setUrl("/dog.png");
client.beginSend();
return;
}
client.beginReceive();
}
void beginSend(bool finished=true)
Begins sending the request.
MessageProgress endSend()
End sending the request.
const std::string & url() const
Returns the HTTP request URL.
Definition Request.h:94
Chunked bodies

A chunked request body is sent with beginSend(false) until the last chunk, so the completion flag is false while more body data will be written. endSend() reports whether the current chunk has left the socket, not whether the whole request is complete. When a chunk has finished and more data remains, write it to request().body() and call beginSend(false) again. When no more chunks remain, beginReceive() finishes the request correctly. To pipeline another chunked request after this one, call beginSend(true) so the request body is terminated.

Persistent connections and HTTPS

A keep-alive header on the request asks for a persistent connection, which pipelining needs and which the server may still close. close() ends the connection. Leave it open only while the next request will reuse it; otherwise the server keep-alive timeout may close it before the client is used again. A later send on a closed or timed-out connection opens a new one.

setSecure() assigns a Pt::Ssl::Context so further connections are HTTPS. setPeerName() sets the name expected in the peer certificate. Send and receive are otherwise unchanged. Certificate and handshake details live in the SSL module.

Member Function Documentation

◆ beginSend()

void beginSend ( bool finished = true)

finished is true when this is the last chunk of the body.