QGIS API Documentation 3.41.0-Master (45a0abf3bec)
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{
29 QMap<QgsServerOgcApi::ContentType, QStringList> map;
30 map[QgsServerOgcApi::ContentType::JSON] = QStringList { QStringLiteral( "application/json" ) };
31 map[QgsServerOgcApi::ContentType::GEOJSON] = QStringList {
32 QStringLiteral( "application/geo+json" ),
33 QStringLiteral( "application/vnd.geo+json" ),
34 QStringLiteral( "application/geojson" )
35 };
36 map[QgsServerOgcApi::ContentType::HTML] = QStringList { QStringLiteral( "text/html" ) };
37 map[QgsServerOgcApi::ContentType::OPENAPI3] = QStringList { QStringLiteral( "application/vnd.oai.openapi+json;version=3.0" ) };
38 map[QgsServerOgcApi::ContentType::XML] = QStringList { QStringLiteral( "application/xml" ) };
39 return map;
40}();
41
42QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> QgsServerOgcApi::sContentTypeAliases = [ ]() -> QHash<ContentType, QList<ContentType>>
43{
44 QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> map;
46 return map;
47}();
48
49
50QgsServerOgcApi::QgsServerOgcApi( QgsServerInterface *serverIface, const QString &rootPath, const QString &name, const QString &description, const QString &version ):
51 QgsServerApi( serverIface ),
52 mRootPath( rootPath ),
53 mName( name ),
54 mDescription( description ),
55 mVersion( version )
56{
57
58}
59
61{
62 //qDebug() << "API destroyed: " << name();
63}
64
66{
67 std::shared_ptr<QgsServerOgcApiHandler> hp( handler );
68 mHandlers.emplace_back( std::move( hp ) );
69}
70
71QUrl QgsServerOgcApi::sanitizeUrl( const QUrl &url )
72{
73 // Since QT 5.12 NormalizePathSegments does not collapse double slashes
74 QUrl u { url.adjusted( QUrl::StripTrailingSlash | QUrl::NormalizePathSegments ) };
75 if ( u.path().contains( QLatin1String( "//" ) ) )
76 {
77 u.setPath( u.path().replace( QLatin1String( "//" ), QChar( '/' ) ) );
78 }
79 // Make sure the path starts with '/'
80 if ( !u.path().startsWith( '/' ) )
81 {
82 u.setPath( u.path().prepend( '/' ) );
83 }
84 return u;
85}
86
88{
89 // Get url
90 const auto path { sanitizeUrl( context.handlerPath( ) ).path() };
91 // Find matching handler
92 auto hasMatch { false };
93 for ( const auto &handler : mHandlers )
94 {
95 QgsMessageLog::logMessage( QStringLiteral( "Checking API path %1 for %2 " ).arg( path, handler->path().pattern() ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
96 if ( handler->path().match( path ).hasMatch() )
97 {
98 hasMatch = true;
99 // Execute handler
100 QgsMessageLog::logMessage( QStringLiteral( "API %1: found handler %2" ).arg( name(), QString::fromStdString( handler->operationId() ) ), QStringLiteral( "Server" ), Qgis::MessageLevel::Info );
101 // May throw QgsServerApiBadRequestException or JSON exceptions on serializing
102 try
103 {
104 handler->handleRequest( context );
105 }
106 catch ( json::exception &ex )
107 {
108 throw QgsServerApiInternalServerError( QStringLiteral( "The API handler returned an error: %1" ).arg( ex.what() ) );
109 }
110 break;
111 }
112 }
113 // Throw
114 if ( ! hasMatch )
115 {
116 throw QgsServerApiBadRequestException( QStringLiteral( "Requested URI does not match any registered API handler" ) );
117 }
118}
119
120const QMap<QgsServerOgcApi::ContentType, QStringList> QgsServerOgcApi::contentTypeMimes()
121{
122 return sContentTypeMime;
123}
124
125const QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType> > QgsServerOgcApi::contentTypeAliases()
126{
127 return sContentTypeAliases;
128}
129
130std::string QgsServerOgcApi::relToString( const Rel &rel )
131{
132 static const QMetaEnum metaEnum = QMetaEnum::fromType<QgsServerOgcApi::Rel>();
133 std::string val { metaEnum.valueToKey( rel ) };
134 std::replace( val.begin(), val.end(), '_', '-' );
135 return val;
136}
137
139{
140 static const QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
141 QString result { metaEnum.valueToKey( ct ) };
142 return result.replace( '_', '-' );
143}
144
146{
147 static const QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
148 return metaEnum.valueToKey( ct );
149}
150
152{
153 return contentTypeToString( ct ).toLower();
154}
155
157{
158 const QString exts = QString::fromStdString( extension );
159 const auto constMimeTypes( QgsServerOgcApi::contentTypeMimes() );
160 for ( auto it = constMimeTypes.constBegin();
161 it != constMimeTypes.constEnd();
162 ++it )
163 {
164 const auto constValues = it.value();
165 for ( const auto &value : constValues )
166 {
167 if ( value.contains( exts, Qt::CaseSensitivity::CaseInsensitive ) )
168 {
169 return it.key();
170 }
171 }
172 }
173 // Default to JSON, but log a warning!
174 QgsMessageLog::logMessage( QStringLiteral( "Content type for extension %1 not found! Returning default (JSON)" ).arg( exts ),
175 QStringLiteral( "Server" ),
178}
179
181{
182 if ( ! sContentTypeMime.contains( contentType ) )
183 {
184 return "";
185 }
186 return sContentTypeMime.value( contentType ).first().toStdString();
187}
188
189const std::vector<std::shared_ptr<QgsServerOgcApiHandler> > QgsServerOgcApi::handlers() const
190{
191 return mHandlers;
192}
193
194
@ 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.