classPiiHttpDevice
#include <PiiHttpDevice.h>
An I/O device for HTTP/1.1 communication.
Inherits QIODevice, PiiStreamFilter
Description
This class can be used to send and parse HTTP request and replies. It works as an ordinary I/O device, but ensures that the HTTP protocol format is retained.
The class automates the handling of HTTP headers as much as
possible. If you request information that is not available without
reading the request header, PiiHttpDevice will read
the header automatically. It also builds the request or response
header, and has reasonable defaults for most header fields. The
header will be automatically sent if data is written to the device.
PiiHttpDevice supports output filtering. All data
written to the client/server can be passed through an unlimited
number of filters which may buffer the data. If no filters are
installed, data will be written directly to the low-level socket.
Headers will be sent just before the first byte of the message body
is going to be written to the client. It is not possible to change
the headers afterwards.
In Server mode, PiiHttpDevice is
typically used in the handleRequest() function of
PiiHttpProtocol::UriHandler:
void MyHandler::handleRequest(const QString& uri, PiiHttpDevice* h, PiiProgressController* controller) { if (h->requestMethod() != "GET") { h->setStatus(PiiHttpProtocol::MethodNotAllowedStatus); return; // do not send anything } h->startOutputFiltering(new PiiStreamBuffer); h->setHeader("Content-Type", "text/html"); h->print("<html><body>You hit a handler at " + uri + "</body></html> "); }
Using a PiiStreamBuffer as an output filter will usually increase performance. The effect is that writes to the device will be stored into memory until the buffer is flushed. PiiHttpProtocol can also utilizes the buffer by automatically setting the Content-Length header.
In Client mode, the I/O device must be created first.
Note that PiiHttpDevice assumes that the I/O device can always read
input data. It doesn't implement any waiting mechanisms for the
cases where data is not immediately available. This makes
communication devices such as QTcpSocket unsuitable as such. Use
PiiWaitingIODevice instead. PiiNetworkClient can be
used to easily create a suitable I/O device:
PiiNetworkClient client("tcp://127.0.0.1:80"); PiiHttpDevice dev(client.openConnection(), PiiHttpDevice::Client); dev.setRequest("GET", "/"); dev.setHeader("Host", "localhost"); dev.finish(); // Read response header and ignore the response body. dev.readHeader(); dev.discardBody();
Public types
|
enum
|
{ KeepAliveConnection, CloseConnection }
Connection types, specified by the |
|
enum
|
{ TextFormat, BinaryFormat }
Encoding formats. |
|
enum
|
{ Client, Server }
Communication modes. |
Constructors and destructor
|
Initialize a HTTP device with the given low-level device. |
|
|
( )
Destroy the HTTP device. |
Public member functions
|
void
|
Adds a query value to the request URI. |
|
qint64
|
( )
Returns the number of bytes in the message body. |
|
qint64
|
( )
|
|
( )
Returns the connection type. |
|
|
int
|
( )
Returns the length of the request/response body. |
|
( )
|
|
|
|
|
|
Decodes data and returns its value as a QVariant. |
|
|
( )
Returns the communication device. |
|
|
void
|
( )
Reads and forgets the whole message body. |
|
Encodes msg to a byte array using the current encoding. |
|
|
Encodes a QVariant to a QByteArray. |
|
|
void
|
Pops an output filter from the filter stack. |
|
virtual qint64
|
(
Writes at most |
|
void
|
( )
Ensures that headers are sent to the other end of the connections, flushes all output filters and flushes the output device. |
|
virtual qint64
|
( )
Flushes all buffered data to the output filter. |
|
( )
Returns the names of form fields in the order they appear in the POST message body. |
|
|
Returns a request parameter from an
|
|
|
QVariantMap
|
( )
Returns all form-encoded values in the message body as a map. |
|
bool
|
( )
Returns |
|
qint64
|
( )
Returns the number of bytes in the parsed request/response header. |
|
bool
|
( )
See if request/response header have been successfully read. |
|
qint64
|
( )
Returns the current header size limit. |
|
( )
Returns the client-supplied name of the host, if there is one. |
|
|
bool
|
( )
Returns |
|
bool
|
( )
Returns |
|
bool
|
( )
|
|
bool
|
( )
Returns |
|
qint64
|
( )
Returns the current request size limit. |
|
virtual PiiStreamFilter *
|
( )
Returns the currently active (topmost) output filter. |
|
qint64
|
Prints text to the device. |
|
( )
Returns the names of all query items as a list. |
|
|
( )
Returns the query string part of the request URI, if any. |
|
|
Returns a query value from the request URI. |
|
|
QVariantMap
|
( )
Returns all query values as a map of key-value pairs. |
|
( )
Reads the whole message body and returns it as a byte array. |
|
|
bool
|
( )
Reads request/response header. |
|
void
|
Removes the header field(s) with name. |
|
void
|
Remove a query value from the request URI. |
|
void
|
Remove all query values from the request uri. |
|
( )
Returns the full request header. |
|
|
( )
Returns the request method. |
|
|
Returns the path part of the request URI. |
|
|
( )
Returns the request URI. |
|
|
Returns a request parameter from either the request URI (GET parameters) or the request body (POST parameters). |
|
|
QVariantMap
|
( )
Returns all request parameters (either GET parameters in the URI or form values in the message body) as a map. |
|
( )
Returns the full response header. |
|
|
void
|
( )
Restarts the request/reply cycle. |
|
bool
|
( )
Sends request/response headers. |
|
void
|
|
|
void
|
Set the communication device. |
|
void
|
Sets a HTTP request/response header field. |
|
void
|
(
Set the maximum number of bytes an HTTP request header is allowed to contain. |
|
void
|
(
Set the maximum number of bytes the entire HTTP message (including the header and the body) is allowed to contain. |
|
void
|
Set the request method to method and request URI to uri. |
|
void
|
Set a value in the request header. |
|
void
|
Set a value in the response header. |
|
void
|
(
Set the HTTP status code. |
|
void
|
Puts an output filter on the filter stack. |
|
int
|
( )
Returns the HTTP response status code. |
Protected member functions
|
qint64
|
(
|
|
qint64
|
(
|
Enumeration details
-
enum ConnectionType
Connection types, specified by the
Connectionrequest header.-
KeepAliveConnection- the default for HTTP/1.1. The connection will not be closed after a request. -
CloseConnection- the connection will be closed after request. This happens when the client sends the "Connection: close" request header.
-
-
enum EncodingFormat
Encoding formats.
-
TextFormat- data is encoded as UTF-8 text. See PiiTextOutputArchive and PiiTextInputArchive. -
BinaryFormat- data is encoded in a raw binary format. See PiiBinaryOutputArchive and PiiBinaryInputArchive.
-
-
enum Mode
Communication modes.
-
Client- the device is used at the client side -
Server- the device is used at the server side
-
Function details
-
PiiHttpDevice
Initialize a HTTP device with the given low-level device.
Parameters
- device
-
the communication device. Typically, device is a PiiWaitingIODevice. The pointer must remain valid during the lifetime of the HTTP device.
- mode
-
communication mode
-
~PiiHttpDevice
()Destroy the HTTP device.
This will finish all unfinished output filters.
-
Adds a query value to the request URI.
This function can be used in
Clientmode to automatically encode values in the query.dev.addQueryValue("v1", 1); dev.addQueryValue("v2", "Hello"); dev.addQueryValue("v2", 3.14); // dev.queryString() == v1=1&v2=%22hello%22&v2=3.14
Parameters
- name
-
the name of the query value. If the name is an empty string, the name and the equal sign will be omitted.
- value
-
the value, will be automatically encoded (see encode()). Multiple items with the same name may exists.
-
qint64 bodyLength
()Returns the number of bytes in the message body.
This value is known only if the header contains a Content-Length field. Otherwise -1 will be returned.
-
qint64 bytesAvailable
() -
ConnectionType connectionType
()Returns the connection type.
If the client has the "Connection" header set to "close", or if the client disconnects, this function returns
CloseConnection. Otherwise it returnsKeepAliveConnection. -
int contentLength
()Returns the length of the request/response body.
-
PiiProgressController * controller
() -
This is an overloaded member function, provided for convenience. It differs from the above function only in what argument(s) it accepts.
-
QVariant decodeVariant
Decodes data and returns its value as a QVariant.
The following conversions are tried, in preference order:
-
If data begins with a magic string that identifies an archive (e.g. "Into Txt" or "Into Bin"), it is assumed to contain a serialized QVariant. The variant will be deserialized.
-
If data can be converted to an
int, anintwill be returned. -
If data can be converted to a
double, adoublewill be returned. -
If data is either "true" or "false", the corresponding boolean value will be returned.
-
Otherwise, a QString will be returned. If the value is enclosed in double quotes, they will be removed.
In some occasions, it may be necessary to pass "true", "false", "1.23" or "Into Bin" as strings. To prevent automatic conversion, enclose the value in double quotes.
Returns
the decoded value. If the decoding fails, an invalid variant will be returned.
-
-
PiiSocketDevice device
()Returns the communication device.
Note that writing to the device directly may break the HTTP protocol. Use the underlying device at your own risk.
-
void discardBody
()Reads and forgets the whole message body.
If you call this function yourself, a POST encoded message body can no longer be automatically parsed, and functions such as formItems() and formValues() return empty values.
-
QByteArray encode
Encodes msg to a byte array using the current encoding.
If the
Content-Encodingheader has not been set, UTF-8 will be used. -
QByteArray encode
Encodes a QVariant to a QByteArray.
If the variant represents a number, it will be converted to decimal representation. Boolean values will be converted to "true" and "false" (without the double quotes). QStrings will be enclosed in double quotes. All other types will be serialized.
-
void endOutputFiltering
Pops an output filter from the filter stack.
This function will collapse the filter stack until it finds filter and tell each filter to finish its job. The removed filters will be deleted. The next filter below filter on the stack (if any) will be activated.
If the last filter is removed, and the filter has buffered data, this function tries to determine the number of bytes to be sent to the client and set the Content-Length header accordingly. If a single byte has been sent previously, it is too late to send the header. If you want to avoid sending the automatic header, call filter->flushFilter() to flush buffered data before endOutputFiltering().
Parameters
- filter
-
the filter until which all filters will be finished. If filter is 0, only the topmost filter will be removed.
-
virtual qint64 filterData
(- const char * data
- qint64 maxSize
[virtual]Writes at most
maxSizebytes ofdatato this output filter.Returns the number of bytes actually written.
Reimplemented from PiiStreamFilter.
-
void finish
()Ensures that headers are sent to the other end of the connections, flushes all output filters and flushes the output device.
On the client side, this function must be called before reading a response. The final form of the request/response headers is available only after finish() is done. For example, connectionType() may be
CloseConnectioneven if the client did not request it.Calling finish() multiple times has no effect. If you intend to use the same PiiHttpDevice for successive requests, you need to call either restart() after handling the request. The setRequest() (on the client side) and readHeader() (on the server side) functions automatically restart the request.
-
virtual qint64 flushFilter
()[virtual]Flushes all buffered data to the output filter.
Returns the number of bytes written. The default implementation returns 0.
Reimplemented from PiiStreamFilter.
-
QStringList formItems
()Returns the names of form fields in the order they appear in the POST message body.
If the message body has not been read, this function does so, even though it is
const.See also
-
Returns a request parameter from an
application/x-www-form-urlencodedPOST body.If the body is not such type, or the value called name does not exist, an invalid variant will be returned. Note that this function will only work if you haven't already read the message body yourself.
If the message body has not been read, this function does so, even though it is
const.See also
-
QVariantMap formValues
()Returns all form-encoded values in the message body as a map.
Parameter values are automatically decoded (see decodeVariant()).
If the message body has not been read, this function does so, even though it is
const. -
bool hasQuery
()Returns
trueif the request URI contains a query string, andfalseotherwise. -
qint64 headerLength
()Returns the number of bytes in the parsed request/response header.
If the header has not been read, -1 will be returned.
-
bool headerRead
()See if request/response header have been successfully read.
Returns
true, if request headers have been read,falseotherwise. -
qint64 headerSizeLimit
()Returns the current header size limit.
-
QString host
()Returns the client-supplied name of the host, if there is one.
-
bool isBodyRead
()Returns
trueif at least one byte of the message body has been read andfalseotherwise. -
bool isReadable
()Returns
trueif the low-level socket device is still connected,falseotherwise. -
bool isSequential
() -
bool isWritable
()Returns
trueif the low-level socket device is still connected,falseotherwise. -
qint64 messageSizeLimit
()Returns the current request size limit.
-
Returns the currently active (topmost) output filter.
Returns
the filter that first filters data written to the device, or 0 if no filters have been added.
Reimplemented from PiiStreamFilter.
-
qint64 print
Prints text to the device.
This function is equivalent to QIODevice::write(), but it converts the unicode input text using the encoding style defined with the
Content-Encodingheader. If no encoding has been set, UTF-8 will be used. -
QStringList queryItems
()Returns the names of all query items as a list.
This function returns the "raw" query names in the order they appear in the request URI. The list may contain duplicate entries.
-
QString queryString
()Returns the query string part of the request URI, if any.
The query string contains URI-encoded query values. The question mark at the beginning of the query string will not be returned.
// request URI: /foo/bar/baz?a=2 QString str = h->queryString(); // str = "a=2"
Returns
the query string. May be empty.
-
Returns a query value from the request URI.
This function returns the variable called name in the encoded request string. If there are multiple values associated with the same key, a list of values will be returned. Values are automatically decoded (see decodeVariant()).
// request URI: /path/?var1=a&var2=b&var2=c QString a = h->queryValue("var1").toString(); // a = "a" QVariantList bc = h->queryValue("var2").toList(); // bc = ("b", "c")
-
QVariantMap queryValues
()Returns all query values as a map of key-value pairs.
Parameter values are automatically decoded (see decodeVariant()).
-
QByteArray readBody
()Reads the whole message body and returns it as a byte array.
Note that the function returns data even if the whole body could not be read.
If you call this function yourself, a POST encoded message body can no longer be automatically parsed, and functions such as formItems() and formValues() return empty values.
-
bool readHeader
()Reads request/response header.
This function checks that the header has not been read and calls the protected #decodeHeader() function if needed.
-
void removeHeader
Removes the header field(s) with name.
If the device is in
Clientmode, this function modifies the request header. InServermode, it modifies the response header. -
void removeQueryValue
Remove a query value from the request URI.
-
void removeQueryValues
()Remove all query values from the request uri.
-
QHttpRequestHeader requestHeader
()Returns the full request header.
-
QString requestMethod
()Returns the request method.
Typically, the answer is either "GET" or "POST", but HTTP extensions may use arbitrary request methods.
-
Returns the path part of the request URI.
// request URI: /foo/bar/baz?a=2 QString str = h->requestPath("/foo/"); // str = "bar/baz"
Parameters
- basePath
-
strip this path from the beginning of the path. This is useful if you want to find the relative path of a URI handler.
-
QString requestUri
()Returns the request URI.
The returned string contains the full path the client sent with the request, including possible encoded request parameters.
-
Returns a request parameter from either the request URI (GET parameters) or the request body (POST parameters).
If the variable is found in both, the request URI takes precedence.
-
QVariantMap requestValues
()Returns all request parameters (either GET parameters in the URI or form values in the message body) as a map.
If the same variable is found in both, the request URI takes precedence. Parameter values are automatically decoded (see decodeVariant()).
-
QHttpResponseHeader responseHeader
()Returns the full response header.
-
void restart
()Restarts the request/reply cycle.
This function needs to be called after each cycle if the same device is used again. On the client side, each setRequest() call automatically restarts the cycle. On the server side, each readHeader() call does the same.
-
bool sendHeader
()Sends request/response headers.
This function checks that the headers have not been sent and calls the protected #encodeHeader() function if needed.
-
void setController
-
void setDevice
Set the communication device.
Usually, a new PiiHttpDevice is created whenever a new communication device is needed. This function is useful in
Clientmode if you need to reopen a connection to a server but still want to retain old configuration such as request parameters or cookies. Setting device to null is not allowed.Exceptions
- PiiInvalidArgumentException&
-
if device is null.
-
Sets a HTTP request/response header field.
If the device is in
Clientmode, this function modifies the request header. InServermode, it modifies the response header.// Set content type h->setHeader("Content-Type", "text/xml"); // Set content length h->setHeader("Content-Length", 31416); // Redirect the client to another address h->setHeader("Location", "http://www.intopii.fi/"); // Note: it is not a good idea to send data to the client after // redirecting it. // Set authentication style h->setHeader("WWW-Authenticate" "Negotiate"); // Add another header with the same name h->setHeader("WWW-Authenticate", "NTLM", false);
Setting the
Content-Encodingheader will automatically change the output text codec. See QTextCodec for supported encodings.Parameters
- name
-
the name of the header field, such as "Location".
- value
-
the value of the field
- replace
-
indicates whether the header should replace a previous similar header, or add a second header of the same type.
-
void setHeaderSizeLimit
(- qint64 headerSizeLimit
Set the maximum number of bytes an HTTP request header is allowed to contain.
This value is used to prevent exhaustive memory allocation. The default value is 4096.
-
void setMessageSizeLimit
(- qint64 messageSizeLimit
Set the maximum number of bytes the entire HTTP message (including the header and the body) is allowed to contain.
This value is used to prevent exhaustive memory allocation. The default value is 1M.
-
Set the request method to method and request URI to uri.
The uri will not be parsed; you can give anything (including invalid data) as the request uri. Calling this function will clear all existing parameters added with addQueryValue().
-
Set a value in the request header.
Parameters
- name
- value
-
the value of the field
- replace
-
indicates whether the header should replace a previous similar header, or add a second header of the same type.
-
Set a value in the response header.
The function will automatically change the status code (setStatus()) if needed. For example, setting the
Locationheader changes the status code automatically to 302 (redirect), unless the status code is already in the 3xx series.Parameters
- name
- value
-
the value of the field
- replace
-
indicates whether the header should replace a previous similar header, or add a second header of the same type.
-
void setStatus
(- int code
Set the HTTP status code.
The default value is 200 (OK).
-
void startOutputFiltering
Puts an output filter on the filter stack.
All subsequent writes to the device will go through filter first.
You may call startOutputFiltering() many times. Just make sure that you call endOutputFiltering() the same number of times. If multiple output filters are active, output will be filtered sequentially through each of them.
// Buffer all data into memory until finish() or endOutputFiltering() is called. dev.startOutputFiltering(new PiiStreamBuffer);
Parameters
- filter
-
the output filter. PiiHttpDevice takes the ownership of the pointer.
-
int status
()Returns the HTTP response status code.
-
qint64 readData
(- char * data
- qint64 maxSize
[protected] -
qint64 writeData
(- const char * data
- qint64 maxSize
[protected]
Add a note
Not a single note added yet. Be the first, add yours.