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