QGIS API Documentation  3.23.0-Master (dd0cd13a00)
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  const 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 }
static QString version()
Version string.
Definition: qgis.cpp:285
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.
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.
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.