Skip to content

Commit

Permalink
Support requests with http post. Up to now, only SOAP requests over H…
Browse files Browse the repository at this point in the history
…TTP POST have been supported
  • Loading branch information
Marco Hugentobler committed Jun 18, 2011
1 parent d750abf commit 783b30e
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 340 deletions.
1 change: 1 addition & 0 deletions src/mapserver/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SET ( qgis_mapserv_SRCS
qgsprojectparser.cpp
qgshttprequesthandler.cpp
qgsgetrequesthandler.cpp
qgspostrequesthandler.cpp
qgssoaprequesthandler.cpp
qgssldparser.cpp
qgssldrenderer.cpp
Expand Down
6 changes: 4 additions & 2 deletions src/mapserver/qgis_map_serv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ map service syntax for SOAP/HTTP POST
#include "qgscapabilitiescache.h"
#include "qgsconfigcache.h"
#include "qgsgetrequesthandler.h"
#include "qgspostrequesthandler.h"
#include "qgssoaprequesthandler.h"
#include "qgsproviderregistry.h"
#include "qgslogger.h"
Expand Down Expand Up @@ -206,8 +207,9 @@ int main( int argc, char * argv[] )
{
if ( strcmp( requestMethod, "POST" ) == 0 )
{
QgsDebugMsg( "Creating QgsSOAPRequestHandler" );
theRequestHandler = new QgsSOAPRequestHandler();
//QgsDebugMsg( "Creating QgsSOAPRequestHandler" );
//theRequestHandler = new QgsSOAPRequestHandler();
theRequestHandler = new QgsPostRequestHandler();
}
else
{
Expand Down
290 changes: 4 additions & 286 deletions src/mapserver/qgsgetrequesthandler.cpp
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
#include "qgsgetrequesthandler.h"
#include "qgsftptransaction.h"
#include "qgslogger.h"
#include "qgsmapserviceexception.h"
#include "qgsremotedatasourcebuilder.h"
#include "qgshttptransaction.h"
#include <QBuffer>
#include <QDomDocument>
#include <QFile>
#include <QTextStream>
#include <QImage>
#include <QStringList>
#include <QUrl>
#include <stdlib.h>

QgsGetRequestHandler::QgsGetRequestHandler(): QgsHttpRequestHandler()
{
}

std::map<QString, QString> QgsGetRequestHandler::parseInput()
{
std::map<QString, QString> parameters;
QString queryString;
std::map<QString, QString> parameters;

const char* qs = getenv( "QUERY_STRING" );
if ( qs )
{
Expand All @@ -32,282 +26,6 @@ std::map<QString, QString> QgsGetRequestHandler::parseInput()
return parameters; //no query string? something must be wrong...
}

//parameters are separated by &
QStringList elements = queryString.split( "&" );

QString element, key, value;

//insert key and value into the map
for ( QStringList::const_iterator it = elements.begin(); it != elements.end(); ++it )
{
element = *it;
int sepidx = element.indexOf( "=", 0, Qt::CaseSensitive );
if ( sepidx == -1 )
{
continue;
}

key = element.left( sepidx );
value = element.mid( sepidx + 1 );
value = QUrl::fromPercentEncoding( value.toLocal8Bit() ); //replace encoded special caracters and utf-8 encodings


if ( key.compare( "SLD_BODY", Qt::CaseInsensitive ) == 0 )
{
key = "SLD";
}
else if ( key.compare( "SLD", Qt::CaseInsensitive ) == 0 )
{
QByteArray fileContents;
if ( value.startsWith( "http", Qt::CaseInsensitive ) )
{
QgsHttpTransaction http( value );
if ( !http.getSynchronously( fileContents ) )
{
continue;
}
}
else if ( value.startsWith( "ftp", Qt::CaseInsensitive ) )
{
QgsFtpTransaction ftp;
if ( !ftp.get( value, fileContents ) )
{
continue;
}
value = QUrl::fromPercentEncoding( fileContents );
}
else
{
continue; //only http and ftp supported at the moment
}
value = QUrl::fromPercentEncoding( fileContents );

}
parameters.insert( std::make_pair( key.toUpper(), value ) );
QgsDebugMsg( "inserting pair " + key.toUpper() + " // " + value + " into the parameter map" );
}

//feature info format?
std::map<QString, QString>::const_iterator info_format_it = parameters.find( "INFO_FORMAT" );
if ( info_format_it != parameters.end() )
{
mFormat = info_format_it->second;
}
else //capabilities format or GetMap format
{
std::map<QString, QString>::const_iterator formatIt = parameters.find( "FORMAT" );
if ( formatIt != parameters.end() )
{
QString formatString = formatIt->second;

QgsDebugMsg( QString( "formatString is: %1" ).arg( formatString ) );

//remove the image/ in front of the format
if ( formatString.compare( "image/png", Qt::CaseInsensitive ) == 0 || formatString.compare( "png", Qt::CaseInsensitive ) == 0 )
{
formatString = "PNG";
}
else if ( formatString.compare( "image/jpeg", Qt::CaseInsensitive ) == 0 || formatString.compare( "image/jpg", Qt::CaseInsensitive ) == 0 \
|| formatString.compare( "jpg", Qt::CaseInsensitive ) == 0 )
{
formatString = "JPG";
}
else if ( formatString.compare( "svg", Qt::CaseInsensitive ) == 0 )
{
formatString = "SVG";
}
else if ( formatString.compare( "pdf", Qt::CaseInsensitive ) == 0 )
{
formatString = "PDF";
}

mFormat = formatString;
}
}


requestStringToParameterMap( queryString, parameters );
return parameters;
}

void QgsGetRequestHandler::sendGetMapResponse( const QString& service, QImage* img ) const
{
Q_UNUSED( service );
if ( img )
{
if ( mFormat != "PNG" && mFormat != "JPG" )
{
sendServiceException( QgsMapServiceException( "InvalidFormat", "Output format '" + mFormat + "' is not supported in the GetMap request" ) );
return;
}

//store the image in a QByteArray and send it directly
QByteArray ba;
QBuffer buffer( &ba );
buffer.open( QIODevice::WriteOnly );
img->save( &buffer, mFormat.toLocal8Bit().data(), -1 );

sendHttpResponse( &ba, formatToMimeType( mFormat ) );
}
}

void QgsGetRequestHandler::sendGetCapabilitiesResponse( const QDomDocument& doc ) const
{
QByteArray ba = doc.toByteArray();
sendHttpResponse( &ba, "text/xml" );
}

void QgsGetRequestHandler::sendGetStyleResponse( const QDomDocument& doc ) const
{
QByteArray ba = doc.toByteArray();
sendHttpResponse( &ba, "text/xml" );
}

void QgsGetRequestHandler::sendGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) const
{
QByteArray ba;
QgsDebugMsg( "Info format is:" + infoFormat );

if ( infoFormat == "text/xml" )
{
ba = infoDoc.toByteArray();
}
else if ( infoFormat == "text/plain" || infoFormat == "text/html" )
{
//create string
QString featureInfoString;

if ( infoFormat == "text/plain" )
{
featureInfoString.append( "GetFeatureInfo results\n" );
featureInfoString.append( "\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "<HEAD>\n" );
featureInfoString.append( "<TITLE> GetFeatureInfo results </TITLE>\n" );
featureInfoString.append( "<meta http-equiv=\"Content-Type\" content=\"text/html;charset=utf-8\">\n" );
featureInfoString.append( "</HEAD>\n" );
featureInfoString.append( "<BODY>\n" );
}

QDomNodeList layerList = infoDoc.elementsByTagName( "Layer" );

//layer loop
for ( int i = 0; i < layerList.size(); ++i )
{
QDomElement layerElem = layerList.at( i ).toElement();
if ( infoFormat == "text/plain" )
{
featureInfoString.append( "Layer '" + layerElem.attribute( "name" ) + "'\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
featureInfoString.append( "<TR><TH width=25%>Layer</TH><TD>" + layerElem.attribute( "name" ) + "</TD></TR>\n" );
featureInfoString.append( "</BR>" );
}

//feature loop (for vector layers)
QDomNodeList featureNodeList = layerElem.elementsByTagName( "Feature" );
QDomElement currentFeatureElement;

if ( featureNodeList.size() < 1 ) //raster layer?
{
QDomNodeList attributeNodeList = layerElem.elementsByTagName( "Attribute" );
for ( int j = 0; j < attributeNodeList.size(); ++j )
{
QDomElement attributeElement = attributeNodeList.at( j ).toElement();
if ( infoFormat == "text/plain" )
{
featureInfoString.append( attributeElement.attribute( "name" ) + " = '" +
attributeElement.attribute( "value" ) + "'\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( "name" ) + "</TH><TD>" +
attributeElement.attribute( "value" ) + "</TD></TR>\n" );
}
}
}
else //vector layer
{
for ( int j = 0; j < featureNodeList.size(); ++j )
{
QDomElement featureElement = featureNodeList.at( j ).toElement();
if ( infoFormat == "text/plain" )
{
featureInfoString.append( "Feature " + featureElement.attribute( "id" ) + "\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "<TABLE border=1 width=100%>\n" );
featureInfoString.append( "<TR><TH>Feature</TH><TD>" + featureElement.attribute( "id" ) + "</TD></TR>\n" );
}
//attribute loop
QDomNodeList attributeNodeList = featureElement.elementsByTagName( "Attribute" );
for ( int k = 0; k < attributeNodeList.size(); ++k )
{
QDomElement attributeElement = attributeNodeList.at( k ).toElement();
if ( infoFormat == "text/plain" )
{
featureInfoString.append( attributeElement.attribute( "name" ) + " = '" +
attributeElement.attribute( "value" ) + "'\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "<TR><TH>" + attributeElement.attribute( "name" ) + "</TH><TD>" + attributeElement.attribute( "value" ) + "</TD></TR>\n" );
}
}

if ( infoFormat == "text/html" )
{
featureInfoString.append( "</TABLE>\n</BR>\n" );
}
}
}
if ( infoFormat == "text/plain" )
{
featureInfoString.append( "\n" );
}
else if ( infoFormat == "text/html" )
{
featureInfoString.append( "</TABLE>\n<BR></BR>\n" );

}
}
if ( infoFormat == "text/html" )
{
featureInfoString.append( "</BODY>\n" );
}
ba = featureInfoString.toUtf8();
}
else //unsupported format, send exception
{
//todo: send service exception
}

sendHttpResponse( &ba, infoFormat );
}

void QgsGetRequestHandler::sendServiceException( const QgsMapServiceException& ex ) const
{
//create Exception DOM document
QDomDocument exceptionDoc;
QDomElement serviceExceptionReportElem = exceptionDoc.createElement( "ServiceExceptionReport" );
serviceExceptionReportElem.setAttribute( "version", "1.3.0" );
serviceExceptionReportElem.setAttribute( "xmlns", "http://www.opengis.net/ogc" );
exceptionDoc.appendChild( serviceExceptionReportElem );
QDomElement serviceExceptionElem = exceptionDoc.createElement( "ServiceException" );
serviceExceptionElem.setAttribute( "code", ex.code() );
QDomText messageText = exceptionDoc.createTextNode( ex.message() );
serviceExceptionElem.appendChild( messageText );
serviceExceptionReportElem.appendChild( serviceExceptionElem );

QByteArray ba = exceptionDoc.toByteArray();
sendHttpResponse( &ba, "text/xml" );
}

void QgsGetRequestHandler::sendGetPrintResponse( QByteArray* ba ) const
{
sendHttpResponse( ba, formatToMimeType( mFormat ) );
}
7 changes: 0 additions & 7 deletions src/mapserver/qgsgetrequesthandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,4 @@ class QgsGetRequestHandler: public QgsHttpRequestHandler
public:
QgsGetRequestHandler();
std::map<QString, QString> parseInput();
/**Sends the image back (but does not delete it)*/
void sendGetMapResponse( const QString& service, QImage* img ) const;
void sendGetCapabilitiesResponse( const QDomDocument& doc ) const;
void sendGetFeatureInfoResponse( const QDomDocument& infoDoc, const QString& infoFormat ) const;
void sendServiceException( const QgsMapServiceException& ex ) const;
void sendGetStyleResponse( const QDomDocument& doc ) const;
void sendGetPrintResponse( QByteArray* ba ) const;
};
Loading

0 comments on commit 783b30e

Please sign in to comment.