QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
qgsserverogcapi.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsserverogcapi.cpp - QgsServerOgcApi
3
4 ---------------------
5 begin : 10.7.2019
6 copyright : (C) 2019 by Alessandro Pasotti
7 email : elpaso at itopen dot it
8 ***************************************************************************
9 * *
10 * This program is free software; you can redistribute it and/or modify *
11 * it under the terms of the GNU General Public License as published by *
12 * the Free Software Foundation; either version 2 of the License, or *
13 * (at your option) any later version. *
14 * *
15 ***************************************************************************/
16
17#include <QDir>
18#include <QDebug>
19#include <QtGlobal>
20
21#include "qgsserverogcapi.h"
22#include "moc_qgsserverogcapi.cpp"
24#include "qgsmessagelog.h"
25#include "qgsapplication.h"
26
27QMap<QgsServerOgcApi::ContentType, QStringList> QgsServerOgcApi::sContentTypeMime = []() -> QMap<QgsServerOgcApi::ContentType, QStringList> {
28 QMap<QgsServerOgcApi::ContentType, QStringList> map;
29 map[QgsServerOgcApi::ContentType::JSON] = QStringList { QStringLiteral( "application/json" ) };
30 map[QgsServerOgcApi::ContentType::GEOJSON] = QStringList {
31 QStringLiteral( "application/geo+json" ),
32 QStringLiteral( "application/vnd.geo+json" ),
33 QStringLiteral( "application/geojson" )
34 };
35 map[QgsServerOgcApi::ContentType::HTML] = QStringList { QStringLiteral( "text/html" ) };
36 map[QgsServerOgcApi::ContentType::OPENAPI3] = QStringList { QStringLiteral( "application/vnd.oai.openapi+json;version=3.0" ) };
37 map[QgsServerOgcApi::ContentType::XML] = QStringList { QStringLiteral( "application/xml" ) };
38 return map;
39}();
40
41QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> QgsServerOgcApi::sContentTypeAliases = []() -> QHash<ContentType, QList<ContentType>> {
42 QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> map;
44 return map;
45}();
46
47
48QgsServerOgcApi::QgsServerOgcApi( QgsServerInterface *serverIface, const QString &rootPath, const QString &name, const QString &description, const QString &version )
49 : QgsServerApi( serverIface ), mRootPath( rootPath ), mName( name ), mDescription( description ), mVersion( version )
50{
51}
52
54{
55 //qDebug() << "API destroyed: " << name();
56}
57
59{
60 std::shared_ptr<QgsServerOgcApiHandler> hp( handler );
61 mHandlers.emplace_back( std::move( hp ) );
62}
63
64QUrl QgsServerOgcApi::sanitizeUrl( const QUrl &url )
65{
66 // Since QT 5.12 NormalizePathSegments does not collapse double slashes
67 QUrl u { url.adjusted( QUrl::StripTrailingSlash | QUrl::NormalizePathSegments ) };
68 if ( u.path().contains( QLatin1String( "//" ) ) )
69 {
70 u.setPath( u.path().replace( QLatin1String( "//" ), QChar( '/' ) ) );
71 }
72 // Make sure the path starts with '/'
73 if ( !u.path().startsWith( '/' ) )
74 {
75 u.setPath( u.path().prepend( '/' ) );
76 }
77 return u;
78}
79
81{
82 // Get url
83 const auto path { sanitizeUrl( context.handlerPath() ).path() };
84 // Find matching handler
85 auto hasMatch { false };
86 for ( const auto &handler : mHandlers )
87 {
88 QgsMessageLog::logMessage( QStringLiteral( "Checking API path %1 for %2 " ).arg( path, handler->path().pattern() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
89 if ( handler->path().match( path ).hasMatch() )
90 {
91 hasMatch = true;
92 // Execute handler
93 QgsMessageLog::logMessage( QStringLiteral( "API %1: found handler %2" ).arg( name(), QString::fromStdString( handler->operationId() ) ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
94 // May throw QgsServerApiBadRequestException or JSON exceptions on serializing
95 try
96 {
97 handler->handleRequest( context );
98 }
99 catch ( json::exception &ex )
100 {
101 throw QgsServerApiInternalServerError( QStringLiteral( "The API handler returned an error: %1" ).arg( ex.what() ) );
102 }
103 break;
104 }
105 }
106 // Throw
107 if ( !hasMatch )
108 {
109 throw QgsServerApiBadRequestException( QStringLiteral( "Requested URI does not match any registered API handler" ) );
110 }
111}
112
113const QMap<QgsServerOgcApi::ContentType, QStringList> QgsServerOgcApi::contentTypeMimes()
114{
115 return sContentTypeMime;
116}
117
118const QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> QgsServerOgcApi::contentTypeAliases()
119{
120 return sContentTypeAliases;
121}
122
123std::string QgsServerOgcApi::relToString( const Rel &rel )
124{
125 static const QMetaEnum metaEnum = QMetaEnum::fromType<QgsServerOgcApi::Rel>();
126 std::string val { metaEnum.valueToKey( rel ) };
127 std::replace( val.begin(), val.end(), '_', '-' );
128 return val;
129}
130
132{
133 static const QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
134 QString result { metaEnum.valueToKey( ct ) };
135 return result.replace( '_', '-' );
136}
137
139{
140 static const QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
141 return metaEnum.valueToKey( ct );
142}
143
145{
146 return contentTypeToString( ct ).toLower();
147}
148
150{
151 const QString exts = QString::fromStdString( extension );
152 const auto constMimeTypes( QgsServerOgcApi::contentTypeMimes() );
153 for ( auto it = constMimeTypes.constBegin();
154 it != constMimeTypes.constEnd();
155 ++it )
156 {
157 const auto constValues = it.value();
158 for ( const auto &value : constValues )
159 {
160 if ( value.contains( exts, Qt::CaseSensitivity::CaseInsensitive ) )
161 {
162 return it.key();
163 }
164 }
165 }
166 // Default to JSON, but log a warning!
167 QgsMessageLog::logMessage( QStringLiteral( "Content type for extension %1 not found! Returning default (JSON)" ).arg( exts ), QStringLiteral( "Server" ), Qgis::MessageLevel::Warning );
169}
170
172{
173 if ( !sContentTypeMime.contains( contentType ) )
174 {
175 return "";
176 }
177 return sContentTypeMime.value( contentType ).first().toStdString();
178}
179
180const std::vector<std::shared_ptr<QgsServerOgcApiHandler>> QgsServerOgcApi::handlers() const
181{
182 return mHandlers;
183}
@ Warning
Warning message.
Definition qgis.h:156
@ Info
Information message.
Definition qgis.h:155
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).
Bad request error API exception.
The QgsServerApiContext class encapsulates the resources for a particular client request: the request...
QString handlerPath() const
Returns the handler component of the URL path, i.e.
Internal server error API exception.
Server generic API endpoint abstract base class.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins.
The QgsServerOgcApiHandler abstract class represents a OGC API handler to be registered in QgsServerO...
static QUrl sanitizeUrl(const QUrl &url)
Returns a sanitized url with extra slashes removed and the path URL component that always starts with...
virtual void executeRequest(const QgsServerApiContext &context) const override
Executes a request by passing the given context to the API handlers.
void registerHandler(Args... args)
Registers an OGC API handler passing Args to the constructor.
QgsServerOgcApi(QgsServerInterface *serverIface, const QString &rootPath, const QString &name, const QString &description=QString(), const QString &version=QString())
QgsServerOgcApi constructor.
static QString contentTypeToExtension(const QgsServerOgcApi::ContentType &ct)
Returns the file extension for a ct (Content-Type).
const std::vector< std::shared_ptr< QgsServerOgcApiHandler > > handlers() const
Returns registered handlers.
static const QMap< QgsServerOgcApi::ContentType, QStringList > contentTypeMimes()
Returns a map of contentType => list of mime types.
ContentType
Media types used for content negotiation, insert more specific first.
@ OPENAPI3
"application/openapi+json;version=3.0"
static QString contentTypeToString(const QgsServerOgcApi::ContentType &ct)
Returns the string representation of a ct (Content-Type) attribute.
Rel
Rel link types.
static std::string contentTypeToStdString(const QgsServerOgcApi::ContentType &ct)
Returns the string representation of a ct (Content-Type) attribute.
static std::string mimeType(const QgsServerOgcApi::ContentType &contentType)
Returns the mime-type for the contentType or an empty string if not found.
~QgsServerOgcApi() override
const QString name() const override
Returns the API name.
static std::string relToString(const QgsServerOgcApi::Rel &rel)
Returns the string representation of rel attribute.
static const QHash< QgsServerOgcApi::ContentType, QList< QgsServerOgcApi::ContentType > > contentTypeAliases()
Returns contentType specializations (e.g.
static QgsServerOgcApi::ContentType contentTypeFromExtension(const std::string &extension)
Returns the Content-Type value corresponding to extension.