MythTV master
httprequest.h
Go to the documentation of this file.
1
2// Program Name: httprequest.h
3// Created : Oct. 21, 2005
4//
5// Purpose : Http Request/Response
6//
7// Copyright (c) 2005 David Blain <dblain@mythtv.org>
8//
9// Licensed under the GPL v2 or later, see LICENSE for details
10//
12
13#ifndef HTTPREQUEST_H_
14#define HTTPREQUEST_H_
15
16#include <utility>
17
18// Qt headers
19#include <QBuffer>
20#include <QDateTime>
21#include <QFile>
22#include <QRegularExpression>
23#include <QTcpSocket>
24#include <QTextStream>
25
26// MythTV headers
29
30#include "upnpexp.h"
31#include "upnputil.h"
33
34static constexpr const char* SOAP_ENVELOPE_BEGIN
35{ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
36 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" \
37 "<s:Body>" };
38static constexpr const char* SOAP_ENVELOPE_END { "</s:Body>\r\n</s:Envelope>" };
39
40
42// Typedefs / Defines
44
46{
48 // HTTP 1.1
52// RequestTypePut = 0x0008,
53// RequestTypeDelete = 0x0010,
54// RequestTypeConnect = 0x0020,
56// RequestTypeTrace = 0x0080, // SECURITY: XST attack risk, shouldn't include cookies or other sensitive info
57 // UPnP
62 // Not a request type
63 RequestTypeResponse = 0x1000
64
65};
66
67enum HttpContentType : std::uint8_t
68{
73};
74
75enum HttpResponseType : std::int8_t
76{
88};
89
91{
92 const char *pszExtension;
93 const char *pszType;
94
95};
96
98
100{
101 public:
102 virtual void ExecutePostProcess( ) = 0;
103 virtual ~IPostProcess() = default;
104};
105
107//
109
111{
112 protected:
113
114 static const char *s_szServerHeaders;
115
116 QRegularExpression m_procReqLineExp {"\\s+"};
117 QRegularExpression m_parseRangeExp {"(\\d|\\-)"};
118
119 public:
120
123
124 QString m_sRawRequest; // e.g. GET /foo/bar.html HTTP/1.1
125
126 QString m_sOriginalUrl; // Raw request URL before % decoded
127 QString m_sRequestUrl; // Raw request URL
128 QString m_sBaseUrl; // Path section of URL, without parameters
129 QString m_sResourceUrl; // Duplicate of Base URL!?
130 QString m_sMethod;
131
135
136 QString m_sPayload;
137
138 QString m_sProtocol;
139 int m_nMajor {0};
140 int m_nMinor {0};
141
142 bool m_bProtected {false};
143 bool m_bEncrypted {false};
144
145 bool m_bSOAPRequest {false};
147
148 // Response
149
151 QString m_sResponseTypeText; // used for ResponseTypeOther
152
153 long m_nResponseStatus {200};
155
156 QString m_sFileName;
157
158 QBuffer m_response;
159
160 IPostProcess *m_pPostProcess {nullptr};
161
164
165 private:
166
167 bool m_bKeepAlive {true};
168 std::chrono::seconds m_nKeepAliveTimeout {0s};
169
170 protected:
171
172 HttpRequestType SetRequestType ( const QString &sType );
173 void SetRequestProtocol ( const QString &sLine );
174 HttpContentType SetContentType ( const QString &sType );
175
176 void ProcessRequestLine ( const QString &sLine );
177 bool ProcessSOAPPayload ( const QString &sSOAPAction );
178 void ExtractMethodFromURL( ); // Service method, not HTTP method
179
180 QString GetResponseStatus ( void ) const;
181 QString GetResponseType ( void ) const;
182 QString GetResponseHeaders ( void );
183
184 bool ParseRange ( QString sRange,
185 long long llSize,
186 long long *pllStart,
187 long long *pllEnd );
188
189 bool ParseKeepAlive ( void );
190
191 void ParseCookies ( void );
192
193 QString BuildResponseHeader ( long long nSize );
194
195 qint64 SendData ( QIODevice *pDevice, qint64 llStart, qint64 llBytes );
196 qint64 SendFile ( QFile &file, qint64 llStart, qint64 llBytes );
197
198 bool IsProtected () const { return m_bProtected; }
199 bool IsEncrypted () const { return m_bEncrypted; }
200 bool Authenticated ();
201
202 QString GetAuthenticationHeader (bool isStale = false);
203 QString CalculateDigestNonce ( const QString &timeStamp) const;
204
205 bool BasicAuthentication ();
206 bool DigestAuthentication ();
207 void AddCORSHeaders ( const QString &sOrigin );
208
209 public:
210
211 HTTPRequest () { m_response.open( QIODevice::ReadWrite ); }
212 virtual ~HTTPRequest () = default;
213
214 bool ParseRequest ();
215
216 void FormatErrorResponse ( bool bServerError,
217 const QString &sFaultString,
218 const QString &sDetails );
219
220 void FormatActionResponse( Serializer *ser );
221 void FormatActionResponse( const NameValues &pArgs );
222 void FormatFileResponse ( const QString &sFileName );
223 void FormatRawResponse ( const QString &sXML );
224
225 qint64 SendResponse ( void );
226 qint64 SendResponseFile( const QString& sFileName );
227
228 void SetResponseHeader ( const QString &sKey,
229 const QString &sValue,
230 bool replace = false );
231
232 void SetCookie ( const QString &sKey, const QString &sValue,
233 const QDateTime &expiryDate,
234 bool secure );
235
236 QString GetRequestHeader ( const QString &sKey, const QString &sDefault );
237
238 bool GetKeepAlive () const { return m_bKeepAlive; }
239
240 Serializer * GetSerializer ();
241
242 QByteArray GetResponsePage ( void ); // Static response e.g. 400, 404, 501
243
244 QString GetRequestProtocol () const;
245 static QString GetResponseProtocol () ;
246
247 QString GetRequestType () const;
248 QString GetLastHeader( const QString &sType ) const;
249
250 static QString GetMimeType ( const QString &sFileExtension );
251 static QStringList GetSupportedMimeTypes ();
252 static QString TestMimeType ( const QString &sFileName );
253 static long GetParameters ( QString sParams, QStringMap &mapParams );
254 static QString Encode ( const QString &sIn );
255 static QString Decode ( const QString &sIn );
256 static QString GetETagHash ( const QByteArray &data );
257
258 void SetKeepAliveTimeout ( std::chrono::seconds nTimeout ) { m_nKeepAliveTimeout = nTimeout; }
259
260 static bool IsUrlProtected ( const QString &sBaseUrl );
261
262 // ------------------------------------------------------------------
263
264 virtual QString ReadLine ( std::chrono::milliseconds msecs ) = 0;
265 virtual qint64 ReadBlock ( char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs = 0ms ) = 0;
266 virtual qint64 WriteBlock ( const char *pData,
267 qint64 nLen ) = 0;
268 virtual QString GetHostName (); // RFC 3875 - The name in the client request
269 virtual QString GetHostAddress () = 0;
270 virtual quint16 GetHostPort () = 0;
271 virtual QString GetPeerAddress () = 0;
272 virtual int getSocketHandle () = 0;
273};
274
276//
278
280{
281 public:
282
283 QTcpSocket *m_pSocket {nullptr};
284
285 public:
286
287 explicit BufferedSocketDeviceRequest( QTcpSocket *pSocket )
288 : m_pSocket(pSocket) {}
289 ~BufferedSocketDeviceRequest() override = default;
290
291 QString ReadLine ( std::chrono::milliseconds msecs ) override; // HTTPRequest
292 qint64 ReadBlock ( char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs = 0ms ) override; // HTTPRequest
293 qint64 WriteBlock ( const char *pData, qint64 nLen ) override; // HTTPRequest
294 QString GetHostAddress () override; // HTTPRequest
295 quint16 GetHostPort () override; // HTTPRequest
296 QString GetPeerAddress () override; // HTTPRequest
297 int getSocketHandle () override // HTTPRequest
298 {return( m_pSocket->socketDescriptor() ); }
299
300};
301
303//
305
307{
308 public:
309 int m_code {-1};
310 QString m_msg;
311
312 explicit HttpException( int nCode = -1, QString sMsg = "")
313 : m_code( nCode ), m_msg (std::move( sMsg ))
314 {}
315
316 // Needed to force a v-table.
317 virtual ~HttpException() = default;
318};
319
321{
322 public:
323
324 QString m_hostName;
325 //int m_port;
326
327 explicit HttpRedirectException( QString sHostName = "",
328 int nCode = -1,
329 const QString &sMsg = "" )
330 : HttpException( nCode, sMsg ), m_hostName(std::move( sHostName ))
331 {}
332
333 ~HttpRedirectException() override = default;
334
335};
336
337#endif
quint16 GetHostPort() override
QString GetPeerAddress() override
QString ReadLine(std::chrono::milliseconds msecs) override
qint64 ReadBlock(char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs=0ms) override
qint64 WriteBlock(const char *pData, qint64 nLen) override
BufferedSocketDeviceRequest(QTcpSocket *pSocket)
Definition: httprequest.h:287
QString GetHostAddress() override
~BufferedSocketDeviceRequest() override=default
int getSocketHandle() override
Definition: httprequest.h:297
bool IsEncrypted() const
Definition: httprequest.h:199
virtual ~HTTPRequest()=default
QString m_sFileName
Definition: httprequest.h:156
virtual QString GetHostAddress()=0
QString m_sPrivateToken
Definition: httprequest.h:162
QString m_sResponseTypeText
Definition: httprequest.h:151
QString m_sNameSpace
Definition: httprequest.h:146
QString m_sMethod
Definition: httprequest.h:130
virtual quint16 GetHostPort()=0
QString m_sRequestUrl
Definition: httprequest.h:127
void SetKeepAliveTimeout(std::chrono::seconds nTimeout)
Definition: httprequest.h:258
virtual int getSocketHandle()=0
bool IsProtected() const
Definition: httprequest.h:198
MythUserSession m_userSession
Definition: httprequest.h:163
QStringMultiMap m_mapHeaders
Definition: httprequest.h:133
virtual QString ReadLine(std::chrono::milliseconds msecs)=0
bool GetKeepAlive() const
Definition: httprequest.h:238
QStringMap m_mapRespHeaders
Definition: httprequest.h:154
QString m_sOriginalUrl
Definition: httprequest.h:126
virtual qint64 ReadBlock(char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs=0ms)=0
virtual qint64 WriteBlock(const char *pData, qint64 nLen)=0
QString m_sResourceUrl
Definition: httprequest.h:129
QString m_sBaseUrl
Definition: httprequest.h:128
QString m_sProtocol
Definition: httprequest.h:138
QStringMap m_mapCookies
Definition: httprequest.h:134
QString m_sRawRequest
Definition: httprequest.h:124
static const char * s_szServerHeaders
Definition: httprequest.h:114
QStringMap m_mapParams
Definition: httprequest.h:132
QString m_sPayload
Definition: httprequest.h:136
QBuffer m_response
Definition: httprequest.h:158
virtual QString GetPeerAddress()=0
virtual ~HttpException()=default
HttpException(int nCode=-1, QString sMsg="")
Definition: httprequest.h:312
QString m_msg
Definition: httprequest.h:310
HttpRedirectException(QString sHostName="", int nCode=-1, const QString &sMsg="")
Definition: httprequest.h:327
~HttpRedirectException() override=default
virtual void ExecutePostProcess()=0
virtual ~IPostProcess()=default
HttpContentType
Definition: httprequest.h:68
@ ContentType_XML
Definition: httprequest.h:71
@ ContentType_JSON
Definition: httprequest.h:72
@ ContentType_Unknown
Definition: httprequest.h:69
@ ContentType_Urlencoded
Definition: httprequest.h:70
static constexpr const char * SOAP_ENVELOPE_END
Definition: httprequest.h:38
HttpResponseType
Definition: httprequest.h:76
@ ResponseTypeSVG
Definition: httprequest.h:84
@ ResponseTypeCSS
Definition: httprequest.h:82
@ ResponseTypeFile
Definition: httprequest.h:85
@ ResponseTypeHTML
Definition: httprequest.h:80
@ ResponseTypeNone
Definition: httprequest.h:77
@ ResponseTypeUnknown
Definition: httprequest.h:78
@ ResponseTypeXML
Definition: httprequest.h:79
@ ResponseTypeJS
Definition: httprequest.h:81
@ ResponseTypeHeader
Definition: httprequest.h:87
@ ResponseTypeText
Definition: httprequest.h:83
@ ResponseTypeOther
Definition: httprequest.h:86
static constexpr const char * SOAP_ENVELOPE_BEGIN
Definition: httprequest.h:35
HttpRequestType
Definition: httprequest.h:46
@ RequestTypeMSearch
Definition: httprequest.h:58
@ RequestTypeSubscribe
Definition: httprequest.h:59
@ RequestTypeNotify
Definition: httprequest.h:61
@ RequestTypePost
Definition: httprequest.h:51
@ RequestTypeOptions
Definition: httprequest.h:55
@ RequestTypeUnsubscribe
Definition: httprequest.h:60
@ RequestTypeGet
Definition: httprequest.h:49
@ RequestTypeHead
Definition: httprequest.h:50
@ RequestTypeResponse
Definition: httprequest.h:63
@ RequestTypeUnknown
Definition: httprequest.h:47
unsigned short uint16_t
Definition: iso6937tables.h:3
STL namespace.
const char * pszType
Definition: httprequest.h:93
const char * pszExtension
Definition: httprequest.h:92
#define UPNP_PUBLIC
Definition: upnpexp.h:9
QMultiMap< QString, QString > QStringMultiMap
Definition: upnputil.h:29
QMap< QString, QString > QStringMap
Definition: upnputil.h:28