Skip to content

Commit 64fc56c

Browse files
committedJan 10, 2017
Implement QgsFcgiRequest and QgsFcgiResponse
1 parent 891e163 commit 64fc56c

33 files changed

+1101
-595
lines changed
 

‎python/server/qgsrequesthandler.sip

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -66,32 +66,21 @@ class QgsRequestHandler
6666
//! @note not available in Python bindings
6767
virtual void setGetCoverageResponse( QByteArray* ba ) = 0;
6868

69-
virtual void setDefaultHeaders();
70-
7169
/** Set an HTTP header*/
7270
virtual void setHeader( const QString &name, const QString &value ) = 0;
7371

7472
/** Remove an HTTP header*/
75-
virtual int removeHeader( const QString &name ) = 0;
73+
virtual void removeHeader( const QString &name ) = 0;
7674

7775
/** Delete all HTTP headers*/
78-
virtual void clearHeaders() = 0;
76+
virtual void clear() = 0;
7977

8078
/** Append the bytestream to response body*/
8179
virtual void appendBody( const QByteArray &body ) = 0;
8280

83-
/** Clears the response body*/
84-
virtual void clearBody() = 0;
85-
86-
/** Return the response body*/
87-
virtual QByteArray body();
88-
8981
/** Set the info format string such as "text/xml"*/
9082
virtual void setInfoFormat( const QString &format ) = 0;
9183

92-
/** Check whether there is any header set or the body is not empty*/
93-
virtual bool responseReady() const = 0;
94-
9584
/** Send out HTTP headers and flush output buffer*/
9685
virtual void sendResponse() = 0;
9786

‎python/server/qgsserver.sip

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ class QgsServer
165165
/** Creates the server instance
166166
* @param captureOutput set to false for stdout output (FCGI)
167167
*/
168-
QgsServer( bool captureOutput = true );
168+
QgsServer();
169169
~QgsServer();
170170

171171
/** Set environment variable
@@ -175,22 +175,25 @@ class QgsServer
175175
*/
176176
void putenv( const QString &var, const QString &val );
177177

178-
/** Handles the request. The output is normally printed trough FCGI printf
179-
* by the request handler or, in case the server has been invoked from python
180-
* bindings, a flag is set that captures all the output headers and body, instead
181-
* of printing it returns the output as a QPair of QByteArray.
178+
/** Handles the request.
182179
* The query string is normally read from environment
183180
* but can be also passed in args and in this case overrides the environment
184181
* variable
185182
*
186-
* @param queryString optional QString containing the query string
187-
* @return the response headers and body QPair of QByteArray if called from python bindings, empty otherwise
183+
* @param request a QgsServerRequest holding request parameters
184+
* @param response a QgsServerResponse for handling response I/O)
188185
*/
189-
QPair<QByteArray, QByteArray> handleRequest( const QString& queryString = QString() );
190-
/*
191-
// The following code was used to test type conversion in python bindings
192-
QPair<QByteArray, QByteArray> testQPair( QPair<QByteArray, QByteArray> pair );
193-
*/
186+
void handleRequest( const QgsServerRequest& request, QgsServerResponse& response );
187+
188+
/** Handles the request from query strinf
189+
* The query string is normally read from environment
190+
* but can be also passed in args and in this case overrides the environment
191+
* variable.
192+
*
193+
* @param queryString QString containing the query string
194+
* @return the response headers and body QPair of QByteArray
195+
*/
196+
QPair<QByteArray, QByteArray> handleRequest( const QString& queryString );
194197

195198
/** Returns a pointer to the server interface */
196199
QgsServerInterface* serverInterface();

‎python/server/qgsserverrequest.sip

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ class QgsServerRequest
3535
HeadMethod, PutMethod, GetMethod, PostMethod, DeleteMethod
3636
};
3737

38+
/**
39+
* Constructor
40+
*/
41+
QgsServerRequest();
42+
3843
/**
3944
* Constructor
4045
*
@@ -81,5 +86,15 @@ class QgsServerRequest
8186
*/
8287
virtual QByteArray data() const;
8388

89+
/**
90+
* Set the request url
91+
*/
92+
void setUrl( const QUrl& url );
93+
94+
/**
95+
* Set the request method
96+
*/
97+
void setMethod( Method method );
98+
8499
};
85100

‎python/server/qgsserverresponse.sip

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ class QgsServerResponse
4242
*/
4343
virtual void setHeader( const QString& key, const QString& value ) = 0;
4444

45+
/**
46+
* Clear header
47+
* Undo a previous 'set_header' call
48+
*/
49+
virtual void clearHeader( const QString& key ) = 0;
50+
51+
4552
/** Set the http return code
4653
* @param code HTTP return code value
4754
*/
@@ -76,5 +83,23 @@ class QgsServerResponse
7683
*/
7784
virtual QIODevice* io() = 0;
7885

86+
/**
87+
* End the transaction
88+
*/
89+
virtual void finish() = 0;
90+
91+
/**
92+
* Flushes the current output buffer to the network
93+
*
94+
* 'flush()' may be called multiple times. For HTTP transactions
95+
* headers will be written on the first call to 'flush()'.
96+
*/
97+
virtual void flush() = 0;
98+
99+
/**
100+
* Reset all headers and content for this response
101+
*/
102+
virtual void clear() = 0;
103+
79104
};
80105

‎src/server/CMakeLists.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ SET ( qgis_mapserv_SRCS
2424
qgscapabilitiescache.cpp
2525
qgsconfigcache.cpp
2626
qgshttprequesthandler.cpp
27-
# qgshttptransaction.cpp
28-
qgsgetrequesthandler.cpp
29-
qgspostrequesthandler.cpp
3027
qgsowsserver.cpp
3128
qgswmsserver.cpp
3229
qgswfsserver.cpp
@@ -57,6 +54,8 @@ SET ( qgis_mapserv_SRCS
5754
qgsserviceregistry.cpp
5855
qgsserverrequest.cpp
5956
qgsserverresponse.cpp
57+
qgsfcgiserverresponse.cpp
58+
qgsbufferserverresponse.cpp
6059
#----------------------------
6160
)
6261
IF("${Qt5Network_VERSION}" VERSION_LESS "5.0.0")

‎src/server/qgis_map_serv.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
//for CMAKE_INSTALL_PREFIX
2020
#include "qgsconfig.h"
2121
#include "qgsserver.h"
22+
#include "qgsfcgiserverresponse.h"
2223

2324
#include <fcgi_stdio.h>
2425
#include <stdlib.h>
@@ -38,14 +39,23 @@ int fcgi_accept()
3839
int main( int argc, char * argv[] )
3940
{
4041
QgsApplication app( argc, argv, getenv( "DISPLAY" ), QString(), QStringLiteral( "server" ) );
41-
QgsServer server( false );
42+
QgsServer server;
4243
#ifdef HAVE_SERVER_PYTHON_PLUGINS
4344
server.initPython();
4445
#endif
4546
// Starts FCGI loop
4647
while ( fcgi_accept() >= 0 )
4748
{
48-
server.handleRequest();
49+
QgsFcgiServerRequest request;
50+
QgsFcgiServerResponse response( request.method() );
51+
if ( ! request.hasError() )
52+
{
53+
server.handleRequest( request, response );
54+
}
55+
else
56+
{
57+
response.sendError( 400, "Bad request" );
58+
}
4959
}
5060
app.exitQgis();
5161
return 0;
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
/***************************************************************************
2+
qgsfcgiserverresponse.cpp
3+
4+
Define response wrapper for fcgi response
5+
-------------------
6+
begin : 2017-01-03
7+
copyright : (C) 2017 by David Marteau
8+
email : david dot marteau at 3liz dot com
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 "qgsbufferserverresponse.h"
21+
#include "qgslogger.h"
22+
#include "qgsmessagelog.h"
23+
24+
#include <QDebug>
25+
26+
//
27+
// QgsBufferServerResponse
28+
//
29+
30+
QgsBufferServerResponse::QgsBufferServerResponse()
31+
{
32+
mBuffer.open( QIODevice::ReadWrite );
33+
mHeadersWritten = false;
34+
mFinished = false;
35+
mReturnCode = 200;
36+
}
37+
38+
QgsBufferServerResponse::~QgsBufferServerResponse()
39+
{
40+
41+
}
42+
43+
void QgsBufferServerResponse::clearHeader( const QString& key )
44+
{
45+
if ( !mHeadersWritten )
46+
mHeaders.remove( key );
47+
}
48+
49+
void QgsBufferServerResponse::setHeader( const QString& key, const QString& value )
50+
{
51+
if ( ! mHeadersWritten )
52+
mHeaders.insert( key, value );
53+
}
54+
55+
void QgsBufferServerResponse::setReturnCode( int code )
56+
{
57+
mReturnCode = code;
58+
}
59+
60+
void QgsBufferServerResponse::sendError( int code, const QString& message )
61+
{
62+
if ( mHeadersWritten )
63+
{
64+
QgsMessageLog::logMessage( "Cannot send error after headers written" );
65+
return;
66+
}
67+
68+
clear();
69+
setReturnCode( code );
70+
setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/plain; charset=utf-8" ) );
71+
write( message );
72+
finish();
73+
}
74+
75+
QIODevice* QgsBufferServerResponse::io()
76+
{
77+
return &mBuffer;
78+
}
79+
80+
void QgsBufferServerResponse::finish()
81+
{
82+
if ( mFinished )
83+
{
84+
QgsMessageLog::logMessage( "finish() called twice" );
85+
return;
86+
}
87+
88+
if ( !mHeadersWritten )
89+
{
90+
if ( ! mHeaders.contains( "Content-Length" ) )
91+
{
92+
mHeaders.insert( QStringLiteral( "Content-Length" ), QStringLiteral( "%1" ).arg( mBuffer.pos() ) );
93+
}
94+
}
95+
flush();
96+
mFinished = true;
97+
}
98+
99+
void QgsBufferServerResponse::flush()
100+
{
101+
if ( ! mHeadersWritten )
102+
{
103+
mHeadersWritten = true;
104+
}
105+
106+
mBuffer.seek( 0 );
107+
QByteArray& ba = mBuffer.buffer();
108+
mBody.append( ba );
109+
ba.clear();
110+
}
111+
112+
113+
void QgsBufferServerResponse::clear()
114+
{
115+
if ( !mHeadersWritten )
116+
mHeaders.clear();
117+
118+
mBuffer.seek( 0 );
119+
mBuffer.buffer().clear();
120+
}
121+
122+
123+
//QgsBufferServerRequest
124+
//
125+
QgsBufferServerRequest::QgsBufferServerRequest( const QString& url, Method method, QByteArray* data )
126+
: QgsServerRequest( url, method )
127+
{
128+
if ( data )
129+
{
130+
mData = *data;
131+
}
132+
}
133+
134+
QgsBufferServerRequest::QgsBufferServerRequest( const QUrl& url, Method method, QByteArray* data )
135+
: QgsServerRequest( url, method )
136+
{
137+
if ( data )
138+
{
139+
mData = *data;
140+
}
141+
}
142+
143+
QgsBufferServerRequest::~QgsBufferServerRequest()
144+
{
145+
}
146+
147+
148+

0 commit comments

Comments
 (0)
Please sign in to comment.