QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
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 "qgis.h"
21 #include "qgsrequesthandler.h"
22 #include "qgsmessagelog.h"
23 #include "qgsserverrequest.h"
24 #include "qgsserverresponse.h"
25 #include <QByteArray>
26 #include <QDomDocument>
27 #include <QUrl>
28 #include <QUrlQuery>
29 
31  : mExceptionRaised( false )
32  , mRequest( request )
33  , mResponse( response )
34 {
35 }
36 
37 QMap<QString, QString> QgsRequestHandler::parameterMap() const
38 {
39  return mRequest.parameters();
40 }
41 
43 {
44  return mExceptionRaised;
45 }
46 
47 void QgsRequestHandler::setResponseHeader( const QString &name, const QString &value )
48 {
49  mResponse.setHeader( name, value );
50 }
51 
53 {
54  mResponse.clear();
55 }
56 
57 void QgsRequestHandler::removeResponseHeader( const QString &name )
58 {
59  mResponse.removeHeader( name );
60 }
61 
62 QString QgsRequestHandler::responseHeader( const QString &name ) const
63 {
64  return mResponse.header( name );
65 }
66 
67 QMap<QString, QString> QgsRequestHandler::responseHeaders() const
68 {
69  return mResponse.headers();
70 }
71 
72 void QgsRequestHandler::setRequestHeader( const QString &name, const QString &value )
73 {
74  mRequest.setHeader( name, value );
75 }
76 
77 void QgsRequestHandler::removeRequestHeader( const QString &name )
78 {
79  mRequest.removeHeader( name );
80 }
81 
82 QString QgsRequestHandler::requestHeader( const QString &name ) const
83 {
84  return mRequest.header( name );
85 }
86 
87 
88 QMap<QString, QString> QgsRequestHandler::requestHeaders() const
89 {
90  return mRequest.headers();
91 }
92 
93 
95 {
96  return mResponse.headersSent();
97 }
98 
99 void QgsRequestHandler::appendBody( const QByteArray &body )
100 {
101  mResponse.write( body );
102 }
103 
105 {
106  mResponse.truncate();
107 }
108 
109 QByteArray QgsRequestHandler::body() const
110 {
111  return mResponse.data();
112 }
113 
114 QByteArray QgsRequestHandler::data() const
115 {
116  return mRequest.data();
117 }
118 
119 QString QgsRequestHandler::url() const
120 {
121  return mRequest.url().toString();
122 }
123 
124 QString QgsRequestHandler::path() const
125 {
126  return mRequest.url().path();
127 }
128 
130 {
131  mResponse.setStatusCode( code );
132 }
133 
135 {
136  return mResponse.statusCode();
137 }
138 
140 {
141  // Send data to output
142  mResponse.flush();
143 }
144 
146 {
147  // Safety measure to avoid potential leaks if called repeatedly
148  mExceptionRaised = true;
149  mResponse.write( ex );
150 }
151 
152 void QgsRequestHandler::setupParameters()
153 {
154  const QgsServerRequest::Parameters parameters = mRequest.parameters();
155 
156  //feature info format?
157  const QString infoFormat = parameters.value( QStringLiteral( "INFO_FORMAT" ) );
158  if ( !infoFormat.isEmpty() )
159  {
160  mFormat = infoFormat;
161  }
162  else //capabilities format or GetMap format
163  {
164  mFormatString = parameters.value( QStringLiteral( "FORMAT" ) );
165  QString formatString = mFormatString;
166  if ( !formatString.isEmpty() )
167  {
168  //remove the image/ in front of the format
169  if ( formatString.contains( QLatin1String( "image/png" ), Qt::CaseInsensitive ) || formatString.compare( QLatin1String( "png" ), Qt::CaseInsensitive ) == 0 )
170  {
171  formatString = QStringLiteral( "PNG" );
172  }
173  else if ( formatString.contains( QLatin1String( "image/jpeg" ), Qt::CaseInsensitive ) || formatString.contains( QLatin1String( "image/jpg" ), Qt::CaseInsensitive )
174  || formatString.compare( QLatin1String( "jpg" ), Qt::CaseInsensitive ) == 0 )
175  {
176  formatString = QStringLiteral( "JPG" );
177  }
178  else if ( formatString.compare( QLatin1String( "svg" ), Qt::CaseInsensitive ) == 0 )
179  {
180  formatString = QStringLiteral( "SVG" );
181  }
182  else if ( formatString.contains( QLatin1String( "pdf" ), Qt::CaseInsensitive ) )
183  {
184  formatString = QStringLiteral( "PDF" );
185  }
186 
187  mFormat = formatString;
188  }
189  }
190 
191 }
192 
194 {
195  if ( mRequest.method() == QgsServerRequest::PostMethod ||
196  mRequest.method() == QgsServerRequest::PutMethod ||
197  mRequest.method() == QgsServerRequest::PatchMethod )
198  {
199  if ( mRequest.header( QStringLiteral( "Content-Type" ) ).contains( QStringLiteral( "json" ) ) )
200  {
201  setupParameters();
202  }
203  else
204  {
205  QString inputString( mRequest.data() );
206  QDomDocument doc;
207  QString errorMsg;
208  int line = -1;
209  int column = -1;
210  if ( !doc.setContent( inputString, true, &errorMsg, &line, &column ) )
211  {
212  // Output Warning about POST without XML content
213  QgsMessageLog::logMessage( QStringLiteral( "Error parsing post data as XML: at line %1, column %2: %3. Assuming urlencoded query string sent in the post body." )
214  .arg( line ).arg( column ).arg( errorMsg ),
215  QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
216 
217  // Process input string as a simple query text
218 
219  typedef QPair<QString, QString> pair_t;
220  const QUrlQuery query( inputString );
221  const QList<pair_t> items = query.queryItems();
222  for ( const pair_t &pair : items )
223  {
224  mRequest.setParameter( pair.first, pair.second );
225  }
226  setupParameters();
227  }
228  else
229  {
230  // we have an XML document
231 
232  setupParameters();
233 
234  const QDomElement docElem = doc.documentElement();
235  // the document element tag name is the request
236  mRequest.setParameter( QStringLiteral( "REQUEST" ), docElem.tagName() );
237  // loop through the attributes which are the parameters
238  // excepting the attributes started by xmlns or xsi
239  const QDomNamedNodeMap map = docElem.attributes();
240  for ( int i = 0 ; i < map.length() ; ++i )
241  {
242  if ( map.item( i ).isNull() )
243  continue;
244 
245  const QDomNode attrNode = map.item( i );
246  const QDomAttr attr = attrNode.toAttr();
247  if ( attr.isNull() )
248  continue;
249 
250  const QString attrName = attr.name();
251  if ( attrName.startsWith( "xmlns" ) || attrName.startsWith( "xsi:" ) )
252  continue;
253 
254  mRequest.setParameter( attrName.toUpper(), attr.value() );
255  }
256  mRequest.setParameter( QStringLiteral( "REQUEST_BODY" ), inputString.replace( '+', QLatin1String( "%2B" ) ) );
257  }
258  }
259  }
260  else
261  {
262  setupParameters();
263  }
264 }
265 
266 void QgsRequestHandler::setParameter( const QString &key, const QString &value )
267 {
268  if ( !( key.isEmpty() || value.isEmpty() ) )
269  {
270  // Warn for potential breaking change if plugin set the MAP parameter
271  // expecting changing the config file path, see PR #9773
272  if ( key.compare( QLatin1String( "MAP" ), Qt::CaseInsensitive ) == 0 )
273  {
274  QgsMessageLog::logMessage( QStringLiteral( "Changing the 'MAP' parameter will have no effect on config path: use QgsSerververInterface::setConfigFilePath instead" ),
275  QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
276  }
277  mRequest.setParameter( key, value );
278  }
279 }
280 
281 
282 QString QgsRequestHandler::parameter( const QString &key ) const
283 {
284  return mRequest.parameter( key );
285 }
286 
287 void QgsRequestHandler::removeParameter( const QString &key )
288 {
289  mRequest.removeParameter( key );
290 }
QgsServerRequest::parameters
QgsServerRequest::Parameters parameters() const
Returns a map of query parameters with keys converted to uppercase.
Definition: qgsserverrequest.cpp:116
QgsRequestHandler::removeRequestHeader
void removeRequestHeader(const QString &name)
Remove an HTTP request header.
Definition: qgsrequesthandler.cpp:77
QgsServerRequest::setHeader
void setHeader(const QString &name, const QString &value)
Set an header.
Definition: qgsserverrequest.cpp:71
QgsRequestHandler::headersSent
bool headersSent() const
Returns true if the HTTP headers were already sent to the client.
Definition: qgsrequesthandler.cpp:94
QgsRequestHandler::clear
void clear()
Clears the response body and headers.
Definition: qgsrequesthandler.cpp:52
QgsRequestHandler::body
QByteArray body() const
Returns the response body data.
Definition: qgsrequesthandler.cpp:109
QgsServerResponse::flush
virtual void flush() SIP_THROW(QgsServerException)
Flushes the current output buffer to the network.
Definition: qgsserverresponse.cpp:73
QgsRequestHandler::url
QString url() const
Returns the request url.
Definition: qgsrequesthandler.cpp:119
QgsServerResponse::truncate
virtual void truncate()=0
Truncate data.
qgis.h
QgsServerResponse::clear
virtual void clear()=0
Reset all headers and content for this response.
QgsServerRequest
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
Definition: qgsserverrequest.h:38
QgsRequestHandler::clearBody
void clearBody()
Clear response buffer.
Definition: qgsrequesthandler.cpp:104
QgsServerRequest::removeHeader
void removeHeader(const QString &name)
Remove an header.
Definition: qgsserverrequest.cpp:81
QgsServerResponse::statusCode
virtual int statusCode() const =0
Returns the http status code.
QgsServerRequest::Parameters
QMap< QString, QString > Parameters
Definition: qgsserverrequest.h:59
QgsServerRequest::removeParameter
virtual void removeParameter(const QString &key)
Remove a parameter.
Definition: qgsserverrequest.cpp:147
QgsServerResponse::write
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
Definition: qgsserverresponse.cpp:25
QgsRequestHandler::path
QString path() const
Returns the path component of the request URL.
Definition: qgsrequesthandler.cpp:124
QgsRequestHandler::responseHeader
QString responseHeader(const QString &name) const
Retrieve response header value.
Definition: qgsrequesthandler.cpp:62
QgsServerRequest::setParameter
virtual void setParameter(const QString &key, const QString &value)
Set a parameter.
Definition: qgsserverrequest.cpp:131
qgsserverrequest.h
QgsRequestHandler::requestHeaders
QMap< QString, QString > requestHeaders() const
Returns the the Request headers.
Definition: qgsrequesthandler.cpp:88
qgsserverresponse.h
QgsServerRequest::PostMethod
@ PostMethod
Definition: qgsserverrequest.h:70
QgsServerRequest::method
QgsServerRequest::Method method() const
Definition: qgsserverrequest.cpp:111
QgsRequestHandler::appendBody
void appendBody(const QByteArray &body)
Sets the info format string such as "text/xml".
Definition: qgsrequesthandler.cpp:99
QgsServerResponse::header
virtual QString header(const QString &key) const =0
Returns the header value.
QgsServerResponse::setStatusCode
virtual void setStatusCode(int code)=0
Set the http status code.
QgsServerResponse::removeHeader
virtual void removeHeader(const QString &key)=0
Clear header Undo a previous 'setHeader' call.
QgsRequestHandler::parseInput
void parseInput()
Parses the input and creates a request neutral Parameter/Value map.
Definition: qgsrequesthandler.cpp:193
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsRequestHandler::setRequestHeader
void setRequestHeader(const QString &name, const QString &value)
Sets an HTTP request header.
Definition: qgsrequesthandler.cpp:72
QgsServerRequest::header
virtual QString header(const QString &name) const
Returns the header value.
Definition: qgsserverrequest.cpp:56
QgsRequestHandler::sendResponse
void sendResponse()
Send out HTTP headers and flush output buffer.
Definition: qgsrequesthandler.cpp:139
QgsRequestHandler::setStatusCode
void setStatusCode(int code)
Sets response http status code.
Definition: qgsrequesthandler.cpp:129
QgsServerResponse::data
virtual QByteArray data() const =0
Gets the data written so far.
QgsRequestHandler::setResponseHeader
void setResponseHeader(const QString &name, const QString &value)
Sets an HTTP response header.
Definition: qgsrequesthandler.cpp:47
QgsRequestHandler::exceptionRaised
bool exceptionRaised() const
Pointer to last raised exception.
Definition: qgsrequesthandler.cpp:42
QgsRequestHandler::parameterMap
QMap< QString, QString > parameterMap() const
Returns the parsed parameters as a key-value pair, to modify a parameter setParameter( const QString ...
Definition: qgsrequesthandler.cpp:37
QgsServerRequest::data
virtual QByteArray data() const
Returns post/put data Check for QByteArray::isNull() to check if data is available.
Definition: qgsserverrequest.cpp:126
QgsServerResponse::headersSent
virtual bool headersSent() const =0
Returns true if the headers have already been sent.
QgsRequestHandler::setServiceException
void setServiceException(const QgsServerException &ex)
Allow plugins to return a QgsMapServiceException.
Definition: qgsrequesthandler.cpp:145
QgsServerException
Exception base class for server exceptions.
Definition: qgsserverexception.h:42
QgsServerRequest::parameter
QString parameter(const QString &key, const QString &defaultValue=QString()) const
Gets a parameter value.
Definition: qgsserverrequest.cpp:137
QgsRequestHandler::statusCode
int statusCode() const
Returns the response http status code.
Definition: qgsrequesthandler.cpp:134
QgsRequestHandler::requestHeader
QString requestHeader(const QString &name) const
Retrieve request header value.
Definition: qgsrequesthandler.cpp:82
QgsServerRequest::url
QUrl url() const
Definition: qgsserverrequest.cpp:86
QgsRequestHandler::removeResponseHeader
void removeResponseHeader(const QString &name)
Remove an HTTP response header.
Definition: qgsrequesthandler.cpp:57
QgsRequestHandler::QgsRequestHandler
QgsRequestHandler(QgsServerRequest &request, QgsServerResponse &response)
Constructor.
Definition: qgsrequesthandler.cpp:30
QgsServerRequest::PatchMethod
@ PatchMethod
Definition: qgsserverrequest.h:72
qgsrequesthandler.h
QgsRequestHandler::data
QByteArray data() const
Returns the request POST data (can be null)
Definition: qgsrequesthandler.cpp:114
QgsRequestHandler::setParameter
void setParameter(const QString &key, const QString &value)
Sets a request parameter.
Definition: qgsrequesthandler.cpp:266
QgsRequestHandler::removeParameter
void removeParameter(const QString &key)
Remove a request parameter.
Definition: qgsrequesthandler.cpp:287
QgsServerRequest::PutMethod
@ PutMethod
Definition: qgsserverrequest.h:68
QgsServerResponse::headers
virtual QMap< QString, QString > headers() const =0
Returns the header value.
QgsServerResponse
QgsServerResponse Class defining response interface passed to services QgsService::executeRequest() m...
Definition: qgsserverresponse.h:43
QgsRequestHandler::parameter
QString parameter(const QString &key) const
Returns a request parameter.
Definition: qgsrequesthandler.cpp:282
QgsRequestHandler::responseHeaders
QMap< QString, QString > responseHeaders() const
Returns the response headers.
Definition: qgsrequesthandler.cpp:67
QgsServerResponse::setHeader
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
qgsmessagelog.h
QgsServerRequest::headers
QMap< QString, QString > headers() const
Returns the header map.
Definition: qgsserverrequest.cpp:76