QGIS API Documentation  3.16.0-Hannover (43b64b13f3)
qgsserverogcapihandler.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsserverogcapihandler.cpp - QgsServerOgcApiHandler
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 <QDateTime>
18 #include <QFileInfo>
19 #include <QDir>
20 #include <QDebug>
21 
22 #include "qgsmessagelog.h"
23 #include "qgsproject.h"
24 #include "qgsjsonutils.h"
25 #include "qgsvectorlayer.h"
26 
27 #include "qgsserverogcapihandler.h"
28 #include "qgsserverapiutils.h"
29 #include "qgsserverresponse.h"
30 #include "qgsserverinterface.h"
31 
32 #include "nlohmann/json.hpp"
33 #include "inja/inja.hpp"
34 
35 using namespace nlohmann;
36 using namespace inja;
37 
38 
39 
40 QVariantMap QgsServerOgcApiHandler::values( const QgsServerApiContext &context ) const
41 {
42  QVariantMap result ;
43  const auto constParameters { parameters( context ) };
44  for ( const auto &p : constParameters )
45  {
46  // value() calls the validators and throws an exception if validation fails
47  result[p.name()] = p.value( context );
48  }
49  const auto match { path().match( context.request()->url().toString() ) };
50  if ( match.hasMatch() )
51  {
52  const auto constNamed { path().namedCaptureGroups() };
53  // Get named path parameters
54  for ( const auto &name : constNamed )
55  {
56  if ( ! name.isEmpty() )
57  result[name] = QUrlQuery( match.captured( name ) ).toString() ;
58  }
59  }
60  return result;
61 }
62 
64 {
65  //qDebug() << "handler destroyed";
66 }
67 
69 {
70  return contentTypes().size() > 0 ? contentTypes().first() : QgsServerOgcApi::ContentType::JSON;
71 }
72 
73 QList<QgsServerOgcApi::ContentType> QgsServerOgcApiHandler::contentTypes() const
74 {
75  return mContentTypes;
76 }
77 
79 {
80  Q_UNUSED( context )
81  throw QgsServerApiNotImplementedException( QStringLiteral( "Subclasses must implement handleRequest" ) );
82 }
83 
84 QString QgsServerOgcApiHandler::contentTypeForAccept( const QString &accept ) const
85 {
86  for ( auto it = QgsServerOgcApi::contentTypeMimes().constBegin();
87  it != QgsServerOgcApi::contentTypeMimes().constEnd(); ++it )
88  {
89  const auto constValues = it.value();
90  for ( const auto &value : constValues )
91  {
92  if ( accept.contains( value, Qt::CaseSensitivity::CaseInsensitive ) )
93  {
94  return value;
95  }
96  }
97  }
98  // Log level info because this is not completely unexpected
99  QgsMessageLog::logMessage( QStringLiteral( "Content type for accept %1 not found!" ).arg( accept ),
100  QStringLiteral( "Server" ),
101  Qgis::Info );
102 
103  return QString();
104 }
105 
106 void QgsServerOgcApiHandler::write( json &data, const QgsServerApiContext &context, const json &htmlMetadata ) const
107 {
108  const QgsServerOgcApi::ContentType contentType { contentTypeFromRequest( context.request() ) };
109  switch ( contentType )
110  {
111  case QgsServerOgcApi::ContentType::HTML:
112  data["handler"] = schema( context );
113  if ( ! htmlMetadata.is_null() )
114  {
115  data["metadata"] = htmlMetadata;
116  }
117  htmlDump( data, context );
118  break;
119  case QgsServerOgcApi::ContentType::GEOJSON:
120  case QgsServerOgcApi::ContentType::JSON:
121  case QgsServerOgcApi::ContentType::OPENAPI3:
122  jsonDump( data, context, QgsServerOgcApi::contentTypeMimes().value( contentType ).first() );
123  break;
124  case QgsServerOgcApi::ContentType::XML:
125  // Not handled yet
126  break;
127  }
128 }
129 
130 void QgsServerOgcApiHandler::write( QVariant &data, const QgsServerApiContext &context, const QVariantMap &htmlMetadata ) const
131 {
132  json j = QgsJsonUtils::jsonFromVariant( data );
133  json jm = QgsJsonUtils::jsonFromVariant( htmlMetadata );
134  QgsServerOgcApiHandler::write( j, context, jm );
135 }
136 
137 std::string QgsServerOgcApiHandler::href( const QgsServerApiContext &context, const QString &extraPath, const QString &extension ) const
138 {
139  QUrl url { context.request()->url() };
140  QString urlBasePath { context.matchedPath() };
141  const auto match { path().match( url.path() ) };
142  if ( match.captured().count() > 0 )
143  {
144  url.setPath( urlBasePath + match.captured( 0 ) );
145  }
146  else
147  {
148  url.setPath( urlBasePath );
149  }
150 
151  // Remove any existing extension
152  const auto suffixLength { QFileInfo( url.path() ).suffix().length() };
153  if ( suffixLength > 0 )
154  {
155  auto path {url.path()};
156  path.truncate( path.length() - ( suffixLength + 1 ) );
157  url.setPath( path );
158  }
159 
160  // Add extra path
161  url.setPath( url.path() + extraPath );
162 
163  // (re-)add extension
164  // JSON is the default anyway so we don't need to add it
165  if ( ! extension.isEmpty() )
166  {
167  // Remove trailing slashes if any.
168  QString path { url.path() };
169  while ( path.endsWith( '/' ) )
170  {
171  path.chop( 1 );
172  }
173  url.setPath( path + '.' + extension );
174  }
175  return QgsServerOgcApi::sanitizeUrl( url ).toString( QUrl::FullyEncoded ).toStdString();
176 
177 }
178 
179 void QgsServerOgcApiHandler::jsonDump( json &data, const QgsServerApiContext &context, const QString &contentType ) const
180 {
181  // Do not append timestamp to openapi
182  if ( ! QgsServerOgcApi::contentTypeMimes().value( QgsServerOgcApi::ContentType::OPENAPI3 ).contains( contentType, Qt::CaseSensitivity::CaseInsensitive ) )
183  {
184  QDateTime time { QDateTime::currentDateTime() };
185  time.setTimeSpec( Qt::TimeSpec::UTC );
186  data["timeStamp"] = time.toString( Qt::DateFormat::ISODate ).toStdString() ;
187  }
188  context.response()->setStatusCode( 200 );
189  context.response()->setHeader( QStringLiteral( "Content-Type" ), contentType );
190 #ifdef QGISDEBUG
191  context.response()->write( data.dump( 2 ) );
192 #else
193  context.response()->write( data.dump( ) );
194 #endif
195 }
196 
198 {
199  Q_UNUSED( context )
200  return nullptr;
201 }
202 
203 json QgsServerOgcApiHandler::link( const QgsServerApiContext &context, const QgsServerOgcApi::Rel &linkType, const QgsServerOgcApi::ContentType contentType, const std::string &title ) const
204 {
205  json l
206  {
207  {
208  "href", href( context, "/",
210  },
211  { "rel", QgsServerOgcApi::relToString( linkType ) },
212  { "type", QgsServerOgcApi::mimeType( contentType ) },
213  { "title", title != "" ? title : linkTitle() },
214  };
215  return l;
216 }
217 
219 {
220  const QgsServerOgcApi::ContentType currentCt { contentTypeFromRequest( context.request() ) };
221  json links = json::array();
222  const QList<QgsServerOgcApi::ContentType> constCts { contentTypes() };
223  for ( const auto &ct : constCts )
224  {
225  links.push_back( link( context, ( ct == currentCt ? QgsServerOgcApi::Rel::self :
226  QgsServerOgcApi::Rel::alternate ), ct,
227  linkTitle() + " as " + QgsServerOgcApi::contentTypeToStdString( ct ) ) );
228  }
229  return links;
230 }
231 
233 {
234  if ( ! context.project() )
235  {
236  throw QgsServerApiImproperlyConfiguredException( QStringLiteral( "Project is invalid or undefined" ) );
237  }
238  // Check collectionId
239  const QRegularExpressionMatch match { path().match( context.request()->url().path( ) ) };
240  if ( ! match.hasMatch() )
241  {
242  throw QgsServerApiNotFoundError( QStringLiteral( "Collection was not found" ) );
243  }
244  const QString collectionId { match.captured( QStringLiteral( "collectionId" ) ) };
245  // May throw if not found
246  return layerFromCollectionId( context, collectionId );
247 
248 }
249 
250 const QString QgsServerOgcApiHandler::staticPath( const QgsServerApiContext &context ) const
251 {
252  // resources/server/api + /static
253  return context.serverInterface()->serverSettings()->apiResourcesDirectory() + QStringLiteral( "/ogc/static" );
254 }
255 
256 const QString QgsServerOgcApiHandler::templatePath( const QgsServerApiContext &context ) const
257 {
258  // resources/server/api + /ogc/templates/ + operationId + .html
259  QString path { context.serverInterface()->serverSettings()->apiResourcesDirectory() };
260  path += QLatin1String( "/ogc/templates" );
261  path += context.apiRootPath();
262  path += '/';
263  path += QString::fromStdString( operationId() );
264  path += QLatin1String( ".html" );
265  return path;
266 }
267 
268 
269 void QgsServerOgcApiHandler::htmlDump( const json &data, const QgsServerApiContext &context ) const
270 {
271  context.response()->setHeader( QStringLiteral( "Content-Type" ), QStringLiteral( "text/html" ) );
272  auto path { templatePath( context ) };
273  if ( ! QFile::exists( path ) )
274  {
275  QgsMessageLog::logMessage( QStringLiteral( "Template not found error: %1" ).arg( path ), QStringLiteral( "Server" ), Qgis::Critical );
276  throw QgsServerApiBadRequestException( QStringLiteral( "Template not found: %1" ).arg( QFileInfo( path ).fileName() ) );
277  }
278 
279  QFile f( path );
280  if ( ! f.open( QFile::ReadOnly | QFile::Text ) )
281  {
282  QgsMessageLog::logMessage( QStringLiteral( "Could not open template file: %1" ).arg( path ), QStringLiteral( "Server" ), Qgis::Critical );
283  throw QgsServerApiInternalServerError( QStringLiteral( "Could not open template file: %1" ).arg( QFileInfo( path ).fileName() ) );
284  }
285 
286  try
287  {
288  // Get the template directory and the file name
289  QFileInfo pathInfo { path };
290  Environment env { QString( pathInfo.dir().path() + QDir::separator() ).toStdString() };
291 
292  // For template debugging:
293  env.add_callback( "json_dump", 0, [ = ]( Arguments & )
294  {
295  return data.dump();
296  } );
297 
298  // Path manipulation: appends a directory path to the current url
299  env.add_callback( "path_append", 1, [ = ]( Arguments & args )
300  {
301  auto url { context.request()->url() };
302  QFileInfo fi{ url.path() };
303  auto suffix { fi.suffix() };
304  auto fName { fi.filePath()};
305  if ( !suffix.isEmpty() )
306  {
307  fName.chop( suffix.length() + 1 );
308  }
309  // Chop any ending slashes
310  while ( fName.endsWith( '/' ) )
311  {
312  fName.chop( 1 );
313  }
314  fName += '/' + QString::number( args.at( 0 )->get<QgsFeatureId>( ) );
315  if ( !suffix.isEmpty() )
316  {
317  fName += '.' + suffix;
318  }
319  fi.setFile( fName );
320  url.setPath( fi.filePath() );
321  return url.toString().toStdString();
322  } );
323 
324  // Path manipulation: removes the specified number of directory components from the current url path
325  env.add_callback( "path_chomp", 1, [ = ]( Arguments & args )
326  {
327  QUrl url { QString::fromStdString( args.at( 0 )->get<std::string>( ) ) };
328  QFileInfo fi{ url.path() };
329  auto suffix { fi.suffix() };
330  auto fName { fi.filePath()};
331  fName.chop( suffix.length() + 1 );
332  // Chomp last segment
333  fName = fName.replace( QRegularExpression( R"raw(\/[^/]+$)raw" ), QString() );
334  if ( !suffix.isEmpty() )
335  {
336  fName += '.' + suffix;
337  }
338  fi.setFile( fName );
339  url.setPath( fi.filePath() );
340  return url.toString().toStdString();
341  } );
342 
343  // Returns filtered links from a link list
344  // links_filter( <links>, <key>, <value> )
345  env.add_callback( "links_filter", 3, [ = ]( Arguments & args )
346  {
347  json links = args.at( 0 )->get<json>( );
348  if ( ! links.is_array() )
349  {
350  links = json::array();
351  }
352  std::string key { args.at( 1 )->get<std::string>( ) };
353  std::string value { args.at( 2 )->get<std::string>( ) };
354  json result = json::array();
355  for ( const auto &l : links )
356  {
357  if ( l[key] == value )
358  {
359  result.push_back( l );
360  }
361  }
362  return result;
363  } );
364 
365  // Returns a short name from content types
366  env.add_callback( "content_type_name", 1, [ = ]( Arguments & args )
367  {
368  const QgsServerOgcApi::ContentType ct { QgsServerOgcApi::contenTypeFromExtension( args.at( 0 )->get<std::string>( ) ) };
370  } );
371 
372  // Replace newlines with <br>
373  env.add_callback( "nl2br", 1, [ = ]( Arguments & args )
374  {
375  QString text { QString::fromStdString( args.at( 0 )->get<std::string>( ) ) };
376  return text.replace( '\n', QLatin1String( "<br>" ) ).toStdString();
377  } );
378 
379 
380  // Returns a list of parameter component data from components -> parameters by ref name
381  // parameter( <ref object> )
382  env.add_callback( "component_parameter", 1, [ = ]( Arguments & args )
383  {
384  json ret = json::array();
385  json ref = args.at( 0 )->get<json>( );
386  if ( ! ref.is_object() )
387  {
388  return ret;
389  }
390  try
391  {
392  QString name = QString::fromStdString( ref["$ref"] );
393  name = name.split( '/' ).last();
394  ret.push_back( data["components"]["parameters"][name.toStdString()] );
395  }
396  catch ( std::exception & )
397  {
398  // Do nothing
399  }
400  return ret;
401  } );
402 
403 
404  // Static: returns the full URL to the specified static <path>
405  env.add_callback( "static", 1, [ = ]( Arguments & args )
406  {
407  auto asset( args.at( 0 )->get<std::string>( ) );
408  QString matchedPath { context.matchedPath() };
409  // If its the root path '/' strip it!
410  if ( matchedPath == '/' )
411  {
412  matchedPath.clear();
413  }
414  return matchedPath.toStdString() + "/static/" + asset;
415  } );
416 
417  context.response()->write( env.render_file( pathInfo.fileName().toStdString(), data ) );
418  }
419  catch ( std::exception &e )
420  {
421  QgsMessageLog::logMessage( QStringLiteral( "Error parsing template file: %1 - %2" ).arg( path, e.what() ), QStringLiteral( "Server" ), Qgis::Critical );
422  throw QgsServerApiInternalServerError( QStringLiteral( "Error parsing template file: %1" ).arg( e.what() ) );
423  }
424 }
425 
427 {
428  // Fallback to default
429  QgsServerOgcApi::ContentType result { defaultContentType() };
430  bool found { false };
431  // First file extension ...
432  const QString extension { QFileInfo( request->url().path() ).suffix().toUpper() };
433  if ( ! extension.isEmpty() )
434  {
435  static QMetaEnum metaEnum { QMetaEnum::fromType<QgsServerOgcApi::ContentType>() };
436  bool ok { false };
437  const int ct { metaEnum.keyToValue( extension.toLocal8Bit().constData(), &ok ) };
438  if ( ok )
439  {
440  result = static_cast<QgsServerOgcApi::ContentType>( ct );
441  found = true;
442  }
443  else
444  {
445  QgsMessageLog::logMessage( QStringLiteral( "The client requested an unsupported extension: %1" ).arg( extension ), QStringLiteral( "Server" ), Qgis::Warning );
446  }
447  }
448  // ... then "Accept"
449  const QString accept { request->header( QStringLiteral( "Accept" ) ) };
450  if ( ! found && ! accept.isEmpty() )
451  {
452  const QString ctFromAccept { contentTypeForAccept( accept ) };
453  if ( ! ctFromAccept.isEmpty() )
454  {
455  auto it = QgsServerOgcApi::contentTypeMimes().constBegin();
456  while ( ! found && it != QgsServerOgcApi::contentTypeMimes().constEnd() )
457  {
458  int idx = it.value().indexOf( ctFromAccept );
459  if ( idx >= 0 )
460  {
461  found = true;
462  result = it.key();
463  }
464  it++;
465  }
466  }
467  else
468  {
469  QgsMessageLog::logMessage( QStringLiteral( "The client requested an unsupported content type in Accept header: %1" ).arg( accept ), QStringLiteral( "Server" ), Qgis::Warning );
470  }
471  }
472  // Validation: check if the requested content type (or an alias) is supported by the handler
473  if ( ! contentTypes().contains( result ) )
474  {
475  // Check aliases
476  bool found { false };
477  if ( QgsServerOgcApi::contentTypeAliases().keys().contains( result ) )
478  {
479  const QList<QgsServerOgcApi::ContentType> constCt { contentTypes() };
480  for ( const auto &ct : constCt )
481  {
482  if ( QgsServerOgcApi::contentTypeAliases()[result].contains( ct ) )
483  {
484  result = ct;
485  found = true;
486  break;
487  }
488  }
489  }
490 
491  if ( ! found )
492  {
493  QgsMessageLog::logMessage( QStringLiteral( "Unsupported Content-Type: %1" ).arg( QgsServerOgcApi::contentTypeToString( result ) ), QStringLiteral( "Server" ), Qgis::Info );
494  throw QgsServerApiBadRequestException( QStringLiteral( "Unsupported Content-Type: %1" ).arg( QgsServerOgcApi::contentTypeToString( result ) ) );
495  }
496  }
497  return result;
498 }
499 
500 QString QgsServerOgcApiHandler::parentLink( const QUrl &url, int levels )
501 {
502  QString path { url.path() };
503  const QFileInfo fi { path };
504  const QString suffix { fi.suffix() };
505  if ( ! suffix.isEmpty() )
506  {
507  path.chop( suffix.length() + 1 );
508  }
509  while ( path.endsWith( '/' ) )
510  {
511  path.chop( 1 );
512  }
513  QRegularExpression re( R"raw(\/[^/]+$)raw" );
514  for ( int i = 0; i < levels ; i++ )
515  {
516  path = path.replace( re, QString() );
517  }
518  QUrl result( url );
519  QUrlQuery query( result );
520  QList<QPair<QString, QString> > qi;
521  const auto constItems { query.queryItems( ) };
522  for ( const auto &i : constItems )
523  {
524  if ( i.first.compare( QStringLiteral( "MAP" ), Qt::CaseSensitivity::CaseInsensitive ) == 0 )
525  {
526  qi.push_back( i );
527  }
528  }
529  // Make sure the parent link ends with a slash
530  if ( ! path.endsWith( '/' ) )
531  {
532  path.append( '/' );
533  }
534  QUrlQuery resultQuery;
535  resultQuery.setQueryItems( qi );
536  result.setQuery( resultQuery );
537  result.setPath( path );
538  return result.toString();
539 }
540 
542 {
543  const auto mapLayers { context.project()->mapLayersByShortName<QgsVectorLayer *>( collectionId ) };
544  if ( mapLayers.count() != 1 )
545  {
546  throw QgsServerApiNotFoundError( QStringLiteral( "Collection with given id (%1) was not found or multiple matches were found" ).arg( collectionId ) );
547  }
548  return mapLayers.first();
549 }
550 
552 {
553  static json defRes =
554  {
555  { "description", "An error occurred." },
556  {
557  "content", {
558  {
559  "application/json", {
560  {
561  "schema", {
562  { "$ref", "#/components/schemas/exception" }
563  }
564  }
565  }
566  },
567  {
568  "text/html", {
569  {
570  "schema", {
571  { "type", "string" }
572  }
573  }
574  }
575  }
576  }
577  }
578  };
579  return defRes;
580 }
581 
583 {
584  return QgsJsonUtils::jsonFromVariant( tags() );
585 }
586 
587 void QgsServerOgcApiHandler::setContentTypesInt( const QList<int> &contentTypes )
588 {
589  mContentTypes.clear();
590  for ( const int &i : qgis::as_const( contentTypes ) )
591  {
592  mContentTypes.push_back( static_cast<QgsServerOgcApi::ContentType>( i ) );
593  }
594 }
595 
596 void QgsServerOgcApiHandler::setContentTypes( const QList<QgsServerOgcApi::ContentType> &contentTypes )
597 {
598  mContentTypes = contentTypes;
599 }
QgsServerApiImproperlyConfiguredException
configuration error on the server prevents to serve the request, which would be valid otherwise.
Definition: qgsserverexception.h:286
QgsServerOgcApiHandler::schema
virtual json schema(const QgsServerApiContext &context) const
Returns handler information from the context for the OPENAPI description (id, description and other m...
Definition: qgsserverogcapihandler.cpp:197
QgsServerOgcApiHandler::contentTypeForAccept
QString contentTypeForAccept(const QString &accept) const
Looks for the first ContentType match in the accept header and returns its mime type,...
Definition: qgsserverogcapihandler.cpp:84
QgsServerApiNotImplementedException
this method is not yet implemented
Definition: qgsserverexception.h:307
QgsServerOgcApiHandler::templatePath
virtual const QString templatePath(const QgsServerApiContext &context) const
Returns the HTML template path for the handler in the given context.
Definition: qgsserverogcapihandler.cpp:256
QgsServerApiContext
The QgsServerApiContext class encapsulates the resources for a particular client request: the request...
Definition: qgsserverapicontext.h:39
QgsServerOgcApiHandler::staticPath
virtual const QString staticPath(const QgsServerApiContext &context) const
Returns the absolute path to the base directory where static resources for this handler are stored in...
Definition: qgsserverogcapihandler.cpp:250
QgsServerOgcApiHandler::layerFromCollectionId
static QgsVectorLayer * layerFromCollectionId(const QgsServerApiContext &context, const QString &collectionId)
Returns a vector layer from the collectionId in the given context.
Definition: qgsserverogcapihandler.cpp:541
QgsServerApiNotFoundError
Not found error API exception.
Definition: qgsserverexception.h:224
QgsServerOgcApi::relToString
static std::string relToString(const QgsServerOgcApi::Rel &rel)
Returns the string representation of rel attribute.
Definition: qgsserverogcapi.cpp:124
Qgis::Warning
@ Warning
Definition: qgis.h:91
QgsServerApiInternalServerError
Internal server error API exception.
Definition: qgsserverexception.h:203
QgsServerApiContext::matchedPath
const QString matchedPath() const
Returns the initial part of the incoming request URL path that matches the API root path.
Definition: qgsserverapicontext.cpp:60
QgsServerOgcApiHandler::setContentTypes
void setContentTypes(const QList< QgsServerOgcApi::ContentType > &contentTypes)
Set the content types to contentTypes.
Definition: qgsserverogcapihandler.cpp:596
QgsServerOgcApiHandler::defaultResponse
static json defaultResponse()
Returns the defaultResponse as JSON.
Definition: qgsserverogcapihandler.cpp:551
QgsServerRequest
QgsServerRequest Class defining request interface passed to services QgsService::executeRequest() met...
Definition: qgsserverrequest.h:39
QgsServerOgcApi::sanitizeUrl
static QUrl sanitizeUrl(const QUrl &url)
Returns a sanitized url with extra slashes removed.
Definition: qgsserverogcapi.cpp:70
QgsServerOgcApiHandler::contentTypeFromRequest
QgsServerOgcApi::ContentType contentTypeFromRequest(const QgsServerRequest *request) const
Returns the content type from the request.
Definition: qgsserverogcapihandler.cpp:426
QgsServerOgcApi::contentTypeMimes
static const QMap< QgsServerOgcApi::ContentType, QStringList > contentTypeMimes()
Returns a map of contentType => list of mime types.
Definition: qgsserverogcapi.cpp:114
QgsServerOgcApiHandler::link
json link(const QgsServerApiContext &context, const QgsServerOgcApi::Rel &linkType=QgsServerOgcApi::Rel::self, const QgsServerOgcApi::ContentType contentType=QgsServerOgcApi::ContentType::JSON, const std::string &title="") const
Builds and returns a link to the resource.
Definition: qgsserverogcapihandler.cpp:203
QgsServerOgcApi::contentTypeToExtension
static QString contentTypeToExtension(const QgsServerOgcApi::ContentType &ct)
Returns the file extension for a ct (Content-Type).
Definition: qgsserverogcapi.cpp:145
QgsServerOgcApiHandler::links
json links(const QgsServerApiContext &context) const
Returns all the links for the given request context.
Definition: qgsserverogcapihandler.cpp:218
qgsserverapiutils.h
QgsServerOgcApiHandler::href
std::string href(const QgsServerApiContext &context, const QString &extraPath=QString(), const QString &extension=QString()) const
Returns an URL to self, to be used for links to the current resources and as a base for constructing ...
Definition: qgsserverogcapihandler.cpp:137
QgsServerApiContext::apiRootPath
QString apiRootPath() const
Returns the API root path.
Definition: qgsserverapicontext.cpp:75
QgsServerOgcApiHandler::setContentTypesInt
void setContentTypesInt(const QList< int > &contentTypes)
Set the content types to contentTypes.
Definition: qgsserverogcapihandler.cpp:587
QgsServerResponse::write
virtual void write(const QString &data)
Write string This is a convenient method that will write directly to the underlying I/O device.
Definition: qgsserverresponse.cpp:25
QgsServerOgcApiHandler::write
void write(json &data, const QgsServerApiContext &context, const json &htmlMetadata=nullptr) const
Writes data to the context response stream, content-type is calculated from the context request,...
Definition: qgsserverogcapihandler.cpp:106
QgsServerOgcApiHandler::htmlDump
void htmlDump(const json &data, const QgsServerApiContext &context) const
Writes data as HTML to the response stream in context using a template.
Definition: qgsserverogcapihandler.cpp:269
Qgis::Info
@ Info
Definition: qgis.h:90
qgsserverresponse.h
QgsServerOgcApiHandler::contentTypes
QList< QgsServerOgcApi::ContentType > contentTypes() const
Returns the list of content types this handler can serve, default to JSON and HTML.
Definition: qgsserverogcapihandler.cpp:73
QgsServerApiContext::project
const QgsProject * project() const
Returns the (possibly NULL) project.
Definition: qgsserverapicontext.cpp:45
QgsServerResponse::setStatusCode
virtual void setStatusCode(int code)=0
Set the http status code.
qgsserverogcapihandler.h
QgsServerApiContext::response
QgsServerResponse * response() const
Returns the server response object.
Definition: qgsserverapicontext.cpp:39
QgsServerOgcApi::contentTypeAliases
static const QHash< QgsServerOgcApi::ContentType, QList< QgsServerOgcApi::ContentType > > contentTypeAliases()
Returns contentType specializations (e.g.
Definition: qgsserverogcapi.cpp:119
QgsProject::mapLayersByShortName
QList< QgsMapLayer * > mapLayersByShortName(const QString &shortName) const
Retrieves a list of matching registered layers by layer shortName.
Definition: qgsproject.cpp:3218
QgsServerRequest::header
QString header(const QString &name) const
Returns the header value.
Definition: qgsserverrequest.cpp:43
QgsServerInterface::serverSettings
virtual QgsServerSettings * serverSettings()=0
Returns the server settings.
QgsServerApiContext::serverInterface
QgsServerInterface * serverInterface() const
Returns the server interface.
Definition: qgsserverapicontext.cpp:55
QgsServerOgcApiHandler::jsonDump
void jsonDump(json &data, const QgsServerApiContext &context, const QString &contentType=QStringLiteral("application/json")) const
Writes data to the context response stream as JSON (indented if debug is active), an optional content...
Definition: qgsserverogcapihandler.cpp:179
QgsServerOgcApi::Rel
Rel
Rel link types.
Definition: qgsserverogcapi.h:58
QgsServerOgcApi::contentTypeToString
static QString contentTypeToString(const QgsServerOgcApi::ContentType &ct)
Returns the string representation of a ct (Content-Type) attribute.
Definition: qgsserverogcapi.cpp:132
qgsvectorlayer.h
QgsServerOgcApiHandler::handleRequest
virtual void handleRequest(const QgsServerApiContext &context) const SIP_THROW(QgsServerApiBadRequestException)
Handles the request within its context.
Definition: qgsserverogcapihandler.cpp:78
QgsVectorLayer
Represents a vector layer which manages a vector based data sets.
Definition: qgsvectorlayer.h:387
QgsServerOgcApi::contenTypeFromExtension
static QgsServerOgcApi::ContentType contenTypeFromExtension(const std::string &extension)
Returns the Content-Type value corresponding to extension.
Definition: qgsserverogcapi.cpp:150
QgsServerOgcApiHandler::defaultContentType
virtual QgsServerOgcApi::ContentType defaultContentType() const
Returns the default response content type in case the client did not specifically ask for any particu...
Definition: qgsserverogcapihandler.cpp:68
QgsServerOgcApi::mimeType
static std::string mimeType(const QgsServerOgcApi::ContentType &contentType)
Returns the mime-type for the contentType or an empty string if not found.
Definition: qgsserverogcapi.cpp:173
QgsMessageLog::logMessage
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).
Definition: qgsmessagelog.cpp:27
QgsServerSettings::apiResourcesDirectory
QString apiResourcesDirectory() const
Returns the server-wide base directory where HTML templates and static assets (e.g.
Definition: qgsserversettings.cpp:492
QgsServerRequest::url
QUrl url() const
Definition: qgsserverrequest.cpp:65
QgsServerApiContext::request
const QgsServerRequest * request() const
Returns the server request object.
Definition: qgsserverapicontext.cpp:33
QgsServerOgcApiHandler::jsonTags
json jsonTags() const
Returns tags as JSON.
Definition: qgsserverogcapihandler.cpp:582
Qgis::Critical
@ Critical
Definition: qgis.h:92
QgsServerOgcApiHandler::parentLink
static QString parentLink(const QUrl &url, int levels=1)
Returns a link to the parent page up to levels in the HTML hierarchy from the given url,...
Definition: qgsserverogcapihandler.cpp:500
qgsjsonutils.h
QgsServerOgcApi::ContentType
ContentType
Media types used for content negotiation, insert more specific first.
Definition: qgsserverogcapi.h:80
QgsServerOgcApiHandler::values
virtual QVariantMap values(const QgsServerApiContext &context) const SIP_THROW(QgsServerApiBadRequestException)
Analyzes the incoming request context and returns the validated parameter map, throws QgsServerApiBad...
Definition: qgsserverogcapihandler.cpp:40
QgsJsonUtils::jsonFromVariant
static json jsonFromVariant(const QVariant &v)
Converts a QVariant v to a json object.
Definition: qgsjsonutils.cpp:400
QgsServerOgcApiHandler::layerFromContext
QgsVectorLayer * layerFromContext(const QgsServerApiContext &context) const
Returns a vector layer instance from the "collectionId" parameter of the path in the given context,...
Definition: qgsserverogcapihandler.cpp:232
QgsServerApiBadRequestException
Bad request error API exception.
Definition: qgsserverexception.h:245
QgsServerOgcApi::contentTypeToStdString
static std::string contentTypeToStdString(const QgsServerOgcApi::ContentType &ct)
Returns the string representation of a ct (Content-Type) attribute.
Definition: qgsserverogcapi.cpp:139
qgsproject.h
QgsServerOgcApiHandler::~QgsServerOgcApiHandler
virtual ~QgsServerOgcApiHandler()
Definition: qgsserverogcapihandler.cpp:63
QgsServerResponse::setHeader
virtual void setHeader(const QString &key, const QString &value)=0
Set Header entry Add Header entry to the response Note that it is usually an error to set Header afte...
QgsFeatureId
qint64 QgsFeatureId
64 bit feature ids negative numbers are used for uncommitted/newly added features
Definition: qgsfeatureid.h:28
qgsmessagelog.h
qgsserverinterface.h