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
501 stars 264 forks source link

Missing Access-Control-Expose-Headers: Location #1689

Closed troll-git closed 3 months ago

troll-git commented 4 months ago

Description I am trying to get a response header in an application that sends an asynchronous request to processes api. Returnes status code is 201 but i cannot access response headers specifically location that i need in order to obtain status when using a javascript application Steps to Reproduce Steps to reproduce the behavior:

Expected behavior for example this function does not return header const handleClick = async () => { const payload = { "inputs": { "layer_index": 0, "url": "https://example.com/MapServer" } }; // Example payload const headers = { 'Content-Type': 'application/json', Prefer: 'respond-async' };

  try {
    const response = await fetch('https://pygeoapi.test.no/processes/geoservice/execution', {
      method: 'POST',
      headers,
      body: JSON.stringify(payload)
    });

    // Check if response is successful
    if (response.ok) {
      // Use the Response.headers.get() method to retrieve the Location header
      const locationHeader = response.headers.get('Location');

      // Check if Location header exists and is not empty
      if (locationHeader) {
        alert(`Location header content: ${locationHeader}`);
      } else {
        alert('Location header not found or empty in response');
      }
    } else {
      alert('Failed to fetch');
    }
  } catch (error) {
    console.error('Error:', error);
    alert('An error occurred, please check the console.');
  }
}

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

Environment

Additional context accordinf to mdn Access-Control-Expose-Headers needs to be enabled on the server. Is there such setting for pygeoapi? https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

francescoingv commented 4 months ago

Which ProcessManager did you set? The default does not accept asynch.

Did you check the process description returned by the API accept asynch?

Possibly the API returned synch. Did you check it?

troll-git commented 4 months ago

in local.config I used the default but in docs it says that asynchronous process execution is supported when using Prefer: respond-async header. I am sure that it was called asynchronously as i got 201 code +response header. THe problem is that response.header - location is not accessible when trying to access from application running in webbrowser. As I mentioned before Access-Control-Expose-Headers is missing in response header which seems to be the issue here. Otherwise how is it possible to do it differently?

francescoingv commented 4 months ago

Which pygeoapi "docs" do you refer?

Asynch IS supported by pygeoapi, but IS NOT supported by the default ProcessManager. To use asynch you need to properly configure geoapi to use a ProcessManager that supports asynch: tinydb is an example.

As said above, I suggest you check first the process description.

For me the simplest approach is to use curl command, not the browser.

You need to use the entrypoit processes/

troll-git commented 4 months ago

https://docs.pygeoapi.io/en/latest/data-publishing/ogcapi-processes.html#asynchronous-support Everything works (curl,python, thunderclient ...) However the task here is to read response header from web application. It is not a discussion on process manager. It is about accessing response header returned by pygeoapi. I am running pygeoapi in docker btw

tomkralidis commented 4 months ago

@troll-git example using curl:

curl -s -v -X 'POST' \
  'http://localhost:5000/processes/hello-world/execution' \
  -H 'Prefer: response-async' \
  -H 'Accept: application/json' \
  -H 'Content-Type: application/json' \
  -d '{
  "inputs": {
    "message": "An optional message.",
    "name": "World"
  }
}'

You will see the various response headers as part of the curl response (including the Location header).

troll-git commented 4 months ago

This is all correct. As I mentioned before, I was able to access location header using curl or different way. However I said that location header is not accessible to a javascript application running in browser. I have mentioned this in my previous comment. I can read reponse header location but not via application in browser. I have pasted a js function above to replicate the issue. PLease refer to this: according to mdn Access-Control-Expose-Headers needs to be enabled on the server. Is there such setting for pygeoapi? https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers. Please check this thread https://github.com/ladjs/superagent/issues/770. In flask app https://flask-cors.readthedocs.io/en/latest/configuration.html specific headers are exposed using CORS_EXPOSE_HEADERS .

tomkralidis commented 3 months ago

Reproduced (my own snippet below for refeence):

<!DOCTYPE html>
<html>
<body>

<h1>JavaScript Fetch API test</h1>
<p id="demo">Fetch a file to change this text.</p>

<script>
let file = "http://127.0.0.1:5000/processes/hello-world/execution"
fetch (file, {
    method: "POST",
    headers: {"Prefer": "respond-async"},
    body: '{"inputs": {"message": "hi", "name": "foo"}}',
    mode: "cors"
    }
)
.then(x => x.headers.get('Content-Type'))
.then(y => document.getElementById("demo").innerHTML = y);
</script>

</body>
</html>