Skip to content

fix: honor Kiota request extensions in Graph transport - #1129

Open
RKS (rksharma-owg) wants to merge 1 commit into
microsoftgraph:mainfrom
rksharma-owg:codex/graph-kiota-request-options
Open

RKS (rksharma-owg) wants to merge 1 commit into
microsoftgraph:mainfrom
rksharma-owg:codex/graph-kiota-request-options

Conversation

@rksharma-owg

Copy link
Copy Markdown

Overview

Restore Graph middleware execution for requests built by microsoft-kiota-http 1.13.0. Graph-core 1.5.1 only enters its middleware pipeline when an HTTPX request has the legacy .options attribute. Kiota commit d9180bb moved per-request options to request.extensions["kiota_request_options"], so the Graph transport bypasses redirect, URL replacement, retry, and telemetry middleware. For an empty 302 response from DriveItem /content, this makes the binary request return None instead of following the download URL.

Accept the extension-based options while retaining support for the legacy attribute used by earlier Kiota releases. Graph request context now receives the extension options when present. No public API or generated SDK changes are needed.

Fixes #1128. Related: microsoft/kiota-python#745 and microsoft/kiota-python#744.

Notes

A credential-free HTTPX transport reproduction returned None after one 302 with Kiota HTTP 1.13.0, but followed the redirect and returned bytes with 1.12.3. The new integration test failed on the unmodified Graph-core transport and passes with this change. It covers two binary content types, legacy option compatibility, extension precedence, and requests without options.

The full-tree isort --check-only src reports an unchanged import-order issue in batch_request_item.py; the repository's actual CI command, isort src, succeeds and only reorders that existing file in an isolated checkout. No unrelated formatting is included here.

Testing Instructions

  • Run pytest after installing requirements-dev.txt: 78 passed locally with its pinned Kiota HTTP 1.11.6.
  • With Kiota HTTP 1.13.0 and HTTPX 0.27.0, run pytest: 78 passed locally on Python 3.12.
  • Run yapf -dr src, mypy src, and pylint src --disable=W --rcfile=.pylintrc: passed locally. Changed-file isort --check-only and sdist/wheel build also passed.
  • Fork preflight checked out contribution SHA b8d5927c651c5e049a132021e72f8d01c83d5021 against upstream base ec79992519f708a014676584d5626ea8d733fe2c: Python 3.10–3.14 × Kiota HTTP 1.11.6/1.13.0 (10 jobs, 78 tests each), format, changed-file import order, mypy, pylint, and CodeQL passed: https://github.com/rksharma-owg/msgraph-sdk-python-core/actions/runs/35680942215.

@rksharma-owg
RKS (rksharma-owg) requested a review from a team as a code owner September 22, 2026 02:53
@sonarqubecloud

Copy link
Copy Markdown

@Mrfence97

Copy link
Copy Markdown

Hi team, is there an update on getting this reviewed? And is there a plan to issue a hotfix release once it's done?

@rksharma-owg

Copy link
Copy Markdown
Author

Thanks for checking in. The fix is ready for review, and the checks currently reported on this PR are passing. I don't have an estimate for maintainer review or a hotfix release; the maintainers will decide the release timing after reviewing the change.

