1 /***************************************************************************
2                           qgsserverapi.h
3 
4   Class defining the service interface for QGIS server APIs.
5   -------------------
6   begin                : 2019-04-16
7   copyright            : (C) 2019 by Alessandro Pasotti
8   email                : elpaso at itopen dot it
9  ***************************************************************************/
10 
11 /***************************************************************************
12  *                                                                         *
13  *   This program is free software; you can redistribute it and/or modify  *
14  *   it under the terms of the GNU General Public License as published by  *
15  *   the Free Software Foundation; either version 2 of the License, or     *
16  *   (at your option) any later version.                                   *
17  *                                                                         *
18  ***************************************************************************/
19 
20 
21 
22 #ifndef QGSSERVERAPI_H
23 #define QGSSERVERAPI_H
24 
25 #include "qgis_server.h"
26 #include <QRegularExpression>
27 #include "qgsserverexception.h"
28 #include "qgsserverrequest.h"
29 
30 class QgsServerResponse;
31 class QgsProject;
32 class QgsServerApiContext;
33 class QgsServerInterface;
34 
35 /**
36  * \ingroup server
37  * \brief Server generic API endpoint abstract base class.
38  *
39  * \see QgsServerOgcApi for an OGC API (aka WFS3) implementation.
40  *
41  * An API must have a name and a (possibly empty) version and define a
42  * (possibly empty) root path (e.g. "/wfs3").
43  *
44  * The server routing logic will check incoming request URLs by passing them
45  * to the API's accept(url) method, the default implementation performs a simple
46  * check for the presence of the API's root path string in the URL.
47  * This simple logic implies that APIs must be registered in reverse order from the
48  * most specific to the most generic: given two APIs with root paths '/wfs' and '/wfs3',
49  * '/wfs3' must be registered first or it will be shadowed by '/wfs'.
50  * APIs developers are encouraged to implement a more robust accept(url) logic by
51  * making sure that their APIs accept only URLs they can actually handle, if they do,
52  * the APIs registration order becomes irrelevant.
53  *
54  * After the API has been registered to the server API registry:
55  *
56  * \code{.py}
57  *   class API(QgsServerApi):
58  *
59  *     def name(self):
60  *       return "Test API"
61  *
62  *     def rootPath(self):
63  *       return "/testapi"
64  *
65  *     def executeRequest(self, request_context):
66  *       request_context.response().write(b"\"Test API\"")
67  *
68  *   server = QgsServer()
69  *   api = API(server.serverInterface())
70  *   server.serverInterface().serviceRegistry().registerApi(api)
71  * \endcode
72  *
73  * the incoming calls with an URL path starting with the API root path
74  * will be routed to the first matching API and executeRequest() method
75  * of the API will be invoked.
76  *
77  *
78  * \since QGIS 3.10
79  */
80 class SERVER_EXPORT QgsServerApi
81 {
82 
83   public:
84 
85     /**
86      * Creates a QgsServerApi object
87      */
88     QgsServerApi( QgsServerInterface *serverIface );
89 
90     virtual ~QgsServerApi() = default;
91 
92     /**
93      * Returns the API name
94      */
95     virtual const QString name() const = 0;
96 
97     /**
98      * Returns the API description
99      */
100     virtual const QString description() const = 0;
101 
102     /**
103      * Returns the version of the service
104      * \note the default implementation returns an empty string
105      */
version()106     virtual const QString version() const { return QString(); }
107 
108     /**
109      * Returns the root path for the API
110      */
111     virtual const QString rootPath() const = 0;
112 
113     /**
114      * Returns TRUE if the given \a url is handled by the API, default implementation checks for the presence of rootPath inside the \a url path.
115      */
116     virtual bool accept( const QUrl &url ) const;
117 
118     /**
119      * Executes a request by passing the given \a context to the API handlers.
120      */
121     virtual void executeRequest( const QgsServerApiContext &context ) const = 0;
122 
123     /**
124      * Returns the server interface
125      */
126     QgsServerInterface *serverIface() const;
127 
128   private:
129 
130     QgsServerInterface *mServerIface = nullptr;
131 };
132 
133 
134 #endif // QGSSERVERAPI_H
135 
136 
137