Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

QGIS Server API support (WFS3 & C.) #144

Closed
elpaso opened this issue May 6, 2019 · 6 comments
Closed

QGIS Server API support (WFS3 & C.) #144

elpaso opened this issue May 6, 2019 · 6 comments

Comments

@elpaso
Copy link

elpaso commented May 6, 2019

QGIS Server API support (WFS3 & C.)

Date 2019/05/07

Author Alessandro Pasotti (@elpaso)

Contact elpaso at itopen dot it

maintainer @elpaso

Version QGIS 3.10 (maybe)

Summary

Provided that OGC is moving towards OpenAPI for WFS3 (and probably other services too), we need to rework the dispatcher system in QGIS Server (now based on SERVICE=... query string parameter).

Hereby I'm proposing a new QGIS Server API (very similar to the existing API for service modules) that would allow to register endpoints to a certain path.

Proposed Solution

Here is how it's supposed to work:

class API(QgsServerApi):

    def name(self):
        return "Test API"

    def rootPath(self):
        return "/testapi"

    def executeRequest(self, request, response, project):
        response.write(b"\"Test API\"")

api = API()
self.server.serverInterface().serviceRegistry().registerApi(api)

The new dispatcher inside the QgsServersers handle request method will first check if the request contains any SERVICE parameter, if it does it assumes it is a legacy OGC service, if not, before bailing out with an "unsupported service" error it will check for any registered api that matches the request path.

The a.m. test API would for instance respond to this call:

QgsBufferServerRequest('http://www.acme.com/testapi')

The QgsServerApi interface (abstract class) would expose some limited methods and since the first use case of this API will probably be WFS3, along the way we could expect some more methods to be factored out and become part of the interface.

This is a preliminary implementation:

/**
 * Server API endpoint abstract base class
 * \since QGIS 3.10
 */
class SERVER_EXPORT QgsServerApi
{

  public:

    QgsServerApi( ) = default;
    virtual ~QgsServerApi() = default;

    /**
     * \returns the name of the API
     */
    virtual QString name() const = 0;

    /**
     * \returns the version of the service
     */
    virtual QString version() const = 0;

    /**
     * \returns the root path for the API
     */
    virtual QString rootPath() const = 0;

    /**
     * Returns TRUE if the given method is supported by the API, default implementation supports all methods.
     */
    virtual bool allowMethod( QgsServerRequest::Method ) const { return true; }

    /**
     * Execute the requests and set result in QgsServerResponse
     */
    virtual void executeRequest( const QgsServerRequest &request,
                                 QgsServerResponse &response, const QgsProject *project ) const = 0;


};

Example(s)

See example in previous paragraph.

Further considerations/limitations

The proposed system will match the first API and the order matters: for example it will not be able to activate two different endpoints if the root path of one of them starts with the root path of another previously added one, for example:

API 1 root path = '/api'
API 2 root path = '/api2'  # this one will never be called because "/api" matches first.

Affected Files

Mainly qgsserver.h and the server registry and interfaces.

Performance Implications

The impact on existing code is negligible.

Backwards Compatibility

No issues

Votes

(required)

@elpaso
Copy link
Author

elpaso commented May 8, 2019

@pblottiere @rldhont any comment?

@pblottiere
Copy link
Member

Hi @elpaso,

Firstly, thanks a lot for taking a look to WFS 3! It's clearly a matter of interest on which we're a bit late.

About the OpenAPI management, I like your approach as well as the proposed implementation. Indeed, it's simple and pretty straightforward.

Considering the future WFS3 service, how do you plan to reuse current classes/methods of the WFS 1.X module? Is it possible? Or do we want to write a specific module (i.e a dedicated shared library)?

But in brief: +1

@elpaso
Copy link
Author

elpaso commented May 9, 2019

Hi @elpaso,

Firstly, thanks a lot for taking a look to WFS 3! It's clearly a matter of interest on which we're a bit late.

About the OpenAPI management, I like your approach as well as the proposed implementation. Indeed, it's simple and pretty straightforward.

Considering the future WFS3 service, how do you plan to reuse current classes/methods of the WFS 1.X module? Is it possible? Or do we want to write a specific module (i.e a dedicated shared library)?

But in brief: +1

Thanks for the feedback!

I believe we'd need a brand new library for WFS3 but maybe we can factorize something common.

@dmarteau
Copy link

dmarteau commented May 9, 2019

Hi @elpaso,

Yes, moving to WFS3 require to adapt the routing workflow of the requests to be more RESTful. My deux cents that it is only a beginning to a more larger step towards REST api

AMHA, instead of adding path support as fallback to the current request routing (based solely on SERVICE) I would be in favor to refactor the server so as to put the path routing on top and let the actual behavior as the '/' root path fallback.

The idea is to implement path request rooting using of the actual qgsService implementation.
Since it a matter of changing a routing key, it should be relatively simple to implement.

@elpaso
Copy link
Author

elpaso commented May 9, 2019

@dmarteau thanks for the feedback!

About the dispatching, I liked the idea to have some kind of "home" page API responding to /, that wouldn't be possible if we leave it as a fallback for actual services.

Instead we could route the actual services through a /ows/ endpoint.

But those are really details, and once the dispatching logic is in place they can be easily changed along the way or better: why don't we refactor the actual services to be APIs themselves?

For instance we could have the WFS service to respond to /wfs/ endpoint etc. etc.

@dmarteau
Copy link

dmarteau commented May 9, 2019

Instead we could route the actual services through a /ows/ endpoint.

Yes, that scratched my mind also :-)

why don't we refactor the actual services to be APIs themselves?

I completely agree with that, and I'm pretty sure that's the correct solution. Also, looking at your proposal for api interface, I'm pretty convinced that we could reuse the actual implementation to turn it into APIs managment.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants