22#include "moc_qgsfcgiserverresponse.cpp"
24#include <fcgi_stdio.h>
29#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
31#include <sys/socket.h>
36typedef struct QgsFCGXStreamData
41 unsigned char *buffStop;
51 int isAnythingWritten;
53 FCGX_Request *reqDataPtr;
58 : mIsResponseFinished( isResponseFinished )
59 , mFeedback( feedback )
62 setObjectName(
"FCGI socket monitor" );
63 Q_ASSERT( mIsResponseFinished );
64 Q_ASSERT( mFeedback );
66#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
67 if ( FCGI_stdout && FCGI_stdout->fcgx_stream && FCGI_stdout->fcgx_stream->data )
69 QgsFCGXStreamData *stream =
static_cast<QgsFCGXStreamData *
>( FCGI_stdin->fcgx_stream->data );
70 if ( stream && stream->reqDataPtr )
72 mIpcFd = stream->reqDataPtr->ipcFd;
77 QStringLiteral(
"FCGIServer" ),
84 QStringLiteral(
"FCGIServer" ),
95 QStringLiteral(
"FCGIServer" ),
100#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
102 while ( !*mIsResponseFinished )
104 const ssize_t x = recv( mIpcFd, &
c, 1, MSG_PEEK | MSG_DONTWAIT );
108 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer: remote socket still connected. errno: %1" ).arg( errno ), 5 );
113 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer: remote socket has been closed! errno: %1" ).arg( errno ), 2 );
118 QThread::msleep( 333L );
121 if ( *mIsResponseFinished )
123 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer: socket monitoring quits normally." ), 2 );
127 QgsDebugMsgLevel( QStringLiteral(
"FCGIServer: socket monitoring quits: no more socket." ), 2 );
141 mBuffer.open( QIODevice::ReadWrite );
144 mSocketMonitoringThread = std::make_unique<QgsSocketMonitoringThread>( &mFinished, mFeedback.get() );
145 mSocketMonitoringThread->start();
151 mSocketMonitoringThread->exit();
152 mSocketMonitoringThread->wait();
157 mHeaders.remove( key );
162 mHeaders.insert( key, value );
167 return mHeaders.value( key );
178 mHeaders.insert( QStringLiteral(
"Status" ), QStringLiteral(
" %1" ).arg( code ) );
188 QStringLiteral(
"FCGIServer" ),
195 setHeader( QStringLiteral(
"Content-Type" ), QStringLiteral(
"text/html;charset=utf-8" ) );
196 write( QStringLiteral(
"<html><body>%1</body></html>" ).arg( message ) );
210 QStringLiteral(
"FCGIServer" ),
215 if ( mFeedback->isCanceled() )
218 FCGI_stdout->fcgx_stream->wasFCloseCalled =
true;
225 if ( ! mHeaders.contains(
"Content-Length" ) )
227 mHeaders.insert( QStringLiteral(
"Content-Length" ), QString::number( mBuffer.pos() ) );
236 if ( ! mHeadersSent )
239 QMap<QString, QString>::const_iterator it;
240 for ( it = mHeaders.constBegin(); it != mHeaders.constEnd(); ++it )
242 fputs( it.key().toUtf8(), FCGI_stdout );
243 fputs(
": ", FCGI_stdout );
244 fputs( it.value().toUtf8(), FCGI_stdout );
245 fputs(
"\n", FCGI_stdout );
247 fputs(
"\n", FCGI_stdout );
256 mBuffer.buffer().clear();
258 else if ( mBuffer.bytesAvailable() > 0 )
260 QByteArray &ba = mBuffer.buffer();
261 const size_t count = fwrite( (
void * )ba.data(), ba.size(), 1, FCGI_stdout );
263 qDebug() << QStringLiteral(
"Sent %1 blocks of %2 bytes" ).arg( count ).arg( ba.size() );
277 mBuffer.buffer().clear();
286 return mBuffer.data();
293 mBuffer.buffer().clear();
299 setHeader( 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()
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.
void cancel()
Tells the internal routines that the current operation should be canceled. This should be run by the ...
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).
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.
QgsSocketMonitoringThread(bool *isResponseFinished, QgsFeedback *feedback)
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)