Skip to content

Expose response headers alongside parsed payload for v2 pagination #149

Description

@admincheg

Problem

Some OVHcloud v2 API endpoints expose functional response metadata through HTTP response headers.

A concrete example is:

GET /v2/publicCloud/project/{projectId}/network

In a live response from this endpoint, pagination metadata is exposed through headers including:

  • X-Pagination-Elements
  • X-Pagination-Cursor-Next

The current python-ovh API makes it difficult to consume both the decoded response body and this metadata from a single request.

The documented high-level helpers (get(), post(), put(), delete()) and Client.call() return the parsed JSON response, while Client.raw_call() provides access to the underlying requests.Response.

For example:

networks = client.get(
    f"/v2/publicCloud/project/{project_id}/network"
)

provides the decoded network list, but the response headers are no longer available to the caller.

Using:

response = client.raw_call(
    "GET",
    f"/v2/publicCloud/project/{project_id}/network",
)

provides the pagination headers, but now the caller is operating below the normal Client.call() response/error handling.

Practical consequence

A consumer that wants to retain the normal high-level handling while also observing the pagination metadata currently has two unattractive choices:

  1. reproduce the relevant Client.call() response/error handling around raw_call(), or
  2. perform the request twice: once through get() for the normal decoded result/error semantics, and once through raw_call() to inspect the response headers.

We currently use the second approach as a conservative workaround. This means two identical read-only API requests are required to obtain information that was present in a single HTTP response.

Expected / proposed capability

Would you consider exposing response metadata while preserving the existing high-level parsing and error handling?

For example, this could be a separate API:

result = client.call_with_response(
    "GET",
    f"/v2/publicCloud/project/{project_id}/network",
)

result.data
result.headers

or an optional mode on Client.call():

result = client.call(
    "GET",
    path,
    return_response=True,
)

The exact interface is not important; a backwards-compatible solution would be preferable.

The important capability is to obtain both:

  • the normally decoded/validated result; and
  • functional response metadata such as pagination headers

from the same HTTP request.

Why this matters

raw_call() is documented as the lowest-level interface for cases requiring access to the raw requests.Response.

However, response headers are no longer necessarily only diagnostic or advanced metadata: newer v2 API endpoints can use them as part of their functional API contract, notably for pagination.

This creates a gap between the recommended high-level interface and the information required to correctly consume such endpoints.

Reproduction

With a project containing public-cloud networks:

import ovh

client = ovh.Client()

path = f"/v2/publicCloud/project/{project_id}/network"

data = client.get(path)

raw = client.raw_call("GET", path)

print(type(data))
print(raw.headers.get("X-Pagination-Elements"))
print(raw.headers.get("X-Pagination-Cursor-Next"))

The first request provides the normal decoded payload but not its response headers. The second exposes the pagination metadata through the underlying response object.

This was observed against the live OVHcloud EU API.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions