22#include "moc_qgsfcgiserverresponse.cpp"
24#include <fcgi_stdio.h>
29#if defined( Q_OS_UNIX ) && !defined( Q_OS_ANDROID )
32#include <sys/socket.h>
38typedef struct QgsFCGXStreamData
43 unsigned char *buffStop;
53 int isAnythingWritten;
55 FCGX_Request *reqDataPtr;
60using namespace std::chrono_literals;
65 : mFeedback( feedback )
68 Q_ASSERT( mFeedback );
70 mShouldStop.store(
false );
72#if defined( Q_OS_UNIX ) && !defined( Q_OS_ANDROID )
73 if ( FCGI_stdout && FCGI_stdout->fcgx_stream && FCGI_stdout->fcgx_stream->data )
75 QgsFCGXStreamData *stream =
static_cast<QgsFCGXStreamData *
>( FCGI_stdout->fcgx_stream->data );
76 if ( stream && stream->reqDataPtr )
78 mIpcFd = stream->reqDataPtr->ipcFd;
83 QStringLiteral(
"FCGIServer" ),
90 QStringLiteral(
"FCGIServer" ),
99 mShouldStop.store(
true );
116#if defined( Q_OS_UNIX ) && !defined( Q_OS_ANDROID )
117 const pid_t threadId = gettid();
119 mShouldStop.store(
false );
123 FD_ZERO( &setOptions );
124 FD_SET( mIpcFd, &setOptions );
126 struct timeval timeout;
128 timeout.tv_usec = 10000;
130 while ( !mShouldStop.load() )
134 int rv = select( mIpcFd + 1, &setOptions, NULL, NULL, &timeout );
149 const ssize_t x = recv( mIpcFd, &
c, 1, MSG_PEEK | MSG_DONTWAIT );
153 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer %1: remote socket still connected. errno: %2, x: %3" )
174 if ( mMutex.try_lock_for( 333ms ) )
178 if ( mShouldStop.load() )
180 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer::run %1: socket monitoring quits normally." ).arg( threadId ), 2 );
199 mBuffer.open( QIODevice::ReadWrite );
202 mSocketMonitoringThread = std::make_unique<QgsSocketMonitoringThread>( mFeedback );
213 mSocketMonitoringThread->stop();
221 mHeaders.remove( key );
226 mHeaders.insert( key, value );
231 return mHeaders.value( key );
242 mHeaders.insert( QStringLiteral(
"Status" ), QStringLiteral(
" %1" ).arg( code ) );
257 setHeader( QStringLiteral(
"Content-Type" ), QStringLiteral(
"text/html;charset=utf-8" ) );
258 write( QStringLiteral(
"<html><body>%1</body></html>" ).arg( message ) );
275 if ( mFeedback->isCanceled() )
278 FCGI_stdout->fcgx_stream->wasFCloseCalled =
true;
285 if ( !mHeaders.contains(
"Content-Length" ) )
287 mHeaders.insert( QStringLiteral(
"Content-Length" ), QString::number( mBuffer.pos() ) );
299 QMap<QString, QString>::const_iterator it;
300 for ( it = mHeaders.constBegin(); it != mHeaders.constEnd(); ++it )
302 fputs( it.key().toUtf8(), FCGI_stdout );
303 fputs(
": ", FCGI_stdout );
304 fputs( it.value().toUtf8(), FCGI_stdout );
305 fputs(
"\n", FCGI_stdout );
307 fputs(
"\n", FCGI_stdout );
316 mBuffer.buffer().clear();
318 else if ( mBuffer.bytesAvailable() > 0 )
320 QByteArray &ba = mBuffer.buffer();
321 const size_t count = fwrite( (
void * ) ba.data(), ba.size(), 1, FCGI_stdout );
323 qDebug() << QStringLiteral(
"Sent %1 blocks of %2 bytes" ).arg( count ).arg( ba.size() );
337 mBuffer.buffer().clear();
346 return mBuffer.data();
353 mBuffer.buffer().clear();
359 mHeaders.insert( QStringLiteral(
"Server" ), QStringLiteral(
" QGIS FCGI server - QGIS version %1" ).arg(
Qgis::version() ) );
static QString version()
Version string.
@ Warning
Warning message.
void setDefaultHeaders()
Set the default headers.
void clear() override
Reset all headers and content for this response.
void setHeader(const QString &key, const QString &value) override
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
void flush() override
Flushes the current output buffer to the network.
virtual ~QgsFcgiServerResponse() override
void removeHeader(const QString &key) override
Clear header Undo a previous 'setHeader' call.
QByteArray data() const override
Gets the data written so far.
QIODevice * io() override
Returns the underlying QIODevice.
bool headersSent() const override
Returns true if the headers have already been sent.
void setStatusCode(int code) override
Set the http status code.
QgsFcgiServerResponse(QgsServerRequest::Method method=QgsServerRequest::GetMethod)
Constructor for QgsFcgiServerResponse.
void sendError(int code, const QString &message) override
Send error This method delegates error handling at the server level.
void truncate() override
Truncate data.
void finish() override
Finish the response, ending the transaction.
QString header(const QString &key) const override
Returns the header value.
Base class for feedback objects to be used for cancellation of something running in a worker thread.
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).
Method
HTTP Method (or equivalent) used for the request.
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
void run()
main thread function
void stop()
Stop the thread.
QgsSocketMonitoringThread(std::shared_ptr< QgsFeedback > feedback)
Constructor for QgsSocketMonitoringThread.
As part of the API refactoring and improvements which landed in the Processing API was substantially reworked from the x version This was done in order to allow much of the underlying Processing framework to be ported into c
#define QgsDebugMsgLevel(str, level)