mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
346 lines
13 KiB
C++
346 lines
13 KiB
C++
/***************************************************************************
|
|
qgsserverogcapihandler.h - QgsServerOgcApiHandler
|
|
|
|
---------------------
|
|
begin : 10.7.2019
|
|
copyright : (C) 2019 by Alessandro Pasotti
|
|
email : elpaso at itopen dot it
|
|
***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
#ifndef QGSSERVEROGCAPIHANDLER_H
|
|
#define QGSSERVEROGCAPIHANDLER_H
|
|
|
|
#include <QRegularExpression>
|
|
#include "qgis_server.h"
|
|
#include "qgsserverquerystringparameter.h"
|
|
#include "qgsserverogcapi.h"
|
|
#include "nlohmann/json_fwd.hpp"
|
|
#include "inja/inja.hpp"
|
|
|
|
#ifndef SIP_RUN
|
|
using namespace nlohmann;
|
|
#endif
|
|
|
|
class QgsServerApiContext;
|
|
|
|
/**
|
|
* \ingroup server
|
|
* The QgsServerOgcApiHandler abstract class represents a OGC API handler to be registered
|
|
* in QgsServerOgcApi class.
|
|
*
|
|
* Subclasses must override operational and informative methods and define
|
|
* the core functionality in handleRequest() method.
|
|
*
|
|
* The following methods MUST be implemented:
|
|
* - path
|
|
* - operationId
|
|
* - summary (shorter text)
|
|
* - description (longer text)
|
|
* - linkTitle
|
|
* - linkType
|
|
* - schema
|
|
*
|
|
* Optionally, override:
|
|
* - tags
|
|
* - parameters
|
|
* - contentTypes
|
|
* - defaultContentType
|
|
*
|
|
*
|
|
* \since QGIS 3.10
|
|
*/
|
|
class SERVER_EXPORT QgsServerOgcApiHandler
|
|
{
|
|
|
|
public:
|
|
|
|
virtual ~QgsServerOgcApiHandler();
|
|
|
|
// /////////////////////////////////////////////
|
|
// MAIN Section (operational)
|
|
|
|
/**
|
|
* URL pattern for this handler, named capture group are automatically
|
|
* extracted and returned by values()
|
|
*
|
|
* Example: "/handlername/(?P<code1>\d{2})/items" will capture "code1" as a
|
|
* named parameter.
|
|
*
|
|
* \see values()
|
|
*/
|
|
virtual QRegularExpression path() const = 0;
|
|
|
|
//! Returns the operation id for template file names and other internal references
|
|
virtual std::string operationId() const = 0;
|
|
|
|
/**
|
|
* Returns a list of query string parameters.
|
|
*
|
|
* Depending on the handler, it may be dynamic (per-request) or static.
|
|
* \param context the request context
|
|
*/
|
|
virtual QList<QgsServerQueryStringParameter> parameters( const QgsServerApiContext &context ) const { Q_UNUSED( context ); return { }; }
|
|
|
|
// /////////////////////////////////////////////
|
|
// METADATA Sections (informative)
|
|
|
|
//! Summary
|
|
virtual std::string summary() const = 0;
|
|
|
|
//! Description
|
|
virtual std::string description() const = 0;
|
|
|
|
//! Title for the handler link
|
|
virtual std::string linkTitle() const = 0;
|
|
|
|
//! Main role for the resource link
|
|
virtual QgsServerOgcApi::Rel linkType() const = 0;
|
|
|
|
//! Tags
|
|
virtual QStringList tags() const { return {}; }
|
|
|
|
/**
|
|
* Returns the default response content type in case the client did not specifically
|
|
* ask for any particular content type.
|
|
*/
|
|
virtual QgsServerOgcApi::ContentType defaultContentType() const { return QgsServerOgcApi::ContentType::JSON; }
|
|
|
|
/**
|
|
* Returns the list of content types this handler can serve, default to JSON and HTML.
|
|
* In case a specialized type (such as GEOJSON) is supported,
|
|
* the generic type (such as JSON) should not be listed.
|
|
* \note not available in Python bindings
|
|
*/
|
|
virtual QList<QgsServerOgcApi::ContentType> contentTypes() const SIP_SKIP;
|
|
|
|
/**
|
|
* Returns the list of content types this handler can serve, default to JSON and HTML.
|
|
* In case a specialized type (such as GEOJSON) is supported,
|
|
* the generic type (such as JSON) should not be listed.
|
|
*/
|
|
virtual QList<int> contentTypesInt() const SIP_PYNAME( contentTypes );
|
|
|
|
/**
|
|
* Handles the request within its \a context
|
|
*
|
|
* Subclasses must implement this methods, and call validate() to
|
|
* extract validated parameters from the request.
|
|
*
|
|
* \throws QgsServerApiBadRequestError if the method encounters any error
|
|
*/
|
|
virtual void handleRequest( const QgsServerApiContext &context ) const SIP_THROW( QgsServerApiBadRequestException ) SIP_VIRTUALERRORHANDLER( serverapi_badrequest_exception_handler );
|
|
|
|
/**
|
|
* Analyzes the incoming request \a context and returns the validated
|
|
* parameter map, throws QgsServerApiBadRequestError in case of errors.
|
|
*
|
|
* Path fragments from the named groups in the path() regular expression
|
|
* are also added to the map.
|
|
*
|
|
* Your handleRequest method should call this function to retrieve
|
|
* the parameters map.
|
|
*
|
|
* \returns the validated parameters map by extracting captured
|
|
* named parameters from the path (no validation is performed on
|
|
* the type because the regular expression can do it),
|
|
* and the query string parameters.
|
|
*
|
|
* \see path()
|
|
* \see parameters()
|
|
* \throws QgsServerApiBadRequestError if validation fails
|
|
*/
|
|
virtual QVariantMap values( const QgsServerApiContext &context ) const SIP_THROW( QgsServerApiBadRequestException );
|
|
|
|
/**
|
|
* Looks for the first ContentType match in the accept header and returns its mime type,
|
|
* returns an empty string if there are not matches.
|
|
*/
|
|
QString contentTypeForAccept( const QString &accept ) const;
|
|
|
|
// /////////////////////////////////////////////////////
|
|
// Utility methods: override should not be required
|
|
|
|
#ifndef SIP_RUN // Skip SIP
|
|
|
|
/**
|
|
* Writes \a data to the \a context response stream, content-type is calculated from the \a context request,
|
|
* optional \a htmlMetadata for the HTML templates can be specified and will be added as "metadata" to
|
|
* the HTML template variables.
|
|
*
|
|
* HTML output uses a template engine.
|
|
*
|
|
* Available template functions:
|
|
* See: https://github.com/pantor/inja#tutorial
|
|
*
|
|
* Available custom template functions:
|
|
* - path_append( path ): appends a directory path to the current url
|
|
* - path_chomp( n ):removes the specified number "n" of directory components from the current url path
|
|
* - json_dump( ): prints current JSON data passed to the template
|
|
* - static( path ): returns the full URL to the specified static path, for example:
|
|
* static( "/style/black.css" ) will return something like "/wfs3/static/style/black.css".
|
|
* - links_filter( links, key, value ): Returns filtered links from a link list
|
|
* - content_type_name( content_type ): Returns a short name from a content type for example "text/html" will return "HTML"
|
|
*
|
|
* \note not available in Python bindings
|
|
*/
|
|
void write( json &data, const QgsServerApiContext &context, const json &htmlMetadata = nullptr ) const;
|
|
|
|
/**
|
|
* Writes \a data to the \a context response stream as JSON
|
|
* (indented if debug is active), an optional \a contentType can be specified.
|
|
*
|
|
* \note not available in Python bindings
|
|
*/
|
|
void jsonDump( json &data, const QgsServerApiContext &context, const QString &contentType = QStringLiteral( "application/json" ) ) const;
|
|
|
|
/**
|
|
* Writes \a data as HTML to the response stream in \a context using a template.
|
|
*
|
|
* \see templatePath()
|
|
* \note not available in Python bindings
|
|
*/
|
|
void htmlDump( const json &data, const QgsServerApiContext &context ) const;
|
|
|
|
/**
|
|
* Returns handler information from the \a context for the OPENAPI description (id, description and other metadata) as JSON.
|
|
* It may return a NULL JSON object in case the handler does not need to be included in the API.
|
|
*
|
|
* \note requires a valid project to be present in the context
|
|
* \note not available in Python bindings
|
|
*/
|
|
virtual json schema( const QgsServerApiContext &context ) const;
|
|
|
|
/**
|
|
* Builds and returns a link to the resource.
|
|
*
|
|
* \param context request context
|
|
* \param linkType type of the link (rel attribute), default to SELF
|
|
* \param contentType content type of the link (default to JSON)
|
|
* \param title title of the link
|
|
* \note not available in Python bindings
|
|
*/
|
|
json link( const QgsServerApiContext &context,
|
|
const QgsServerOgcApi::Rel &linkType = QgsServerOgcApi::Rel::self,
|
|
const QgsServerOgcApi::ContentType contentType = QgsServerOgcApi::ContentType::JSON,
|
|
const std::string &title = "" ) const;
|
|
|
|
/**
|
|
* Returns all the links for the given request \a context.
|
|
*
|
|
* The base implementation returns the alternate and self links, subclasses may
|
|
* add other links.
|
|
*
|
|
* \note not available in Python bindings
|
|
*/
|
|
json links( const QgsServerApiContext &context ) const;
|
|
|
|
|
|
/**
|
|
* Returns a vector layer instance from the "collectionId" parameter of the path in the given \a context,
|
|
* requires a valid project instance in the context.
|
|
*
|
|
* \note not available in Python bindings
|
|
*
|
|
* \throws QgsServerApiNotFoundError if the layer could not be found
|
|
* \throws QgsServerApiImproperlyConfiguredException if project is not set
|
|
*/
|
|
QgsVectorLayer *layerFromContext( const QgsServerApiContext &context ) const;
|
|
|
|
#endif // SIP skipped
|
|
|
|
/**
|
|
* Writes \a data to the \a context response stream, content-type is calculated from the \a context request,
|
|
* optional \a htmlMetadata for the HTML templates can be specified and will be added as "metadata" to
|
|
* the HTML template variables.
|
|
*
|
|
* HTML output uses a template engine.
|
|
*
|
|
* Available template functions:
|
|
* See: https://github.com/pantor/inja#tutorial
|
|
*
|
|
* Available custom template functions:
|
|
* - path_append( path ): appends a directory path to the current url
|
|
* - path_chomp( n ): removes the specified number "n" of directory components from the current url path
|
|
* - json_dump(): prints current JSON data passed to the template
|
|
* - static( path): returns the full URL to the specified static path, for example:
|
|
* static("/style/black.css") will return something like "/wfs3/static/style/black.css".
|
|
* - links_filter( links, key, value ): returns filtered links from a link list
|
|
* - content_type_name( content_type ): returns a short name from a content type for example "text/html" will return "HTML"
|
|
*
|
|
*/
|
|
void write( QVariant &data, const QgsServerApiContext &context, const QVariantMap &htmlMetadata = QVariantMap() ) const SIP_THROW( QgsServerApiBadRequestException );
|
|
|
|
/**
|
|
* Returns an URL to self, to be used for links to the current resources and as a base for constructing links to sub-resources
|
|
*
|
|
* \param context the current request context
|
|
* \param extraPath an optional extra path that will be appended to the calculated URL
|
|
* \param extension optional file extension to add (the dot will be added automatically).
|
|
*/
|
|
std::string href( const QgsServerApiContext &context, const QString &extraPath = QString(), const QString &extension = QString() ) const;
|
|
|
|
/**
|
|
* Returns the HTML template path for the handler in the given \a context
|
|
*
|
|
* The template path is calculated from QgsServerSettings's apiResourcesDirectory() as follow:
|
|
* apiResourcesDirectory() + "/ogc/templates/" + context.apiRootPath + operationId + ".html"
|
|
* e.g. for an API with root path "/wfs3" and an handler with operationId "collectionItems", the path
|
|
* will be apiResourcesDirectory() + "/ogc/templates/wfs3/collectionItems.html"
|
|
*/
|
|
const QString templatePath( const QgsServerApiContext &context ) const;
|
|
|
|
/**
|
|
* Returns the absolute path to the base directory where static resources for
|
|
* this handler are stored in the given \a context.
|
|
*
|
|
*/
|
|
const QString staticPath( const QgsServerApiContext &context ) const;
|
|
|
|
/**
|
|
* Returns the content type from the \a request.
|
|
*
|
|
* The path file extension is examined first and checked for known mime types,
|
|
* the "Accept" HTTP header is examined next.
|
|
* Fallback to the default content type of the handler if none of the above matches.
|
|
*
|
|
* \throws QgsServerApiBadRequestError if the content type of the request is not compatible with the handler (\see contentTypes member)
|
|
*/
|
|
QgsServerOgcApi::ContentType contentTypeFromRequest( const QgsServerRequest *request ) const;
|
|
|
|
/**
|
|
* Returns a link to the parent page up to \a levels in the HTML hierarchy from the given \a url, MAP query argument is preserved
|
|
*/
|
|
static QString parentLink( const QUrl &url, int levels = 1 );
|
|
|
|
/**
|
|
* Returns a vector layer from the \a collectionId in the given \a context
|
|
*/
|
|
static QgsVectorLayer *layerFromCollection( const QgsServerApiContext &context, const QString &collectionId );
|
|
|
|
/**
|
|
* Returns the defaultResponse as JSON
|
|
*
|
|
* \note not available in Python bindings
|
|
*/
|
|
static json defaultResponse() SIP_SKIP;
|
|
|
|
/**
|
|
* Returns tags as JSON
|
|
*
|
|
* \see tags()
|
|
*
|
|
* \note not available in Python bindings
|
|
*/
|
|
json jsonTags( ) const SIP_SKIP;
|
|
|
|
|
|
};
|
|
|
|
#endif // QGSSERVEROGCAPIHANDLER_H
|