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 "upnpresultcode.h"
32#include "upnputil.h"
34
35static constexpr const char* SOAP_ENVELOPE_BEGIN
36{ "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " \
37 "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">" \
38 "<s:Body>" };
39static constexpr const char* SOAP_ENVELOPE_END { "</s:Body>\r\n</s:Envelope>" };
40
41
43// Typedefs / Defines
45
47{
49 // HTTP 1.1
53// RequestTypePut = 0x0008,
54// RequestTypeDelete = 0x0010,
55// RequestTypeConnect = 0x0020,
57// RequestTypeTrace = 0x0080, // SECURITY: XST attack risk, shouldn't include cookies or other sensitive info
58 // UPnP
63 // Not a request type
64 RequestTypeResponse = 0x1000
65
66};
67
68enum HttpContentType : std::uint8_t
69{
74};
75
76enum HttpResponseType : std::int8_t
77{
89};
90
92{
93 const char *pszExtension;
94 const char *pszType;
95
96};
97
99
101{
102 public:
103 virtual void ExecutePostProcess( ) = 0;
104 virtual ~IPostProcess() = default;
105};
106
108//
110
112{
113 protected:
114
115 static const char *s_szServerHeaders;
116
117 QRegularExpression m_procReqLineExp {"\\s+"};
118 QRegularExpression m_parseRangeExp {"(\\d|\\-)"};
119
120 public:
121
124
125 QString m_sRawRequest; // e.g. GET /foo/bar.html HTTP/1.1
126
127 QString m_sOriginalUrl; // Raw request URL before % decoded
128 QString m_sRequestUrl; // Raw request URL
129 QString m_sBaseUrl; // Path section of URL, without parameters
130 QString m_sResourceUrl; // Duplicate of Base URL!?
131 QString m_sMethod;
132
136
137 QString m_sPayload;
138
139 QString m_sProtocol;
140 int m_nMajor {0};
141 int m_nMinor {0};
142
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 IsEncrypted () const { return m_bEncrypted; }
199
200 void AddCORSHeaders ( const QString &sOrigin );
201
202 public:
203
204 HTTPRequest () { m_response.open( QIODevice::ReadWrite ); }
205 virtual ~HTTPRequest () = default;
206
207 bool ParseRequest ();
208
209 void FormatErrorResponse ( bool bServerError,
210 const QString &sFaultString,
211 const QString &sDetails );
212 void FormatErrorResponse(UPnPResultCode eCode, const QString &sMsg = "");
213
214 void FormatActionResponse( Serializer *ser );
215 void FormatActionResponse( const NameValues &pArgs );
216 void FormatFileResponse ( const QString &sFileName );
217 void FormatRawResponse ( const QString &sXML );
218
219 qint64 SendResponse ( void );
220 void SendResponseRedirect(const QString &hostName);
221 qint64 SendResponseFile( const QString& sFileName );
222
223 void SetResponseHeader ( const QString &sKey,
224 const QString &sValue,
225 bool replace = false );
226
227 void SetCookie ( const QString &sKey, const QString &sValue,
228 const QDateTime &expiryDate,
229 bool secure );
230
231 QString GetRequestHeader ( const QString &sKey, const QString &sDefault );
232
233 bool GetKeepAlive () const { return m_bKeepAlive; }
234
235 Serializer * GetSerializer ();
236
237 QByteArray GetResponsePage ( void ); // Static response e.g. 400, 404, 501
238
239 QString GetRequestProtocol () const;
240 static QString GetResponseProtocol () ;
241
242 QString GetRequestType () const;
243 QString GetLastHeader( const QString &sType ) const;
244
245 static QString GetMimeType ( const QString &sFileExtension );
246 static QStringList GetSupportedMimeTypes ();
247 static QString TestMimeType ( const QString &sFileName );
248 static long GetParameters ( QString sParams, QStringMap &mapParams );
249 static QString GetETagHash ( const QByteArray &data );
250
251 void SetKeepAliveTimeout ( std::chrono::seconds nTimeout ) { m_nKeepAliveTimeout = nTimeout; }
252
253 // ------------------------------------------------------------------
254
255 virtual QString ReadLine ( std::chrono::milliseconds msecs ) = 0;
256 virtual qint64 ReadBlock ( char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs = 0ms ) = 0;
257 virtual qint64 WriteBlock ( const char *pData,
258 qint64 nLen ) = 0;
259 virtual QString GetHostName (); // RFC 3875 - The name in the client request
260 virtual QString GetHostAddress () = 0;
261 virtual quint16 GetHostPort () = 0;
262 virtual QString GetPeerAddress () = 0;
263 virtual int getSocketHandle () = 0;
264};
265
267//
269
271{
272 public:
273
274 QTcpSocket *m_pSocket {nullptr};
275
276 public:
277
278 explicit BufferedSocketDeviceRequest( QTcpSocket *pSocket )
279 : m_pSocket(pSocket) {}
280 ~BufferedSocketDeviceRequest() override = default;
281
282 QString ReadLine ( std::chrono::milliseconds msecs ) override; // HTTPRequest
283 qint64 ReadBlock ( char *pData, qint64 nMaxLen, std::chrono::milliseconds msecs = 0ms ) override; // HTTPRequest
284 qint64 WriteBlock ( const char *pData, qint64 nLen ) override; // HTTPRequest
285 QString GetHostAddress () override; // HTTPRequest
286 quint16 GetHostPort () override; // HTTPRequest
287 QString GetPeerAddress () override; // HTTPRequest
288 int getSocketHandle () override // HTTPRequest
289 {return( m_pSocket->socketDescriptor() ); }
290
291};
292
294//
296
298{
299 public:
300 int m_code {-1};
301 QString m_msg;
302
303 explicit HttpException( int nCode = -1, QString sMsg = "")
304 : m_code( nCode ), m_msg (std::move( sMsg ))
305 {}
306
307 // Needed to force a v-table.
308 virtual ~HttpException() = default;
309};
310
312{
313 public:
314
315 QString m_hostName;
316 //int m_port;
317
318 explicit HttpRedirectException( QString sHostName = "",
319 int nCode = -1,
320 const QString &sMsg = "" )
321 : HttpException( nCode, sMsg ), m_hostName(std::move( sHostName ))
322 {}
323
324 ~HttpRedirectException() override = default;
325
326};
327
328#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:278
QString GetHostAddress() override
~BufferedSocketDeviceRequest() override=default
int getSocketHandle() override
Definition: httprequest.h:288
bool IsEncrypted() const
Definition: httprequest.h:198
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:131
virtual quint16 GetHostPort()=0
QString m_sRequestUrl
Definition: httprequest.h:128
void SetKeepAliveTimeout(std::chrono::seconds nTimeout)
Definition: httprequest.h:251
virtual int getSocketHandle()=0
MythUserSession m_userSession
Definition: httprequest.h:163
QStringMultiMap m_mapHeaders
Definition: httprequest.h:134
virtual QString ReadLine(std::chrono::milliseconds msecs)=0
bool GetKeepAlive() const
Definition: httprequest.h:233
QStringMap m_mapRespHeaders
Definition: httprequest.h:154
QString m_sOriginalUrl
Definition: httprequest.h:127
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:130
QString m_sBaseUrl
Definition: httprequest.h:129
QString m_sProtocol
Definition: httprequest.h:139
QStringMap m_mapCookies
Definition: httprequest.h:135
QString m_sRawRequest
Definition: httprequest.h:125
static const char * s_szServerHeaders
Definition: httprequest.h:115
QStringMap m_mapParams
Definition: httprequest.h:133
QString m_sPayload
Definition: httprequest.h:137
QBuffer m_response
Definition: httprequest.h:158
virtual QString GetPeerAddress()=0
virtual ~HttpException()=default
HttpException(int nCode=-1, QString sMsg="")
Definition: httprequest.h:303
QString m_msg
Definition: httprequest.h:301
HttpRedirectException(QString sHostName="", int nCode=-1, const QString &sMsg="")
Definition: httprequest.h:318
~HttpRedirectException() override=default
virtual void ExecutePostProcess()=0
virtual ~IPostProcess()=default
HttpContentType
Definition: httprequest.h:69
@ ContentType_XML
Definition: httprequest.h:72
@ ContentType_JSON
Definition: httprequest.h:73
@ ContentType_Unknown
Definition: httprequest.h:70
@ ContentType_Urlencoded
Definition: httprequest.h:71
static constexpr const char * SOAP_ENVELOPE_END
Definition: httprequest.h:39
HttpResponseType
Definition: httprequest.h:77
@ ResponseTypeSVG
Definition: httprequest.h:85
@ ResponseTypeCSS
Definition: httprequest.h:83
@ ResponseTypeFile
Definition: httprequest.h:86
@ ResponseTypeHTML
Definition: httprequest.h:81
@ ResponseTypeNone
Definition: httprequest.h:78
@ ResponseTypeUnknown
Definition: httprequest.h:79
@ ResponseTypeXML
Definition: httprequest.h:80
@ ResponseTypeJS
Definition: httprequest.h:82
@ ResponseTypeHeader
Definition: httprequest.h:88
@ ResponseTypeText
Definition: httprequest.h:84
@ ResponseTypeOther
Definition: httprequest.h:87
static constexpr const char * SOAP_ENVELOPE_BEGIN
Definition: httprequest.h:36
HttpRequestType
Definition: httprequest.h:47
@ RequestTypeMSearch
Definition: httprequest.h:59
@ RequestTypeSubscribe
Definition: httprequest.h:60
@ RequestTypeNotify
Definition: httprequest.h:62
@ RequestTypePost
Definition: httprequest.h:52
@ RequestTypeOptions
Definition: httprequest.h:56
@ RequestTypeUnsubscribe
Definition: httprequest.h:61
@ RequestTypeGet
Definition: httprequest.h:50
@ RequestTypeHead
Definition: httprequest.h:51
@ RequestTypeResponse
Definition: httprequest.h:64
@ RequestTypeUnknown
Definition: httprequest.h:48
unsigned short uint16_t
Definition: iso6937tables.h:3
static SSDPRequestType ProcessRequestLine(const QString &sLine)
Definition: ssdp.cpp:193
const char * pszType
Definition: httprequest.h:94
const char * pszExtension
Definition: httprequest.h:93
#define UPNP_PUBLIC
Definition: upnpexp.h:9
UPnPResultCode
Definition: upnpresultcode.h:9
QMultiMap< QString, QString > QStringMultiMap
Definition: upnputil.h:29
QMap< QString, QString > QStringMap
Definition: upnputil.h:28