| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | /**
 | 
					
						
							|  |  |  |   @file | 
					
						
							|  |  |  |   @author Stefan Frings | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifndef HTTPREQUEST_H
 | 
					
						
							|  |  |  | #define HTTPREQUEST_H
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <QByteArray>
 | 
					
						
							|  |  |  | #include <QHostAddress>
 | 
					
						
							|  |  |  | #include <QTcpSocket>
 | 
					
						
							|  |  |  | #include <QMap>
 | 
					
						
							|  |  |  | #include <QMultiMap>
 | 
					
						
							|  |  |  | #include <QSettings>
 | 
					
						
							|  |  |  | #include <QTemporaryFile>
 | 
					
						
							|  |  |  | #include <QUuid>
 | 
					
						
							|  |  |  | #include "httpglobal.h"
 | 
					
						
							| 
									
										
										
										
											2017-11-13 13:46:02 +01:00
										 |  |  | #include "httplistenersettings.h"
 | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-20 13:49:21 +01:00
										 |  |  | #include "export.h"
 | 
					
						
							| 
									
										
										
										
											2018-03-03 20:23:38 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-11 09:32:15 +01:00
										 |  |  | namespace qtwebapp { | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | /**
 | 
					
						
							|  |  |  |   This object represents a single HTTP request. It reads the request | 
					
						
							|  |  |  |   from a TCP socket and provides getters for the individual parts | 
					
						
							|  |  |  |   of the request. | 
					
						
							|  |  |  |   <p> | 
					
						
							|  |  |  |   The follwing config settings are required: | 
					
						
							|  |  |  |   <code><pre> | 
					
						
							|  |  |  |   maxRequestSize=16000 | 
					
						
							|  |  |  |   maxMultiPartSize=1000000 | 
					
						
							|  |  |  |   </pre></code> | 
					
						
							|  |  |  |   <p> | 
					
						
							|  |  |  |   MaxRequestSize is the maximum size of a HTTP request. In case of | 
					
						
							|  |  |  |   multipart/form-data requests (also known as file-upload), the maximum | 
					
						
							|  |  |  |   size of the body must not exceed maxMultiPartSize. | 
					
						
							|  |  |  |   The body is always a little larger than the file itself. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-03 20:23:38 +01:00
										 |  |  | class HTTPSERVER_API HttpRequest { | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  |     Q_DISABLE_COPY(HttpRequest) | 
					
						
							|  |  |  |     friend class HttpSessionStore; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Values for getStatus() */ | 
					
						
							|  |  |  |     enum RequestStatus {waitForRequest, waitForHeader, waitForBody, complete, abort}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Constructor. | 
					
						
							|  |  |  |       @param settings Configuration settings | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     HttpRequest(QSettings* settings); | 
					
						
							| 
									
										
										
										
											2017-11-13 13:46:02 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Constructor. | 
					
						
							|  |  |  |       @param settings Configuration settings as a structure | 
					
						
							|  |  |  |     */ | 
					
						
							| 
									
										
										
										
											2017-11-18 10:15:29 +01:00
										 |  |  |     HttpRequest(const HttpListenerSettings* settings); | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Destructor. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     virtual ~HttpRequest(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Read the HTTP request from a socket. | 
					
						
							|  |  |  |       This method is called by the connection handler repeatedly | 
					
						
							|  |  |  |       until the status is RequestStatus::complete or RequestStatus::abort. | 
					
						
							|  |  |  |       @param socket Source of the data | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     void readFromSocket(QTcpSocket* socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the status of this reqeust. | 
					
						
							|  |  |  |       @see RequestStatus | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     RequestStatus getStatus() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get the method of the HTTP request  (e.g. "GET") */ | 
					
						
							|  |  |  |     QByteArray getMethod() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get the decoded path of the HTPP request (e.g. "/index.html") */ | 
					
						
							|  |  |  |     QByteArray getPath() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get the raw path of the HTTP request (e.g. "/file%20with%20spaces.html") */ | 
					
						
							|  |  |  |     const QByteArray& getRawPath() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get the version of the HTPP request (e.g. "HTTP/1.1") */ | 
					
						
							|  |  |  |     QByteArray getVersion() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the value of a HTTP request header. | 
					
						
							|  |  |  |       @param name Name of the header, not case-senitive. | 
					
						
							|  |  |  |       @return If the header occurs multiple times, only the last | 
					
						
							|  |  |  |       one is returned. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QByteArray getHeader(const QByteArray& name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the values of a HTTP request header. | 
					
						
							|  |  |  |       @param name Name of the header, not case-senitive. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QList<QByteArray> getHeaders(const QByteArray& name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |      * Get all HTTP request headers. Note that the header names | 
					
						
							|  |  |  |      * are returned in lower-case. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     QMultiMap<QByteArray,QByteArray> getHeaderMap() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the value of a HTTP request parameter. | 
					
						
							|  |  |  |       @param name Name of the parameter, case-sensitive. | 
					
						
							|  |  |  |       @return If the parameter occurs multiple times, only the last | 
					
						
							|  |  |  |       one is returned. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QByteArray getParameter(const QByteArray& name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the values of a HTTP request parameter. | 
					
						
							|  |  |  |       @param name Name of the parameter, case-sensitive. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QList<QByteArray> getParameters(const QByteArray& name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get all HTTP request parameters. */ | 
					
						
							|  |  |  |     QMultiMap<QByteArray,QByteArray> getParameterMap() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get the HTTP request body.  */ | 
					
						
							|  |  |  |     QByteArray getBody() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Decode an URL parameter. | 
					
						
							|  |  |  |       E.g. replace "%23" by '#' and replace '+' by ' '. | 
					
						
							|  |  |  |       @param source The url encoded strings | 
					
						
							|  |  |  |       @see QUrl::toPercentEncoding for the reverse direction | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     static QByteArray urlDecode(const QByteArray source); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get an uploaded file. The file is already open. It will | 
					
						
							|  |  |  |       be closed and deleted by the destructor of this HttpRequest | 
					
						
							|  |  |  |       object (after processing the request). | 
					
						
							|  |  |  |       <p> | 
					
						
							|  |  |  |       For uploaded files, the method getParameters() returns | 
					
						
							|  |  |  |       the original fileName as provided by the calling web browser. | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QTemporaryFile* getUploadedFile(const QByteArray fieldName) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the value of a cookie. | 
					
						
							|  |  |  |       @param name Name of the cookie | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     QByteArray getCookie(const QByteArray& name) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Get all cookies. */ | 
					
						
							|  |  |  |     QMap<QByteArray,QByteArray>& getCookieMap(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Get the address of the connected client. | 
					
						
							|  |  |  |       Note that multiple clients may have the same IP address, if they | 
					
						
							|  |  |  |       share an internet connection (which is very common). | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     QHostAddress getPeerAddress() const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Request headers */ | 
					
						
							|  |  |  |     QMultiMap<QByteArray,QByteArray> headers; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Parameters of the request */ | 
					
						
							|  |  |  |     QMultiMap<QByteArray,QByteArray> parameters; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Uploaded files of the request, key is the field name. */ | 
					
						
							|  |  |  |     QMap<QByteArray,QTemporaryFile*> uploadedFiles; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Received cookies */ | 
					
						
							|  |  |  |     QMap<QByteArray,QByteArray> cookies; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Storage for raw body data */ | 
					
						
							|  |  |  |     QByteArray bodyData; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Request method */ | 
					
						
							|  |  |  |     QByteArray method; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Request path (in raw encoded format) */ | 
					
						
							|  |  |  |     QByteArray path; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Request protocol version */ | 
					
						
							|  |  |  |     QByteArray version; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /**
 | 
					
						
							|  |  |  |       Status of this request. For the state engine. | 
					
						
							|  |  |  |       @see RequestStatus | 
					
						
							|  |  |  |     */ | 
					
						
							|  |  |  |     RequestStatus status; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Address of the connected peer. */ | 
					
						
							|  |  |  |     QHostAddress peerAddress; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Maximum size of requests in bytes. */ | 
					
						
							|  |  |  |     int maxSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Maximum allowed size of multipart forms in bytes. */ | 
					
						
							|  |  |  |     int maxMultiPartSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Current size */ | 
					
						
							|  |  |  |     int currentSize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Expected size of body */ | 
					
						
							|  |  |  |     int expectedBodySize; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Name of the current header, or empty if no header is being processed */ | 
					
						
							|  |  |  |     QByteArray currentHeader; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Boundary of multipart/form-data body. Empty if there is no such header */ | 
					
						
							|  |  |  |     QByteArray boundary; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Temp file, that is used to store the multipart/form-data body */ | 
					
						
							|  |  |  |     QTemporaryFile* tempFile; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Parse the multipart body, that has been stored in the temp file. */ | 
					
						
							|  |  |  |     void parseMultiPartFile(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Sub-procedure of readFromSocket(), read the first line of a request. */ | 
					
						
							|  |  |  |     void readRequest(QTcpSocket* socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Sub-procedure of readFromSocket(), read header lines. */ | 
					
						
							|  |  |  |     void readHeader(QTcpSocket* socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Sub-procedure of readFromSocket(), read the request body. */ | 
					
						
							|  |  |  |     void readBody(QTcpSocket* socket); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Sub-procedure of readFromSocket(), extract and decode request parameters. */ | 
					
						
							|  |  |  |     void decodeRequestParams(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Sub-procedure of readFromSocket(), extract cookies from headers */ | 
					
						
							|  |  |  |     void extractCookies(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** Buffer for collecting characters of request and header lines */ | 
					
						
							|  |  |  |     QByteArray lineBuffer; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-17 08:52:15 +01:00
										 |  |  |     /** Settings flag */ | 
					
						
							|  |  |  |     bool useQtSettings; | 
					
						
							| 
									
										
										
										
											2017-08-23 18:47:07 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif // HTTPREQUEST_H
 |