Skip to content

Commit 823f2dd

Browse files
elpasonyalldawson
authored andcommitted
Merge pull request #8929 from elpaso/bugfix-21059-server-post-request-issues
Fix POST requests for QGIS server Cherry-picked from master b129850
1 parent bc4ccd0 commit 823f2dd

File tree

12 files changed

+236
-108
lines changed

12 files changed

+236
-108
lines changed

python/server/auto_generated/qgsfcgiserverrequest.sip.in

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,20 +32,6 @@ Class defining fcgi request
3232
Returns true if an error occurred during initialization
3333
%End
3434

35-
virtual QUrl url() const;
36-
37-
%Docstring
38-
39-
:return: the request url
40-
41-
Overrides base implementation because FCGI is typically behind
42-
a proxy server and QGIS Server will see a rewritten QUERY_STRING.
43-
FCGI implementation stores the REQUEST_URI (which is the URL seen
44-
by the proxy before it gets rewritten) and returns it instead of
45-
the rewritten one.
46-
%End
47-
48-
4935
};
5036

5137
/************************************************************************

python/server/auto_generated/qgsserverrequest.sip.in

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,13 @@ Constructor
5656

5757
virtual ~QgsServerRequest();
5858

59-
virtual QUrl url() const;
59+
QUrl url() const;
6060
%Docstring
6161

62-
:return: the request url
62+
:return: the request url as seen by QGIS server
6363

64-
Subclasses may override in case the original URL (not rewritten, e.g.from
65-
a web server rewrite module) needs to be returned instead of the URL
66-
seen by QGIS server.
64+
.. seealso:: :py:func:`originalUrl`
65+
server, by default the two are equal
6766
%End
6867

6968
QgsServerRequest::Method method() const;
@@ -139,13 +138,35 @@ is available.
139138
void setUrl( const QUrl &url );
140139
%Docstring
141140
Set the request url
141+
%End
142+
143+
QUrl originalUrl() const;
144+
%Docstring
145+
Returns the request url as seen by the web server,
146+
by default this is equal to the url seen by QGIS server
147+
148+
.. seealso:: :py:func:`url`
149+
150+
.. versionadded:: 3.6
142151
%End
143152

144153
void setMethod( QgsServerRequest::Method method );
145154
%Docstring
146155
Set the request method
147156
%End
148157

158+
protected:
159+
160+
void setOriginalUrl( const QUrl &url );
161+
%Docstring
162+
Set the request original ``url`` (the request url as seen by the web server)
163+
164+
.. seealso:: :py:func:`setUrl`
165+
166+
.. versionadded:: 3.6
167+
%End
168+
169+
149170
};
150171

151172
/************************************************************************

src/server/qgsfcgiserverrequest.cpp

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ QgsFcgiServerRequest::QgsFcgiServerRequest()
7171
}
7272

7373
// Store the URL before the server rewrite that could have been set in QUERY_STRING
74-
mOriginalUrl = url;
74+
setOriginalUrl( url );
7575

7676
// OGC parameters are passed with the query string, which is normally part of
7777
// the REQUEST_URI, we override the query string url in case it is defined
@@ -133,26 +133,33 @@ QByteArray QgsFcgiServerRequest::data() const
133133
return mData;
134134
}
135135

136-
QUrl QgsFcgiServerRequest::url() const
137-
{
138-
return mOriginalUrl.isEmpty() ? QgsServerRequest::url() : mOriginalUrl;
139-
}
140-
141136
// Read post put data
142137
void QgsFcgiServerRequest::readData()
143138
{
144139
// Check if we have CONTENT_LENGTH defined
145140
const char *lengthstr = getenv( "CONTENT_LENGTH" );
146141
if ( lengthstr )
147142
{
148-
#ifdef QGISDEBUG
149-
qDebug() << "fcgi: reading " << lengthstr << " bytes from stdin";
150-
#endif
151143
bool success = false;
152144
int length = QString( lengthstr ).toInt( &success );
145+
// Note: REQUEST_BODY is not part of CGI standard, and it is not
146+
// normally passed by any CGI web server and it is implemented only
147+
// to allow unit tests to inject a request body and simulate a POST
148+
// request
149+
const char *request_body = getenv( "REQUEST_BODY" );
150+
if ( success && request_body )
151+
{
152+
QString body( request_body );
153+
body.truncate( length );
154+
mData.append( body.toUtf8() );
155+
length = 0;
156+
}
157+
#ifdef QGISDEBUG
158+
qDebug() << "fcgi: reading " << lengthstr << " bytes from " << ( request_body ? "REQUEST_BODY" : "stdin" );
159+
#endif
153160
if ( success )
154161
{
155-
// XXX This not efficiont at all !!
162+
// XXX This not efficient at all !!
156163
for ( int i = 0; i < length; ++i )
157164
{
158165
mData.append( getchar() );

src/server/qgsfcgiserverrequest.h

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,6 @@ class SERVER_EXPORT QgsFcgiServerRequest: public QgsServerRequest
4242
*/
4343
bool hasError() const { return mHasError; }
4444

45-
/**
46-
* \returns the request url
47-
*
48-
* Overrides base implementation because FCGI is typically behind
49-
* a proxy server and QGIS Server will see a rewritten QUERY_STRING.
50-
* FCGI implementation stores the REQUEST_URI (which is the URL seen
51-
* by the proxy before it gets rewritten) and returns it instead of
52-
* the rewritten one.
53-
*/
54-
QUrl url() const override;
55-
56-
5745
private:
5846
void readData();
5947

