Using the HTTP Classes
This section describes how to connect to a server, create a request, send a request, retrieve a reply, and interpret a reply.
Connecting to the Server
Example 4 connects an application to a server using an
RWHttpClient. It initializes the
RWHttpClient object and specifies the HTTP server to connect to.
NOTE >> Servers and files shown in the code might not exist and are included as examples only.
Example 4 – Connecting to the server
RWHttpClient client = RWHttpSocketClient::make(); //1
try {
client.connect("www.roguewave.com"); //2
} catch (const RWxmsg& msg) {
// error...
}
RWHttpClient defaults to port 80 on the server specified. If you want to connect to the HTTP server on an alternate port, you can pass an optional argument to the connect method, as shown below.
client.connect("www.roguewave.com", 8001);
This invocation connects to the HTTP server running on port 8001 of the www.roguewave.com server.
RWHttpAgent does not have an explicit connection mechanism because connections to HTTP servers are established automatically as they are needed to fill requests. All
RWHttpAgent instances are automatically valid on construction.
RWHttpAgent agent;
Creating a Request
The
RWHttpClient classes encapsulate HTTP requests within the helper class
RWHttpRequest. All HTTP requests must specify:
• The method to execute on the server
• The path to the document that the method will act on
• The version of the HTTP protocol that the request conforms to
• Any HTTP headers that are required by the type of request
Example 5 constructs an
HTTP GET request to the root document of the HTTP server. The request does not include any user-defined HTTP headers, however an
HTTP Host header is automatically added to the request before sending the request to the server. For more information about adding additional HTTP headers or modifying the default headers, see
“Adding and Removing Headers.” Example 5 – Creating a request
RWHttpRequest request(RWHttpRequest::Get, "/");
RWHttpRequest objects default to HTTP/1.1 formatted request, however the major and minor versions of the request can be set through member functions:
request.setVersion(1, 0);
This example converts the
RWHttpRequest into an HTTP/1.0 request with all of the restrictions associated with HTTP/1.0 requests. Unless a server specifically cannot accept HTTP/1.1 formatted requests, use the default.
Sending a Request
After an
RWHttpClient is connected to an HTTP server and an
RWHttpRequest object is constructed, your application can submit the request to the client so that it can be sent to the server.
Example 6 – Submitting a request to the client
try {
client.submit(request);
} catch(const RWxmsg& msg) {
// error...
}
The submit method evaluates the request object to ensure that it is complete. If it is, it is sent to the associated HTTP server. Based on the client and request constructed before, the submit method in
Example 6 sends the following request to the server:
GET / HTTP/1.1
Host: www.roguewave.com
The
RWHttpAgent class uses member functions in order to submit requests to a server. Because
RWHttpAgents are not explicitly connected to any servers, additional information must be passed to the request so that it can determine where the request must be sent. An
RWURL object encapsulates the information required by the
RWHttpAgent class.
Example 7 – Using RWURL
RWURL url("http://www.roguewave.com/");
RWTIOUResult<RWHttpReply> replyIOU = agent.executeGet(url);
All
RWHttpAgent execute methods return an
RWTIOUResult that contains the response from the server after the request has completed. For more information on the
RWTIOUResult class, see the following:
• SourcePro API Reference Guide
Retrieving a Reply
After an HTTP request is submitted, the server processes it and sends a response back to the client. Your application can retrieve the reply from the
RWHttpClient object using the
getReply() method:
RWHttpReply reply = client.getReply();
The
getReply() method returns an
RWHttpReply object. The
getReply() method blocks until the complete reply from the server is read.
RWHttpAgent combines the request and retrieval steps of
RWHttpClient into a single request as mentioned in
“Sending a Request.” Because the
RWHttpAgent request returns immediately with an
RWTIOUResult object, your application must ensure that the request is complete before attempting to access the results of the request:
RWHttpReply reply = replyIOU.redeem();
The
redeem() method of an
RWTIOUResult object blocks until the request is complete and the result is fully retrieved from the server. After the reply object is redeemed, the resulting reply is no different than one retrieved through an
RWHttpClient request.
Interpreting the Reply
An
RWHttpReply object has several member functions that access the information returned from the HTTP server. These functions can retrieve:
• Headers
• Status code and status message
• Version of the HTTP response
• Body of the message
Example 8 shows how to check the status of the reply, and how to retrieve the body of the message. It checks the status of the reply to ensure that the request is successful.
Example 8 – Checking the status and retrieving the body of the message
if(reply.is2XX()) {
cout << reply.getBody() << endl;
}
NOTE >> A status code in the 200 range usually indicates success. For more information about status codes, see RFC 2616, which defines the HTTP protocol.
If the reply is successful, the body of the message is retrieved as an
RWCString, and the message body is streamed to
stdout.
Bringing it All Together
Example 9 is a complete document request using an
RWHttpClient.
Example 9 – Requesting a document using an RWHttpClient
RWHttpClient client; // 1
RWHttpRequest request(RWHttpRequest::Get, "/"); // 2
client = RWHttpSocketClient::make(); // 3
try {
client.connect("www.roguewave.com"); // 4
client.submit(request); // 5
RWHttpReply reply = client.getReply(); // 6
cout << reply.asString() << endl; // 7
if(reply.is2XX()) { // 8
cout << reply.getBody() << endl; // 9
}
} catch(const RWxmsg& msg) { // 10
// error...
}
Example 10 shows the same request to an HTTP server using
RWHttpAgent. It is a simple HTTP request-response interaction using only a single HTTP method (
GET).
Example 10 – Requesting a document using an RWHttpAgent
RWHttpAgent agent; // 1
RWURL url("http://www.roguewave.com/"); // 2
RWTIOUResult<RWHttpReply> replyIOU; // 3
try {
replyIOU = agent.executeGet(url); // 4
RWHttpReply reply = replyIOU.redeem(); // 5
cout << reply.asString() << endl;
if (reply.is2XX()) {
cout << reply.getBody() << endl;
}
} catch(const RWxmsg& msg) {
// error...
}
NOTE >> For more advanced examples, see the examples in the next section and the sample programs distributed with the HTTP package. Sample programs are located in the examples directory created for your installation. For more information, see the books Installing and Building Your SourcePro Products and Building Your Applications.