-
-
Notifications
You must be signed in to change notification settings - Fork 279
pygeoapi does not respect header q values #1948
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
Labels
bug
Something isn't working
Comments
Untested: diff --git a/pygeoapi/api/__init__.py b/pygeoapi/api/__init__.py
index 7ce3ec4..854d667 100644
--- a/pygeoapi/api/__init__.py
+++ b/pygeoapi/api/__init__.py
@@ -339,7 +339,7 @@ class APIRequest:
h = headers.get('accept', headers.get('Accept', '')).strip() # noqa
(fmts, mimes) = zip(*FORMAT_TYPES.items())
# basic support for complex types (i.e. with "q=0.x")
- for type_ in (t.split(';')[0].strip() for t in h.split(',') if t):
+ for type_ in sorted(h.split(','), key=lambda x: x.split('q=')[-1], reverse=True): # noqa
if type_ in mimes:
idx_ = mimes.index(type_)
format_ = fmts[idx_] |
Its worth noting we technically allow the type of preference setting for the following headers def get_choice_from_headers(headers: dict,
header_name: str,
all: bool = False) -> Any:
"""
Gets choices from a request dictionary,
considering numerical ordering of preferences.
Supported are complex preference strings (e.g. "fr-CH, fr;q=0.9, en;q=0.8")
:param headers: `dict` of request headers.
:param header_name: Name of request header.
:param all: bool to return one or all header values.
:returns: Sorted choices from header
"""
try:
# Clean headers and select header of interest
cleaned_headers = {k.lower(): v for k, v in headers.items()}
header = cleaned_headers[header_name.lower()].split(',')
except:
LOGGER.warning(f'Requested header not found: {header_name}')
return
# Parse choices, extracting optional q values (defaults to 1.0)
choices = []
for i, part in enumerate(header):
match = re.match(r'^([^;]+)(?:;q=([\d.]+))?$', part.strip())
if match:
value, q_value = match.groups()
q_value = float(q_value) if q_value else 1.0
# Sort choices by q value and index
if 0 <= q_value <= 1:
heapq.heappush(choices, (1 / q_value, i, value))
# Drop q value
sorted_choices = [choice[-1] for choice in choices]
# Return one or all choices
return sorted_choices if all else sorted_choices[0] |
5 tasks
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Description
When sending a request to pygeoapi with multiple values in accept parameter, pygeoapi takes the first item instead of evaluating the q values of all options sent in the header.
Steps to Reproduce
Steps to reproduce the behavior:
Accept: application/json;q=0.5,application/ld+json;q=1
Expected behavior
pygeoapi evaluates the full header context to decide the most appropriate header to send in the response.
Screenshots/Tracebacks
If applicable, add screenshots to help explain your problem.
Environment
Additional context
Add any other context about the problem here.
The text was updated successfully, but these errors were encountered: