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