geopython / pygeoapi

pygeoapi is a Python server implementation of the OGC API suite of standards. The project emerged as part of the next generation OGC API efforts in 2018 and provides the capability for organizations to deploy a RESTful OGC API endpoint using OpenAPI, GeoJSON, and HTML. pygeoapi is open source and released under an MIT license.
https://pygeoapi.io
MIT License
483 stars 258 forks source link

Setting SCRIPT_NAME is not reflected in the links of the JSON content #206

Closed francbartoli closed 5 years ago

francbartoli commented 5 years ago

Description If running pygeoapi behind an AWS API Gateway and SCRIPT_NAME is set then the requests are returning content with wrong links:

{
    "collections": [
        {
            "links": [
                {
                    "type": "text/html",
                    "rel": "canonical",
                    "title": "information",
                    "href": "http://localhost/layers/geonode%3Aadm_iso2_type",
                    "hreflang": "en-EN"
                },
                {
                    "type": "application/geo+json",
                    "rel": "item",
                    "title": "Features as GeoJSON",
                    "href": "http://localhost:5000/collections/countries/items?f=json"
                },
                {
                    "type": "text/html",
                    "rel": "item",
                    "title": "Features as HTML",
                    "href": "http://localhost:5000/collections/countries/items?f=html"
                },
                {
                    "type": "application/json",
                    "rel": "self",
                    "title": "This document as JSON",
                    "href": "http://localhost:5000/collections/countries?f=json"
                },
                {
                    "type": "text/html",
                    "rel": "alternate",
                    "title": "This document as HTML",
                    "href": "http://localhost:5000/collections/countries?f=html"
                }
            ],
            "crs": [
                "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
            ],
            "name": "countries",
            "title": "Admin0 countries.",
            "description": "Admin0 world countries.",
            "keywords": [
                "admin0",
                "countries"
            ],
            "extent": [
                -180,
                -90,
                180,
                90
            ]
        }
    ],
    "links": [
        {
            "type": "application/json",
            "rel": "self",
            "title": "This document as JSON",
            "href": "http://localhost:5000/collections?f=json"
        },
        {
            "type": "text/html",
            "rel": "alternate",
            "title": "This document as HTML",
            "href": "http://localhost:5000/collections?f=html"
        }
    ]
}

Steps to Reproduce docker run -p 5000:80 -e SCRIPT_NAME=/geoapi -it geoapi/countries run

Expected behavior

{
    "collections": [
        {
            "links": [
                {
                    "type": "text/html",
                    "rel": "canonical",
                    "title": "information",
                    "href": "http://localhost/layers/geonode%3Aadm_iso2_type",
                    "hreflang": "en-EN"
                },
                {
                    "type": "application/geo+json",
                    "rel": "item",
                    "title": "Features as GeoJSON",
                    "href": "http://localhost:5000/geoapi/collections/countries/items?f=json"
                },
                {
                    "type": "text/html",
                    "rel": "item",
                    "title": "Features as HTML",
                    "href": "http://localhost:5000/geoapi/collections/countries/items?f=html"
                },
                {
                    "type": "application/json",
                    "rel": "self",
                    "title": "This document as JSON",
                    "href": "http://localhost:5000/geoapi/collections/countries?f=json"
                },
                {
                    "type": "text/html",
                    "rel": "alternate",
                    "title": "This document as HTML",
                    "href": "http://localhost:5000/geoapi/collections/countries?f=html"
                }
            ],
            "crs": [
                "http://www.opengis.net/def/crs/OGC/1.3/CRS84"
            ],
            "name": "countries",
            "title": "Admin0 countries.",
            "description": "Admin0 world countries.",
            "keywords": [
                "admin0",
                "countries"
            ],
            "extent": [
                -180,
                -90,
                180,
                90
            ]
        }
    ],
    "links": [
        {
            "type": "application/json",
            "rel": "self",
            "title": "This document as JSON",
            "href": "http://localhost:5000/geoapi/collections?f=json"
        },
        {
            "type": "text/html",
            "rel": "alternate",
            "title": "This document as HTML",
            "href": "http://localhost:5000/geoapi/collections?f=html"
        }
    ]
}

Screenshots/Tracebacks If applicable, add screenshots to help explain your problem.

Environment Docker based

Additional context Add any other context about the problem here.

justb4 commented 5 years ago

@francbartoli good you opened this issue! IMO there is indeed a problem, at least an inflexibility which, I think/hope, may be overcome, but will require some hard thinking and testing many constellations.

Inflexibility: the endpoint URL is now to be configured under server: within the pygeoapi config YAML. For the Docker image it is default:

server:
    bind:
        host: 0.0.0.0
        port: 80
    url: http://localhost:5000
    mimetype: application/json; charset=UTF-8
.
.

So http://localhost:5000 is your endpoint URL by default. But e.g. for the https://demo.pygeoapi.io/master instance, see local.config.yml. This may solve your problem short-term?

I think it should not be necessary to configure url (like e.g. not required in GeoServer) as it could be determined from incoming requests (SCRIPT name, PROXY, FORWARDED -HTTP headers etc). Here the hard thinking begins. I have deployed Flask apps without needing this url, but when an app needs to return full URLs back to the client we need some intelligence in the Flask app that should work in standalone and reverseproxied deployments...

There's various solutions found with some web-search like:

I hope someone can fill in/suggest further from here?

francbartoli commented 5 years ago

@justb4 thanks, probably both are really helpful! The links are now correctly served if the url in the configuration file has:

server:
    bind:
        host: 0.0.0.0
        port: 80
    url: http://localhost:5000/geoapi
    mimetype: application/json; charset=UTF-8

and the command still has SCRIPT_NAME:

docker run -p 5000:80 -e SCRIPT_NAME=/geoapi -it geoapi/countries run