Michael Palermiti (mpalermiti) added a commit to mpalermiti/outlook-mcp that referenced this pull request Sep 30, 2026
…K placeholder (#81)

* fix(deps): cap kiota below 1.13 — /me was reaching the wire as the SDK placeholder

A fresh `uv tool install outlook-graph-mcp` resolved microsoft-kiota-*
1.13+ and every /me call failed with "me-token-to-replace is invalid"
(#80). kiota 1.13.0 (2026-09-18) moved per-request options from a
monkey-patched `request.options` attribute to
`request.extensions["kiota_request_options"]`, and its UrlReplaceHandler
now reads only the new place. msgraph-core 1.5.1, the latest release,
still reads `request.options` in middleware/async_graph_transport.py, so
the rewrite it installs for `/users/me-token-to-replace` -> `/me` never
fires and Graph receives the literal placeholder. The upstream fix is
microsoftgraph/msgraph-sdk-python-core#1129, open and unreleased.

Nothing capped kiota; msgraph-core itself allows <2.0. The lock pinned
1.12.3, so `uv sync`, every CI job and every developer install were
green while every new user's install was broken — the fresh-install
and published-install canaries imported the package, counted the tools
and never sent a request. Same class as the five-week outage.

The kiota family is capped below 1.13 until a msgraph-core release
carries #1129; the lock is unchanged at 1.12.3.

tests/test_me_rewrite_reaches_the_wire.py builds the client exactly
as msgraph does, hands the factory an httpx client on a mock transport,
and asserts on the URL the real middleware pipeline sends. It runs
against whatever the environment resolved, which is the point. Verified
by mutation: under the lock it passes; against kiota 1.14.0 it fails on
`.../users/me-token-to-replace`. Both install jobs in ci.yml now run it
as a script after their version report. Note the published-install job
installs PyPI-latest, which IS broken, so that weekly job will be red
until the next release ships — that is the canary doing its job.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LparmojWQ3m9tcJhRGqZjP

* test(wire): the nested /me path is rewritten too, and says why

Graph tolerates /users/<anything> one segment deep, so a bare /me health
check returns 200 with the placeholder still in the URL while every nested
path 404s. A canary that probed Graph with /me alone would stay green
(Nyaecho, #80). Asserting on the URL string catches both; the nested case
carries the explanation.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LparmojWQ3m9tcJhRGqZjP

---------

Co-authored-by: Michael Palermiti <253352132+mpalermiti@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Michael Palermiti (mpalermiti) added a commit to mpalermiti/outlook-mcp that referenced this pull request Sep 30, 2026
…K placeholder (#81)

* fix(deps): cap kiota below 1.13 — /me was reaching the wire as the SDK placeholder

A fresh `uv tool install outlook-graph-mcp` resolved microsoft-kiota-*
1.13+ and every /me call failed with "me-token-to-replace is invalid"
(#80). kiota 1.13.0 (2026-09-18) moved per-request options from a
monkey-patched `request.options` attribute to
`request.extensions["kiota_request_options"]`, and its UrlReplaceHandler
now reads only the new place. msgraph-core 1.5.1, the latest release,
still reads `request.options` in middleware/async_graph_transport.py, so
the rewrite it installs for `/users/me-token-to-replace` -> `/me` never
fires and Graph receives the literal placeholder. The upstream fix is
microsoftgraph/msgraph-sdk-python-core#1129, open and unreleased.

Nothing capped kiota; msgraph-core itself allows <2.0. The lock pinned
1.12.3, so `uv sync`, every CI job and every developer install were
green while every new user's install was broken — the fresh-install
and published-install canaries imported the package, counted the tools
and never sent a request. Same class as the five-week outage.

The kiota family is capped below 1.13 until a msgraph-core release
carries #1129; the lock is unchanged at 1.12.3.

tests/test_me_rewrite_reaches_the_wire.py builds the client exactly
as msgraph does, hands the factory an httpx client on a mock transport,
and asserts on the URL the real middleware pipeline sends. It runs
against whatever the environment resolved, which is the point. Verified
by mutation: under the lock it passes; against kiota 1.14.0 it fails on
`.../users/me-token-to-replace`.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LparmojWQ3m9tcJhRGqZjP

* test(wire): the nested /me path is rewritten too, and says why

Graph tolerates /users/<anything> one segment deep, so a bare /me health
check returns 200 with the placeholder still in the URL while every nested
path 404s. A canary that probed Graph with /me alone would stay green
(Nyaecho, #80). Asserting on the URL string catches both; the nested case
carries the explanation.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LparmojWQ3m9tcJhRGqZjP

(cherry picked from commit d16bd30 onto v1.22.0 for the
1.22.1 hotfix; CHANGELOG entry rewritten as a 1.22.1 section. The ci.yml step that runs
this test in the install jobs is not part of #81 as merged and is not included here.)

---------

Co-authored-by: Michael Palermiti <253352132+mpalermiti@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AsyncGraphTransport silently skips the entire middleware pipeline (URL-replace, retry, redirect) with microsoft-kiota-http>=1.13.0

2 participants