Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #8929 from elpaso/bugfix-21059-server-post-request…
…-issues

Fix POST requests for QGIS server

Cherry-picked from master b129850
  • Loading branch information
elpaso authored and nyalldawson committed Feb 6, 2019
1 parent bc4ccd0 commit 823f2dd
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 108 deletions.
14 changes: 0 additions & 14 deletions python/server/auto_generated/qgsfcgiserverrequest.sip.in
Expand Up @@ -32,20 +32,6 @@ Class defining fcgi request
Returns true if an error occurred during initialization
%End

virtual QUrl url() const;

%Docstring

:return: the request url

Overrides base implementation because FCGI is typically behind
a proxy server and QGIS Server will see a rewritten QUERY_STRING.
FCGI implementation stores the REQUEST_URI (which is the URL seen
by the proxy before it gets rewritten) and returns it instead of
the rewritten one.
%End


};

/************************************************************************
Expand Down
31 changes: 26 additions & 5 deletions python/server/auto_generated/qgsserverrequest.sip.in
Expand Up @@ -56,14 +56,13 @@ Constructor

virtual ~QgsServerRequest();

virtual QUrl url() const;
QUrl url() const;
%Docstring

:return: the request url
:return: the request url as seen by QGIS server

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

QgsServerRequest::Method method() const;
Expand Down Expand Up @@ -139,13 +138,35 @@ is available.
void setUrl( const QUrl &url );
%Docstring
Set the request url
%End

QUrl originalUrl() const;
%Docstring
Returns the request url as seen by the web server,
by default this is equal to the url seen by QGIS server

.. seealso:: :py:func:`url`

.. versionadded:: 3.6
%End

void setMethod( QgsServerRequest::Method method );
%Docstring
Set the request method
%End

protected:

void setOriginalUrl( const QUrl &url );
%Docstring
Set the request original ``url`` (the request url as seen by the web server)

.. seealso:: :py:func:`setUrl`

.. versionadded:: 3.6
%End


};

/************************************************************************
Expand Down
27 changes: 17 additions & 10 deletions src/server/qgsfcgiserverrequest.cpp
Expand Up @@ -71,7 +71,7 @@ QgsFcgiServerRequest::QgsFcgiServerRequest()
}

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

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

QUrl QgsFcgiServerRequest::url() const
{
return mOriginalUrl.isEmpty() ? QgsServerRequest::url() : mOriginalUrl;
}

// Read post put data
void QgsFcgiServerRequest::readData()
{
// Check if we have CONTENT_LENGTH defined
const char *lengthstr = getenv( "CONTENT_LENGTH" );
if ( lengthstr )
{
#ifdef QGISDEBUG
qDebug() << "fcgi: reading " << lengthstr << " bytes from stdin";
#endif
bool success = false;
int length = QString( lengthstr ).toInt( &success );
// Note: REQUEST_BODY is not part of CGI standard, and it is not
// normally passed by any CGI web server and it is implemented only
// to allow unit tests to inject a request body and simulate a POST
// request
const char *request_body = getenv( "REQUEST_BODY" );
if ( success && request_body )
{
QString body( request_body );
body.truncate( length );
mData.append( body.toUtf8() );
length = 0;
}
#ifdef QGISDEBUG
qDebug() << "fcgi: reading " << lengthstr << " bytes from " << ( request_body ? "REQUEST_BODY" : "stdin" );
#endif
if ( success )
{
// XXX This not efficiont at all !!
// XXX This not efficient at all !!
for ( int i = 0; i < length; ++i )
{
mData.append( getchar() );
Expand Down
14 changes: 0 additions & 14 deletions src/server/qgsfcgiserverrequest.h
Expand Up @@ -42,18 +42,6 @@ class SERVER_EXPORT QgsFcgiServerRequest: public QgsServerRequest
*/
bool hasError() const { return mHasError; }

/**
* \returns the request url
*
* Overrides base implementation because FCGI is typically behind
* a proxy server and QGIS Server will see a rewritten QUERY_STRING.
* FCGI implementation stores the REQUEST_URI (which is the URL seen
* by the proxy before it gets rewritten) and returns it instead of
* the rewritten one.
*/
QUrl url() const override;


private:
void readData();

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

QByteArray mData;
bool mHasError = false;
//! Url before the server rewrite
QUrl mOriginalUrl;
};

