QGIS API Documentation  3.14.0-Pi (9f7028fd23)
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() ).completeSuffix().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 += QStringLiteral( "/ogc/templates" );
261  path += context.apiRootPath();
262  path += '/';
263  path += QString::fromStdString( operationId() );
264  path += QStringLiteral( ".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 { ( 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  return context.matchedPath().toStdString() + "/static/" + asset;
409  } );
410 
411  context.response()->write( env.render_file( pathInfo.fileName().toStdString(), data ) );
412  }
413  catch ( std::exception &e )
414  {
415  QgsMessageLog::logMessage( QStringLiteral( "Error parsing template file: %1 - %2" ).arg( path, e.what() ), QStringLiteral( "Server" ), Qgis::Critical );
416  throw QgsServerApiInternalServerError( QStringLiteral( "Error parsing template file: %1" ).arg( e.what() ) );
417  }
418 }
419 
421 {
422  // Fallback to default
423  QgsServerOgcApi::ContentType result { defaultContentType() };
424  bool found { false };
425  // First file extension ...
426  const QString extension { QFileInfo( request->url().path() ).completeSuffix().toUpper() };
427  if ( ! extension.isEmpty() )
428  {
429  static QMetaEnum metaEnum { QMetaEnum::fromType<QgsServerOgcApi::ContentType>() };
430  bool ok { false };
431  const int ct { metaEnum.keyToValue( extension.toLocal8Bit().constData(), &ok ) };
432  if ( ok )
433  {
434  result = static_cast<QgsServerOgcApi::ContentType>( ct );
435  found = true;
436  }
437  else
438  {
439  QgsMessageLog::logMessage( QStringLiteral( "The client requested an unsupported extension: %1" ).arg( extension ), QStringLiteral( "Server" ), Qgis::Warning );
440  }
441  }
442  // ... then "Accept"
443  const QString accept { request->header( QStringLiteral( "Accept" ) ) };
444  if ( ! found && ! accept.isEmpty() )
445  {
446  const QString ctFromAccept { contentTypeForAccept( accept ) };
447  if ( ! ctFromAccept.isEmpty() )
448  {
449  auto it = QgsServerOgcApi::contentTypeMimes().constBegin();
450  while ( ! found && it != QgsServerOgcApi::contentTypeMimes().constEnd() )
451  {
452  int idx = it.value().indexOf( ctFromAccept );
453  if ( idx >= 0 )
454  {
455  found = true;
456  result = it.key();
457  }
458  it++;
459  }
460  }
461  else
462  {
463  QgsMessageLog::logMessage( QStringLiteral( "The client requested an unsupported content type in Accept header: %1" ).arg( accept ), QStringLiteral( "Server" ), Qgis::Warning );
464  }
465  }
466  // Validation: check if the requested content type (or an alias) is supported by the handler
467  if ( ! contentTypes().contains( result ) )
468  {
469  // Check aliases
470  bool found { false };
471  if ( QgsServerOgcApi::contentTypeAliases().keys().contains( result ) )
472  {
473  const QList<QgsServerOgcApi::ContentType> constCt { contentTypes() };
474  for ( const auto &ct : constCt )
475  {
476  if ( QgsServerOgcApi::contentTypeAliases()[result].contains( ct ) )
477  {
478  result = ct;
479  found = true;
480  break;
481  }
482  }
483  }
484 
485  if ( ! found )
486  {
487  QgsMessageLog::logMessage( QStringLiteral( "Unsupported Content-Type: %1" ).arg( QgsServerOgcApi::contentTypeToString( result ) ), QStringLiteral( "Server" ), Qgis::Info );
488  throw QgsServerApiBadRequestException( QStringLiteral( "Unsupported Content-Type: %1" ).arg( QgsServerOgcApi::contentTypeToString( result ) ) );
489  }
490  }
491  return result;
492 }
493 
494 QString QgsServerOgcApiHandler::parentLink( const QUrl &url, int levels )
495 {
496  QString path { url.path() };
497  const QFileInfo fi { path };
498  const QString suffix { fi.suffix() };
499  if ( ! suffix.isEmpty() )
500  {
501  path.chop( suffix.length() + 1 );
502  }
503  while ( path.endsWith( '/' ) )
504  {
505  path.chop( 1 );
506  }
507  QRegularExpression re( R"raw(\/[^/]+$)raw" );
508  for ( int i = 0; i < levels ; i++ )
509  {
510  path = path.replace( re, QString() );
511  }
512  QUrl result( url );
513  QUrlQuery query( result );
514  QList<QPair<QString, QString> > qi;
515  const auto constItems { query.queryItems( ) };
516  for ( const auto &i : constItems )
517  {
518  if ( i.first.compare( QStringLiteral( "MAP" ), Qt::CaseSensitivity::CaseInsensitive ) == 0 )
519  {
520  qi.push_back( i );
521  }
522  }
523  // Make sure the parent link ends with a slash
524  if ( ! path.endsWith( '/' ) )
525  {
526  path.append( '/' );
527  }
528  QUrlQuery resultQuery;
529  resultQuery.setQueryItems( qi );
530  result.setQuery( resultQuery );
531  result.setPath( path );
532  return result.toString();
533 }
534 
536 {
537  const auto mapLayers { context.project()->mapLayersByShortName<QgsVectorLayer *>( collectionId ) };
538  if ( mapLayers.count() != 1 )
539  {
540  throw QgsServerApiNotFoundError( QStringLiteral( "Collection with given id (%1) was not found or multiple matches were found" ).arg( collectionId ) );
541  }
542  return mapLayers.first();
543 }
544 
546 {
547  static json defRes =
548  {
549  { "description", "An error occurred." },
550  {
551  "content", {
552  {
553  "application/json", {
554  {
555  "schema", {
556  { "$ref", "#/components/schemas/exception" }
557  }
558  }
559  }
560  },
561  {
562  "text/html", {
563  {
564  "schema", {
565  { "type", "string" }
566  }
567  }
568  }
569  }
570  }
571  }
572  };
573  return defRes;
574 }
575 
577 {
578  return QgsJsonUtils::jsonFromVariant( tags() );
579 }
580 
581 void QgsServerOgcApiHandler::setContentTypesInt( const QList<int> &contentTypes )
582 {
583  mContentTypes.clear();
584  for ( const int &i : qgis::as_const( contentTypes ) )
585  {
586  mContentTypes.push_back( static_cast<QgsServerOgcApi::ContentType>( i ) );
587  }
588 }
589 
590 void QgsServerOgcApiHandler::setContentTypes( const QList<QgsServerOgcApi::ContentType> &contentTypes )
591 {
592  mContentTypes = contentTypes;
593 }
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: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: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:256
QgsServerApiContext
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: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:535
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:124
Qgis::Warning
@ Warning
Definition: qgis.h:104
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:590
QgsServerOgcApiHandler::defaultResponse
static json defaultResponse()
Returns the defaultResponse as JSON.
Definition: qgsserverogcapihandler.cpp:545
QgsServerRequest
Definition: qgsserverrequest.h:38
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:420
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:581
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:103
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 contenType 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:3134
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:57
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
Definition: qgsvectorlayer.h:385
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:423
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:576
Qgis::Critical
@ Critical
Definition: qgis.h:105
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:494
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:395
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:244
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
Definition: qgsfeatureid.h:25
qgsmessagelog.h
qgsserverinterface.h