QGIS API Documentation 3.99.0-Master (2fe06baccd8)
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 <QUrl>
30#include <QUrlQuery>
31
33 : mRequest( request )
34 , mResponse( response )
35{
36}
37
38QMap<QString, QString> QgsRequestHandler::parameterMap() const
39{
40 return mRequest.parameters();
41}
42
44{
45 return mExceptionRaised;
46}
47
48void QgsRequestHandler::setResponseHeader( const QString &name, const QString &value )
49{
50 mResponse.setHeader( name, value );
51}
52
54{
55 mResponse.clear();
56}
57
58void QgsRequestHandler::removeResponseHeader( const QString &name )
59{
60 mResponse.removeHeader( name );
61}
62
63QString QgsRequestHandler::responseHeader( const QString &name ) const
64{
65 return mResponse.header( name );
66}
67
68QMap<QString, QString> QgsRequestHandler::responseHeaders() const
69{
70 return mResponse.headers();
71}
72
73void QgsRequestHandler::setRequestHeader( const QString &name, const QString &value )
74{
75 mRequest.setHeader( name, value );
76}
77
78void QgsRequestHandler::removeRequestHeader( const QString &name )
79{
80 mRequest.removeHeader( name );
81}
82
83QString QgsRequestHandler::requestHeader( const QString &name ) const
84{
85 return mRequest.header( name );
86}
87
88
89QMap<QString, QString> QgsRequestHandler::requestHeaders() const
90{
91 return mRequest.headers();
92}
93
94
96{
97 return mResponse.headersSent();
98}
99
100void QgsRequestHandler::appendBody( const QByteArray &body )
101{
102 mResponse.write( body );
103}
104
106{
107 mResponse.truncate();
108}
109
110QByteArray QgsRequestHandler::body() const
111{
112 return mResponse.data();
113}
114
115QByteArray QgsRequestHandler::data() const
116{
117 return mRequest.data();
118}
119
121{
122 return mRequest.url().toString();
123}
124
126{
127 return mRequest.url().path();
128}
129
131{
132 mResponse.setStatusCode( code );
133}
134
136{
137 return mResponse.statusCode();
138}
139
141{
142 // Send data to output
143 mResponse.flush();
144}
145
147{
148 // Safety measure to avoid potential leaks if called repeatedly
149 mExceptionRaised = true;
150 mResponse.write( ex );
151}
152
153void QgsRequestHandler::setupParameters()
154{
155 const QgsServerRequest::Parameters parameters = mRequest.parameters();
156
157 //feature info format?
158 const QString infoFormat = parameters.value( QStringLiteral( "INFO_FORMAT" ) );
159 if ( !infoFormat.isEmpty() )
160 {
161 mFormat = infoFormat;
162 }
163 else //capabilities format or GetMap format
164 {
165 mFormatString = parameters.value( QStringLiteral( "FORMAT" ) );
166 QString formatString = mFormatString;
167 if ( !formatString.isEmpty() )
168 {
169 //remove the image/ in front of the format
170 if ( formatString.contains( QLatin1String( "image/png" ), Qt::CaseInsensitive ) || formatString.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 )
171 {
172 formatString = QStringLiteral( "PNG" );
173 }
174 else if ( formatString.contains( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) || formatString.contains( QLatin1String( "image/jpg" ), Qt::CaseInsensitive )
175 || formatString.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0 )
176 {
177 formatString = QStringLiteral( "JPG" );
178 }
179 else if ( formatString.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
180 {
181 formatString = QStringLiteral( "SVG" );
182 }
183 else if ( formatString.contains( QLatin1String( "pdf" ), Qt::CaseInsensitive ) )
184 {
185 formatString = QStringLiteral( "PDF" );
186 }
187
188 mFormat = formatString;
189 }
190 }
191}
192
194{
195 if ( mRequest.method() == QgsServerRequest::PostMethod || mRequest.method() == QgsServerRequest::PutMethod || mRequest.method() == QgsServerRequest::PatchMethod )
196 {
197 if ( mRequest.header( QStringLiteral( "Content-Type" ) ).contains( QStringLiteral( "json" ) ) )
198 {
199 setupParameters();
200 }
201 else
202 {
203 QString inputString( mRequest.data() );
204 QDomDocument doc;
205 QString errorMsg;
206 int line = -1;
207 int column = -1;
208 if ( !doc.setContent( inputString, true, &errorMsg, &line, &column ) )
209 {
210 // Output Warning about POST without XML content
211 QgsMessageLog::logMessage( QStringLiteral( "Error parsing post data as XML: at line %1, column %2: %3. Assuming urlencoded query string sent in the post body." ).arg( line ).arg( column ).arg( errorMsg ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
212
213 // Process input string as a simple query text
214
215 typedef QPair<QString, QString> pair_t;
216 const QUrlQuery query( inputString );
217 const QList<pair_t> items = query.queryItems();
218 for ( const pair_t &pair : items )
219 {
220 mRequest.setParameter( pair.first, pair.second );
221 }
222 setupParameters();
223 }
224 else
225 {
226 // we have an XML document
227
228 setupParameters();
229
230 const QDomElement docElem = doc.documentElement();
231 // the document element tag name is the request
232 mRequest.setParameter( QStringLiteral( "REQUEST" ), docElem.tagName() );
233 // loop through the attributes which are the parameters
234 // excepting the attributes started by xmlns or xsi
235 const QDomNamedNodeMap map = docElem.attributes();
236 for ( int i = 0; i < map.length(); ++i )
237 {
238 if ( map.item( i ).isNull() )
239 continue;
240
241 const QDomNode attrNode = map.item( i );
242 const QDomAttr attr = attrNode.toAttr();
243 if ( attr.isNull() )
244 continue;
245
246 const QString attrName = attr.name();
247 if ( attrName.startsWith( "xmlns" ) || attrName.startsWith( "xsi:" ) )
248 continue;
249
250 mRequest.setParameter( attrName.toUpper(), attr.value() );
251 }
252 mRequest.setParameter( QStringLiteral( "REQUEST_BODY" ), inputString.replace( '+', QLatin1String( "%2B" ) ) );
253 }
254 }
255 }
256 else
257 {
258 setupParameters();
259 }
260}
261
262void QgsRequestHandler::setParameter( const QString &key, const QString &value )
263{
264 if ( !( key.isEmpty() || value.isEmpty() ) )
265 {
266 // Warn for potential breaking change if plugin set the MAP parameter
267 // expecting changing the config file path, see PR #9773
268 if ( key.compare( QLatin1String( "MAP" ), Qt::CaseInsensitive ) == 0 )
269 {
270 QgsMessageLog::logMessage( QStringLiteral( "Changing the 'MAP' parameter will have no effect on config path: use QgsSerververInterface::setConfigFilePath instead" ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
271 }
272 mRequest.setParameter( key, value );
273 }
274}
275
276
277QString QgsRequestHandler::parameter( const QString &key ) const
278{
279 return mRequest.parameter( key );
280}
281
282void QgsRequestHandler::removeParameter( const QString &key )
283{
284 mRequest.removeParameter( key );
285}
@ Warning
Warning message.
Definition qgis.h:158
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())
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.