QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsfcgiserverresponse.cpp
Go to the documentation of this file.
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 "qgis.h"
21 #include "qgsfcgiserverresponse.h"
22 #include "qgsmessagelog.h"
23 #include <fcgi_stdio.h>
24 #include <QDebug>
25 
26 //
27 // QgsFcgiServerResponse
28 //
29 
31  : mMethod( method )
32 {
33  mBuffer.open( QIODevice::ReadWrite );
35 }
36 
37 void QgsFcgiServerResponse::removeHeader( const QString &key )
38 {
39  mHeaders.remove( key );
40 }
41 
42 void QgsFcgiServerResponse::setHeader( const QString &key, const QString &value )
43 {
44  mHeaders.insert( key, value );
45 }
46 
47 QString QgsFcgiServerResponse::header( const QString &key ) const
48 {
49  return mHeaders.value( key );
50 }
51 
53 {
54  return mHeadersSent;
55 }
56 
58 {
59  // fcgi applications must return HTTP status in header
60  mHeaders.insert( QStringLiteral( "Status" ), QStringLiteral( " %1" ).arg( code ) );
61  // Store the code to make it available for plugins
62  mStatusCode = code;
63 }
64 
65 void QgsFcgiServerResponse::sendError( int code, const QString &message )
66 {
67  if ( mHeadersSent )
68  {
69  QgsMessageLog::logMessage( "Cannot send error after headers written" );
70  return;
71  }
72 
73  clear();
74  setStatusCode( code );
75  setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/html;charset=utf-8" ) );
76  write( QStringLiteral( "<html><body>%1</body></html>" ).arg( message ) );
77  finish();
78 }
79 
81 {
82  return &mBuffer;
83 }
84 
86 {
87  if ( mFinished )
88  {
89  QgsMessageLog::logMessage( "finish() called twice" );
90  return;
91  }
92 
93  if ( !mHeadersSent )
94  {
95  if ( ! mHeaders.contains( "Content-Length" ) )
96  {
97  mHeaders.insert( QStringLiteral( "Content-Length" ), QString::number( mBuffer.pos() ) );
98  }
99  }
100  flush();
101  mFinished = true;
102 }
103 
105 {
106  if ( ! mHeadersSent )
107  {
108  // Send all headers
109  QMap<QString, QString>::const_iterator it;
110  for ( it = mHeaders.constBegin(); it != mHeaders.constEnd(); ++it )
111  {
112  fputs( it.key().toUtf8(), FCGI_stdout );
113  fputs( ": ", FCGI_stdout );
114  fputs( it.value().toUtf8(), FCGI_stdout );
115  fputs( "\n", FCGI_stdout );
116  }
117  fputs( "\n", FCGI_stdout );
118  mHeadersSent = true;
119  }
120 
121  mBuffer.seek( 0 );
122  if ( mMethod == QgsServerRequest::HeadMethod )
123  {
124  // Ignore data for head method as we only
125  // write headers for HEAD requests
126  mBuffer.buffer().clear();
127  }
128  else if ( mBuffer.bytesAvailable() > 0 )
129  {
130  QByteArray &ba = mBuffer.buffer();
131  size_t count = fwrite( ( void * )ba.data(), ba.size(), 1, FCGI_stdout );
132 #ifdef QGISDEBUG
133  qDebug() << QStringLiteral( "Sent %1 blocks of %2 bytes" ).arg( count ).arg( ba.size() );
134 #else
135  Q_UNUSED( count )
136 #endif
137  // Reset the internal buffer
138  ba.clear();
139  }
140 }
141 
142 
144 {
145  mHeaders.clear();
146  mBuffer.seek( 0 );
147  mBuffer.buffer().clear();
148 
149  // Restore default headers
151 }
152 
153 
154 QByteArray QgsFcgiServerResponse::data() const
155 {
156  return mBuffer.data();
157 }
158 
159 
161 {
162  mBuffer.seek( 0 );
163  mBuffer.buffer().clear();
164 }
165 
166 
168 {
169  setHeader( QStringLiteral( "Server" ), QStringLiteral( " QGIS FCGI server - QGIS version %1" ).arg( Qgis::version() ) );
170 }
Qgis::version
static QString version()
Version string.
Definition: qgis.cpp:276
QgsFcgiServerResponse::io
QIODevice * io() override
Returns the underlying QIODevice.
Definition: qgsfcgiserverresponse.cpp:80
QgsFcgiServerResponse::setHeader
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...
Definition: qgsfcgiserverresponse.cpp:42
qgis.h
QgsFcgiServerResponse::headersSent
bool headersSent() const override
Returns true if the headers have already been sent.
Definition: qgsfcgiserverresponse.cpp:52
QgsFcgiServerResponse::sendError
void sendError(int code, const QString &message) override
Send error This method delegates error handling at the server level.
Definition: qgsfcgiserverresponse.cpp:65
QgsServerRequest::HeadMethod
@ HeadMethod
Definition: qgsserverrequest.h:52
QgsFcgiServerResponse::data
QByteArray data() const override
Gets the data written so far.
Definition: qgsfcgiserverresponse.cpp:154
QgsFcgiServerResponse::clear
void clear() override
Reset all headers and content for this response.
Definition: qgsfcgiserverresponse.cpp:143
QgsFcgiServerResponse::flush
void flush() override
Flushes the current output buffer to the network.
Definition: qgsfcgiserverresponse.cpp:104
QgsServerResponse::write
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
Definition: qgsserverresponse.cpp:25
QgsFcgiServerResponse::truncate
void truncate() override
Truncate data.
Definition: qgsfcgiserverresponse.cpp:160
QgsFcgiServerResponse::header
QString header(const QString &key) const override
Returns the header value.
Definition: qgsfcgiserverresponse.cpp:47
QgsFcgiServerResponse::QgsFcgiServerResponse
QgsFcgiServerResponse(QgsServerRequest::Method method=QgsServerRequest::GetMethod)
Constructor for QgsFcgiServerResponse.
Definition: qgsfcgiserverresponse.cpp:30
QgsFcgiServerResponse::removeHeader
void removeHeader(const QString &key) override
Clear header Undo a previous 'setHeader' call.
Definition: qgsfcgiserverresponse.cpp:37
qgsfcgiserverresponse.h
QgsFcgiServerResponse::setStatusCode
void setStatusCode(int code) override
Set the http status code.
Definition: qgsfcgiserverresponse.cpp:57
QgsMessageLog::logMessage
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Definition: qgsmessagelog.cpp:27
QgsServerRequest::Method
Method
HTTP Method (or equivalent) used for the request.
Definition: qgsserverrequest.h:51
QgsFcgiServerResponse::finish
void finish() override
Finish the response, ending the transaction.
Definition: qgsfcgiserverresponse.cpp:85
QgsFcgiServerResponse::setDefaultHeaders
void setDefaultHeaders()
Set the default headers.
Definition: qgsfcgiserverresponse.cpp:167
qgsmessagelog.h