#endif
11 changes: 11 additions & 0 deletions src/server/qgsserverrequest.cpp
Expand Up @@ -27,6 +27,7 @@ QgsServerRequest::QgsServerRequest( const QString &url, Method method, const Hea

QgsServerRequest::QgsServerRequest( const QUrl &url, Method method, const Headers &headers )
: mUrl( url )
, mOriginalUrl( url )
, mMethod( method )
, mHeaders( headers )
{
Expand Down Expand Up @@ -60,6 +61,16 @@ QUrl QgsServerRequest::url() const
return mUrl;
}

QUrl QgsServerRequest::originalUrl() const
{
return mOriginalUrl;
}

void QgsServerRequest::setOriginalUrl( const QUrl &url )
{
mOriginalUrl = url;
}

QgsServerRequest::Method QgsServerRequest::method() const
{
return mMethod;
Expand Down
32 changes: 27 additions & 5 deletions src/server/qgsserverrequest.h
Expand Up @@ -82,13 +82,12 @@ class SERVER_EXPORT QgsServerRequest
virtual ~QgsServerRequest() = default;

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

/**
* \returns the request method
Expand Down Expand Up @@ -159,13 +158,36 @@ class SERVER_EXPORT QgsServerRequest
*/
void setUrl( const QUrl &url );

/**
* Returns the request url as seen by the web server,
* by default this is equal to the url seen by QGIS server
*
* \see url() for the rewritten url
* \since QGIS 3.6
*/
QUrl originalUrl() const;

/**
* Set the request method
*/
void setMethod( QgsServerRequest::Method method );

protected:

/**
* Set the request original \a url (the request url as seen by the web server)
*
* \see setUrl() for the rewritten url
* \since QGIS 3.6
*/
void setOriginalUrl( const QUrl &url );


private:
// Url as seen by QGIS server after web server rewrite
QUrl mUrl;
// Unrewritten url as seen by the web server
QUrl mOriginalUrl;
Method mMethod = GetMethod;
// We mark as mutable in order
// to support lazy initialization
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wcs/qgswcsutils.cpp
Expand Up @@ -250,7 +250,7 @@ namespace QgsWcs
// Build default url
if ( href.isEmpty() )
{
QUrl url = request.url();
QUrl url = request.originalUrl();
QUrlQuery q( url );

for ( auto param : q.queryItems() )
Expand Down
30 changes: 19 additions & 11 deletions src/server/services/wfs/qgswfsutils.cpp
Expand Up @@ -37,28 +37,36 @@ namespace QgsWfs

QString serviceUrl( const QgsServerRequest &request, const QgsProject *project )
{
QString href;
QUrl href;
if ( project )
{
href = QgsServerProjectUtils::wfsServiceUrl( *project );
href.setUrl( QgsServerProjectUtils::wfsServiceUrl( *project ) );
}

// Build default url
if ( href.isEmpty() )
{
QUrl url = request.url();

QgsWfsParameters params;
params.load( QUrlQuery( url ) );
params.remove( QgsServerParameter::REQUEST );
params.remove( QgsServerParameter::VERSION_SERVICE );
params.remove( QgsServerParameter::SERVICE );
static QSet<QString> sFilter
{
QStringLiteral( "REQUEST" ),
QStringLiteral( "VERSION" ),
QStringLiteral( "SERVICE" ),
};

href = request.originalUrl();
QUrlQuery q( href );

for ( auto param : q.queryItems() )
{
if ( sFilter.contains( param.first.toUpper() ) )
q.removeAllQueryItems( param.first );
}

url.setQuery( params.urlQuery() );
href = url.toString();
href.setQuery( q );
}

return href;
return href.toString();
}

QString layerTypeName( const QgsMapLayer *layer )
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wms/qgswmsutils.cpp
Expand Up @@ -56,7 +56,7 @@ namespace QgsWms
QStringLiteral( "_DC" )
};

href = request.url();
href = request.originalUrl();
QUrlQuery q( href );

for ( auto param : q.queryItems() )
Expand Down
2 changes: 1 addition & 1 deletion src/server/services/wmts/qgswmtsutils.cpp
Expand Up @@ -64,7 +64,7 @@ namespace QgsWmts
// Build default url
if ( href.isEmpty() )
{
QUrl url = request.url();
QUrl url = request.originalUrl();

QgsWmtsParameters params;
params.load( QUrlQuery( url ) );
Expand Down

0 comments on commit 823f2dd

Please sign in to comment.