QGIS API Documentation  3.10.0-A Coruña (6c816b4204)
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 
20 #include "qgsserverogcapi.h"
21 #include "qgsserverogcapihandler.h"
22 #include "qgsmessagelog.h"
23 #include "qgsapplication.h"
24 
25 QMap<QgsServerOgcApi::ContentType, QStringList> QgsServerOgcApi::sContentTypeMime = [ ]() -> QMap<QgsServerOgcApi::ContentType, QStringList>
26 {
27  QMap<QgsServerOgcApi::ContentType, QStringList> map;
28  map[QgsServerOgcApi::ContentType::JSON] = QStringList { QStringLiteral( "application/json" ) };
29  map[QgsServerOgcApi::ContentType::GEOJSON] = QStringList {
30  QStringLiteral( "application/geo+json" ),
31  QStringLiteral( "application/vnd.geo+json" ),
32  QStringLiteral( "application/geojson" )
33  };
34  map[QgsServerOgcApi::ContentType::HTML] = QStringList { QStringLiteral( "text/html" ) };
35  map[QgsServerOgcApi::ContentType::OPENAPI3] = QStringList { QStringLiteral( "application/openapi+json;version=3.0" ) };
36  return map;
37 }();
38 
39 QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> QgsServerOgcApi::sContentTypeAliases = [ ]() -> QHash<ContentType, QList<ContentType>>
40 {
41  QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType>> map;
42  map[ContentType::JSON] = { QgsServerOgcApi::ContentType::GEOJSON, QgsServerOgcApi::ContentType::OPENAPI3 };
43  return map;
44 }();
45 
46 
47 QgsServerOgcApi::QgsServerOgcApi( QgsServerInterface *serverIface, const QString &rootPath, const QString &name, const QString &description, const QString &version ):
48  QgsServerApi( serverIface ),
49  mRootPath( rootPath ),
50  mName( name ),
51  mDescription( description ),
52  mVersion( version )
53 {
54 
55 }
56 
58 {
59  //qDebug() << "API destroyed: " << name();
60 }
61 
63 {
64  std::shared_ptr<QgsServerOgcApiHandler> hp( handler );
65  mHandlers.emplace_back( std::move( hp ) );
66 }
67 
68 QUrl QgsServerOgcApi::sanitizeUrl( const QUrl &url )
69 {
70  return url.adjusted( QUrl::StripTrailingSlash | QUrl::NormalizePathSegments );
71 }
72 
74 {
75  // Get url
76  auto path { sanitizeUrl( context.request()->url() ).path() };
77  // Find matching handler
78  auto hasMatch { false };
79  for ( const auto &h : mHandlers )
80  {
81  QgsMessageLog::logMessage( QStringLiteral( "Checking API path %1 for %2 " ).arg( path, h->path().pattern() ), QStringLiteral( "Server" ), Qgis::Info );
82  if ( h->path().match( path ).hasMatch() )
83  {
84  hasMatch = true;
85  // Execute handler
86  QgsMessageLog::logMessage( QStringLiteral( "Found API handler %1" ).arg( QString::fromStdString( h->operationId() ) ), QStringLiteral( "Server" ), Qgis::Info );
87  // May throw QgsServerApiBadRequestException or JSON exceptions on serializing
88  try
89  {
90  h->handleRequest( context );
91  }
92  catch ( json::exception &ex )
93  {
94  throw QgsServerApiInternalServerError( QStringLiteral( "The API handler returned an error: %1" ).arg( ex.what() ) );
95  }
96  break;
97  }
98  }
99  // Throw
100  if ( ! hasMatch )
101  {
102  throw QgsServerApiBadRequestException( QStringLiteral( "Requested URI does not match any registered API handler" ) );
103  }
104 }
105 
106 const QMap<QgsServerOgcApi::ContentType, QStringList> QgsServerOgcApi::contentTypeMimes()
107 {
108  return sContentTypeMime;
109 }
110 
111 const QHash<QgsServerOgcApi::ContentType, QList<QgsServerOgcApi::ContentType> > QgsServerOgcApi::contentTypeAliases()
112 {
113  return sContentTypeAliases;
114 }
115 
116 std::string QgsServerOgcApi::relToString( const Rel &rel )
117 {
118  static QMetaEnum metaEnum = QMetaEnum::fromType<QgsServerOgcApi::Rel>();
119  std::string val { metaEnum.valueToKey( rel ) };
120  std::replace( val.begin(), val.end(), '_', '-' );
121  return val;
122 }
123 
125 {
126  static QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
127  QString result { metaEnum.valueToKey( ct ) };
128  return result.replace( '_', '-' );
129 }
130 
132 {
133  static QMetaEnum metaEnum = QMetaEnum::fromType<ContentType>();
134  return metaEnum.valueToKey( ct );
135 }
136 
138 {
139  return contentTypeToString( ct ).toLower();
140 }
141 
143 {
144  const QString exts = QString::fromStdString( extension );
145  for ( auto it = QgsServerOgcApi::contentTypeMimes().constBegin();
146  it != QgsServerOgcApi::contentTypeMimes().constEnd();
147  ++it )
148  {
149  const auto constValues = it.value();
150  for ( const auto &value : constValues )
151  {
152  if ( value.contains( exts, Qt::CaseSensitivity::CaseInsensitive ) )
153  {
154  return it.key();
155  }
156  }
157  }
158  // Default to JSON, but log a warning!
159  QgsMessageLog::logMessage( QStringLiteral( "Content type for extension %1 not found! Returning default (JSON)" ).arg( exts ),
160  QStringLiteral( "Server" ),
161  Qgis::Warning );
162  return QgsServerOgcApi::ContentType::JSON;
163 }
164 
166 {
167  if ( ! sContentTypeMime.contains( contentType ) )
168  {
169  return "";
170  }
171  return sContentTypeMime.value( contentType ).first().toStdString();
172 }
173 
174 const std::vector<std::shared_ptr<QgsServerOgcApiHandler> > QgsServerOgcApi::handlers() const
175 {
176  return mHandlers;
177 }
178 
179 
Server generic API endpoint abstract base class.
Definition: qgsserverapi.h:80
const std::vector< std::shared_ptr< QgsServerOgcApiHandler > > handlers() const
Returns registered handlers.
static QString contentTypeToString(const QgsServerOgcApi::ContentType &ct)
Returns the string representation of a ct (Content-Type) attribute.
void registerHandler(Args... args)
Registers an OGC API handler passing Args to the constructor.
The QgsServerOgcApiHandler abstract class represents a OGC API handler to be registered in QgsServerO...
static const QHash< QgsServerOgcApi::ContentType, QList< QgsServerOgcApi::ContentType > > contentTypeAliases()
Returns contenType specializations (e.g.
static std::string relToString(const QgsServerOgcApi::Rel &rel)
Returns the string representation of rel attribute.
static QgsServerOgcApi::ContentType contenTypeFromExtension(const std::string &extension)
Returns the Content-Type value corresponding to extension.
Internal server error API exception.
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.
QgsServerOgcApi(QgsServerInterface *serverIface, const QString &rootPath, const QString &name, const QString &description=QString(), const QString &version=QString())
QgsServerOgcApi constructor.
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.
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).
static QUrl sanitizeUrl(const QUrl &url)
Returns a sanitized url with extra slashes removed.
The QgsServerApiContext class encapsulates the resources for a particular client request: the request...
Bad request error API exception.
QgsServerInterface Class defining interfaces exposed by QGIS Server and made available to plugins...
Rel
Rel link types.
virtual void executeRequest(const QgsServerApiContext &context) const override SIP_THROW(QgsServerApiBadRequestException)
Executes a request by passing the given context to the API handlers.
static QString contentTypeToExtension(const QgsServerOgcApi::ContentType &ct)
Returns the file extension for a ct (Content-Type).
~QgsServerOgcApi() override
const QgsServerRequest * request() const
Returns the server request object.