@@ -64,8 +52,6 @@ class SERVER_EXPORT QgsFcgiServerRequest: public QgsServerRequest
6452

6553
QByteArray mData;
6654
bool mHasError = false;
67-
//! Url before the server rewrite
68-
QUrl mOriginalUrl;
6955
};
7056

7157
#endif

src/server/qgsserverrequest.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ QgsServerRequest::QgsServerRequest( const QString &url, Method method, const Hea
2727

2828
QgsServerRequest::QgsServerRequest( const QUrl &url, Method method, const Headers &headers )
2929
: mUrl( url )
30+
, mOriginalUrl( url )
3031
, mMethod( method )
3132
, mHeaders( headers )
3233
{
@@ -60,6 +61,16 @@ QUrl QgsServerRequest::url() const
6061
return mUrl;
6162
}
6263

64+
QUrl QgsServerRequest::originalUrl() const
65+
{
66+
return mOriginalUrl;
67+
}
68+
69+
void QgsServerRequest::setOriginalUrl( const QUrl &url )
70+
{
71+
mOriginalUrl = url;
72+
}
73+
6374
QgsServerRequest::Method QgsServerRequest::method() const
6475
{
6576
return mMethod;

src/server/qgsserverrequest.h

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,12 @@ class SERVER_EXPORT QgsServerRequest
8282
virtual ~QgsServerRequest() = default;
8383

8484
/**
85-
* \returns the request url
85+
* \returns the request url as seen by QGIS server
8686
*
87-
* Subclasses may override in case the original URL (not rewritten, e.g.from
88-
* a web server rewrite module) needs to be returned instead of the URL
89-
* seen by QGIS server.
87+
* \see originalUrl for the unrewritten url as seen by the web
88+
* server, by default the two are equal
9089
*/
91-
virtual QUrl url() const;
90+
QUrl url() const;
9291

9392
/**
9493
* \returns the request method
@@ -159,13 +158,36 @@ class SERVER_EXPORT QgsServerRequest
159158
*/
160159
void setUrl( const QUrl &url );
161160

161+
/**
162+
* Returns the request url as seen by the web server,
163+
* by default this is equal to the url seen by QGIS server
164+
*
165+
* \see url() for the rewritten url
166+
* \since QGIS 3.6
167+
*/
168+
QUrl originalUrl() const;
169+
162170
/**
163171
* Set the request method
164172
*/
165173
void setMethod( QgsServerRequest::Method method );
166174

175+
protected:
176+
177+
/**
178+
* Set the request original \a url (the request url as seen by the web server)
179+
*
180+
* \see setUrl() for the rewritten url
181+
* \since QGIS 3.6
182+
*/
183+
void setOriginalUrl( const QUrl &url );
184+
185+
167186
private:
187+
// Url as seen by QGIS server after web server rewrite
168188
QUrl mUrl;
189+
// Unrewritten url as seen by the web server
190+
QUrl mOriginalUrl;
169191
Method mMethod = GetMethod;
170192
// We mark as mutable in order
171193
// to support lazy initialization

src/server/services/wcs/qgswcsutils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ namespace QgsWcs
250250
// Build default url
251251
if ( href.isEmpty() )
252252
{
253-
QUrl url = request.url();
253+
QUrl url = request.originalUrl();
254254
QUrlQuery q( url );
255255

256256
for ( auto param : q.queryItems() )

src/server/services/wfs/qgswfsutils.cpp

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,28 +37,36 @@ namespace QgsWfs
3737

3838
QString serviceUrl( const QgsServerRequest &request, const QgsProject *project )
3939
{
40-
QString href;
40+
QUrl href;
4141
if ( project )
4242
{
43-
href = QgsServerProjectUtils::wfsServiceUrl( *project );
43+
href.setUrl( QgsServerProjectUtils::wfsServiceUrl( *project ) );
4444
}
4545

4646
// Build default url
4747
if ( href.isEmpty() )
4848
{
49-
QUrl url = request.url();
5049

51-
QgsWfsParameters params;
52-
params.load( QUrlQuery( url ) );
53-
params.remove( QgsServerParameter::REQUEST );
54-
params.remove( QgsServerParameter::VERSION_SERVICE );
55-
params.remove( QgsServerParameter::SERVICE );
50+
static QSet<QString> sFilter
51+
{
52+
QStringLiteral( "REQUEST" ),
53+
QStringLiteral( "VERSION" ),
54+
QStringLiteral( "SERVICE" ),
55+
};
56+
57+
href = request.originalUrl();
58+
QUrlQuery q( href );
59+
60+
for ( auto param : q.queryItems() )
61+
{
62+
if ( sFilter.contains( param.first.toUpper() ) )
63+
q.removeAllQueryItems( param.first );
64+
}
5665

57-
url.setQuery( params.urlQuery() );
58-
href = url.toString();
66+
href.setQuery( q );
5967
}
6068

61-
return href;
69+
return href.toString();
6270
}
6371

6472
QString layerTypeName( const QgsMapLayer *layer )

src/server/services/wms/qgswmsutils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ namespace QgsWms
5656
QStringLiteral( "_DC" )
5757
};
5858

59-
href = request.url();
59+
href = request.originalUrl();
6060
QUrlQuery q( href );
6161

6262
for ( auto param : q.queryItems() )

src/server/services/wmts/qgswmtsutils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ namespace QgsWmts
6464
// Build default url
6565
if ( href.isEmpty() )
6666
{
67-
QUrl url = request.url();
67+
QUrl url = request.originalUrl();
6868

6969
QgsWmtsParameters params;
7070
params.load( QUrlQuery( url ) );

0 commit comments

Comments
 (0)