QGIS API Documentation 4.1.0-Master (5bf3c20f3c9)
Loading...
Searching...
No Matches
qgsrequesthandler.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgshttprequesthandler.cpp
3 -------------------------
4 begin : June 29, 2007
5 copyright : (C) 2007 by Marco Hugentobler
6 (C) 2014 by Alessandro Pasotti
7 email : marco dot hugentobler at karto dot baug dot ethz dot ch
8 a dot pasotti at itopen dot it
9 ***************************************************************************/
10
11/***************************************************************************
12 * *
13 * This program is free software; you can redistribute it and/or modify *
14 * it under the terms of the GNU General Public License as published by *
15 * the Free Software Foundation; either version 2 of the License, or *
16 * (at your option) any later version. *
17 * *
18 ***************************************************************************/
19
20#include "qgsrequesthandler.h"
21
22#include "qgis.h"
23#include "qgsmessagelog.h"
24#include "qgsserverrequest.h"
25#include "qgsserverresponse.h"
26
27#include <QByteArray>
28#include <QDomDocument>
29#include <QString>
30#include <QUrl>
31#include <QUrlQuery>
32
33using namespace Qt::StringLiterals;
34
36 : mRequest( request )
37 , mResponse( response )
38{}
39
40QMap<QString, QString> QgsRequestHandler::parameterMap() const
41{
42 return mRequest.parameters();
43}
44
46{
47 return mExceptionRaised;
48}
49
50void QgsRequestHandler::setResponseHeader( const QString &name, const QString &value )
51{
52 mResponse.setHeader( name, value );
53}
54
56{
57 mResponse.clear();
58}
59
60void QgsRequestHandler::removeResponseHeader( const QString &name )
61{
62 mResponse.removeHeader( name );
63}
64
65QString QgsRequestHandler::responseHeader( const QString &name ) const
66{
67 return mResponse.header( name );
68}
69
70QMap<QString, QString> QgsRequestHandler::responseHeaders() const
71{
72 return mResponse.headers();
73}
74
75void QgsRequestHandler::setRequestHeader( const QString &name, const QString &value )
76{
77 mRequest.setHeader( name, value );
78}
79
80void QgsRequestHandler::removeRequestHeader( const QString &name )
81{
82 mRequest.removeHeader( name );
83}
84
85QString QgsRequestHandler::requestHeader( const QString &name ) const
86{
87 return mRequest.header( name );
88}
89
90
91QMap<QString, QString> QgsRequestHandler::requestHeaders() const
92{
93 return mRequest.headers();
94}
95
96
98{
99 return mResponse.headersSent();
100}
101
102void QgsRequestHandler::appendBody( const QByteArray &body )
103{
104 mResponse.write( body );
105}
106
108{
109 mResponse.truncate();
110}
111
112QByteArray QgsRequestHandler::body() const
113{
114 return mResponse.data();
115}
116
117QByteArray QgsRequestHandler::data() const
118{
119 return mRequest.data();
120}
121
123{
124 return mRequest.url().toString();
125}
126
128{
129 return mRequest.url().path();
130}
131
133{
134 mResponse.setStatusCode( code );
135}
136
138{
139 return mResponse.statusCode();
140}
141
143{
144 // Send data to output
145 mResponse.flush();
146}
147
149{
150 // Safety measure to avoid potential leaks if called repeatedly
151 mExceptionRaised = true;
152 mResponse.write( ex );
153}
154
155void QgsRequestHandler::setupParameters()
156{
157 const QgsServerRequest::Parameters parameters = mRequest.parameters();
158
159 //feature info format?
160 const QString infoFormat = parameters.value( u"INFO_FORMAT"_s );
161 if ( !infoFormat.isEmpty() )
162 {
163 mFormat = infoFormat;
164 }
165 else //capabilities format or GetMap format
166 {
167 mFormatString = parameters.value( u"FORMAT"_s );
168 QString formatString = mFormatString;
169 if ( !formatString.isEmpty() )
170 {
171 //remove the image/ in front of the format
172 if ( formatString.contains( "image/png"_L1, Qt::CaseInsensitive ) || formatString.compare( "png"_L1, Qt::CaseInsensitive ) == 0 )
173 {
174 formatString = u"PNG"_s;
175 }
176 else if ( formatString.contains( "image/jpeg"_L1, Qt::CaseInsensitive ) || formatString.contains( "image/jpg"_L1, Qt::CaseInsensitive ) || formatString.compare( "jpg"_L1, Qt::CaseInsensitive ) == 0 )
177 {
178 formatString = u"JPG"_s;
179 }
180 else if ( formatString.compare( "svg"_L1, Qt::CaseInsensitive ) == 0 )
181 {
182 formatString = u"SVG"_s;
183 }
184 else if ( formatString.contains( "pdf"_L1, Qt::CaseInsensitive ) )
185 {
186 formatString = u"PDF"_s;
187 }
188
189 mFormat = formatString;
190 }
191 }
192}
193
195{
196 if ( mRequest.method() == QgsServerRequest::PostMethod || mRequest.method() == QgsServerRequest::PutMethod || mRequest.method() == QgsServerRequest::PatchMethod )
197 {
198 if ( mRequest.header( u"Content-Type"_s ).contains( u"json"_s ) )
199 {
200 setupParameters();
201 }
202 else
203 {
204 QString inputString( mRequest.data() );
205 QDomDocument doc;
206 QString errorMsg;
207 int line = -1;
208 int column = -1;
209 if ( !doc.setContent( inputString, true, &errorMsg, &line, &column ) )
210 {
211 // Output Warning about POST without XML content
213 logMessage( u"Error parsing post data as XML: at line %1, column %2: %3. Assuming urlencoded query string sent in the post body."_s.arg( line ).arg( column ).arg( errorMsg ), u"Server"_s, Qgis::MessageLevel::Warning );
214
215 // Process input string as a simple query text
216
217 typedef QPair<QString, QString> pair_t;
218 const QUrlQuery query( inputString );
219 const QList<pair_t> items = query.queryItems();
220 for ( const pair_t &pair : items )
221 {
222 mRequest.setParameter( pair.first, pair.second );
223 }
224 setupParameters();
225 }
226 else
227 {
228 // we have an XML document
229
230 setupParameters();
231
232 const QDomElement docElem = doc.documentElement();
233 // the document element tag name is the request
234 mRequest.setParameter( u"REQUEST"_s, docElem.tagName() );
235 // loop through the attributes which are the parameters
236 // excepting the attributes started by xmlns or xsi
237 const QDomNamedNodeMap map = docElem.attributes();
238 for ( int i = 0; i < map.length(); ++i )
239 {
240 if ( map.item( i ).isNull() )
241 continue;
242
243 const QDomNode attrNode = map.item( i );
244 const QDomAttr attr = attrNode.toAttr();
245 if ( attr.isNull() )
246 continue;
247
248 const QString attrName = attr.name();
249 if ( attrName.startsWith( "xmlns" ) || attrName.startsWith( "xsi:" ) )
250 continue;
251
252 mRequest.setParameter( attrName.toUpper(), attr.value() );
253 }
254 mRequest.setParameter( u"REQUEST_BODY"_s, inputString.replace( '+', "%2B"_L1 ) );
255 }
256 }
257 }
258 else
259 {
260 setupParameters();
261 }
262}
263
264void QgsRequestHandler::setParameter( const QString &key, const QString &value )
265{
266 if ( !( key.isEmpty() || value.isEmpty() ) )
267 {
268 // Warn for potential breaking change if plugin set the MAP parameter
269 // expecting changing the config file path, see PR #9773
270 if ( key.compare( "MAP"_L1, Qt::CaseInsensitive ) == 0 )
271 {
272 QgsMessageLog::logMessage( u"Changing the 'MAP' parameter will have no effect on config path: use QgsSerververInterface::setConfigFilePath instead"_s, u"Server"_s, Qgis::MessageLevel::Warning );
273 }
274 mRequest.setParameter( key, value );
275 }
276}
277
278
279QString QgsRequestHandler::parameter( const QString &key ) const
280{
281 return mRequest.parameter( key );
282}
283
284void QgsRequestHandler::removeParameter( const QString &key )
285{
286 mRequest.removeParameter( key );
287}
@ Warning
Warning message.
Definition qgis.h:162
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true, const char *file=__builtin_FILE(), const char *function=__builtin_FUNCTION(), int line=__builtin_LINE(), Qgis::StringFormat format=Qgis::StringFormat::PlainText)
Adds a message to the log instance (and creates it if necessary).
void removeParameter(const QString &key)
Remove a request parameter.
void removeRequestHeader(const QString &name)
Remove an HTTP request header.
QString responseHeader(const QString &name) const
Retrieve response header value.
void clearBody()
Clear response buffer.
QString requestHeader(const QString &name) const
Retrieve request header value.
QMap< QString, QString > parameterMap() const
Returns the parsed parameters as a key-value pair.
QString path() const
Returns the path component of the request URL.
QByteArray data() const
Returns the request POST data (can be null).
bool exceptionRaised() const
Pointer to last raised exception.
bool headersSent() const
Returns true if the HTTP headers were already sent to the client.
void parseInput()
Parses the input and creates a request neutral Parameter/Value map.
void setServiceException(const QgsServerException &ex)
Allow plugins to return a QgsMapServiceException.
void removeResponseHeader(const QString &name)
Remove an HTTP response header.
void sendResponse()
Send out HTTP headers and flush output buffer.
QMap< QString, QString > responseHeaders() const
Returns the response headers.
void setRequestHeader(const QString &name, const QString &value)
Sets an HTTP request header.
void appendBody(const QByteArray &body)
Sets the info format string such as "text/xml".
QString parameter(const QString &key) const
Returns a request parameter.
QMap< QString, QString > requestHeaders() const
Returns the the Request headers.
QString url() const
Returns the request url.
void setStatusCode(int code)
Sets response http status code.
QgsRequestHandler(QgsServerRequest &request, QgsServerResponse &response)
Constructor.
QByteArray body() const
Returns the response body data.
void clear()
Clears the response body and headers.
void setResponseHeader(const QString &name, const QString &value)
Sets an HTTP response header.
int statusCode() const
Returns the response http status code.
void setParameter(const QString &key, const QString &value)
Sets a request parameter.
Exception base class for server exceptions.
Defines requests passed to QgsService classes.
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
QMap< QString, QString > Parameters
Defines the response interface passed to QgsService.