世界を動かす技術を、日本語で。

HTTPX2への移行

2026年8月28日原文(github.com)

概要

OpenAI Python SDKは HTTPX2 への移行を完了。 HTTPX2は 自動インストール され、旧httpxは同梱されない。 TLS設定や証明書の扱いが certifiからOS信頼ストア へ変更。 カスタムHTTPクライアントやMockも HTTPX2インターフェース へ適合が必要。 旧HTTPXとの互換性維持策も 一時的に提供 されている。

OpenAI Python SDKのHTTPX2移行ガイド

  • OpenAI Python SDKは 同期・非同期HTTPクライアント としてHTTPX2を採用
  • openaiパッケージインストール時にHTTPX2が自動導入、httpxは含まれない仕様
  • SDKのデフォルトクライアント利用時は 既存API呼び出し・認証・ストリーミング・リトライ・タイムアウト 等がそのまま動作
  • 追加のHTTPX2インストールや設定は不要pip install openaiのみで利用可能
  • 旧SDK経由でhttpxを利用していた場合は 独自にhttpx依存追加 または httpx2への移行 が必要

TLS証明書と信頼ストアの変更

  • HTTPX2は certifiのCAバンドルからOSの信頼ストア に証明書検証方法を変更
  • SDKは certifiをインストールしなくなり、OS信頼ストア未導入の環境では証明書検証が失敗する場合あり
  • 最小限のコンテナや企業プロキシ環境では OS信頼ストアのCA証明書導入 が必要
  • 明示的な証明書バンドル指定例
    • export SSL_CERT_FILE=/path/to/ca-bundle.pem
    • ディレクトリ指定: export SSL_CERT_DIR=/path/to/ca-directory
  • カスタムクライアントでの証明書指定例
    import ssl
    from openai import OpenAI, DefaultHttpx2Client
    ssl_context = ssl.create_default_context(cafile="/path/to/ca-bundle.pem")
    client = OpenAI(http_client=DefaultHttpx2Client(verify=ssl_context))
    
  • 非同期用はDefaultAsyncHttpx2Client(verify=ssl_context)を利用

カスタムHTTPクライアントの利用

  • HTTPX2クライアント・設定オブジェクト を利用する必要
  • SDK推奨のタイムアウト・接続プール・リダイレクト設定を維持するヘルパーを提供
    • 例: プロキシ経由接続
      proxy_client = OpenAI(http_client=DefaultHttpx2Client(proxy="http://proxy.example.com:8080"))
      
    • 例: カスタムトランスポート・タイムアウト
      import httpx2
      transport_client = OpenAI(
        http_client=DefaultHttpx2Client(
          transport=httpx2.HTTPTransport(local_address="0.0.0.0"),
          timeout=httpx2.Timeout(30.0, connect=5.0),
        )
      )
      
  • httpx2.Client, httpx2.AsyncClient も直接指定可能
  • DefaultHttpxClient, DefaultAsyncHttpxClientも動作するが、今後はDefaultHttpx2Client, DefaultAsyncHttpx2Clientの明示利用推奨

タイムアウト・URL・トランスポート・接続設定

  • httpx固有オブジェクトはhttpx2対応オブジェクトへ置換 が必要
    • 例:
      • httpx.Clienthttpx2.Client
      • httpx.Timeouthttpx2.Timeout
      • httpx.HTTPTransporthttpx2.HTTPTransport
  • タイムアウト数値やURL文字列は 変更不要
  • カスタムトランスポートやプロキシ設定、接続プールの拡張は httpx2インターフェース に適合

認証・イベントフック

  • 認証ハンドラやフック はhttpx2のリクエスト・レスポンスオブジェクトを受け取る
  • カスタム認証クラスやフックの型注釈も httpx2.Request/Response へ更新
  • 例:
    def log_request(request: httpx2.Request) -> None:
        print(request.method, request.url)
    client = OpenAI(http_client=DefaultHttpx2Client(event_hooks={"request": [log_request]}))
    
  • サードパーティの認証・計測・トレースは HTTPX2対応が必須

レスポンス・ストリーミング・例外

  • SDKのパース済みレスポンスモデルは変更なし
  • ネイティブHTTPX2クライアント利用時は httpx2.Request/Response 型となる
  • 例外も openai.APITimeoutErrorやopenai.APIConnectionError で捕捉、内部causeはHTTPX2例外
  • レガシーHTTPXクライアント注入時は httpx型のリクエスト・レスポンス・例外 となる

aiohttp対応

  • サポートされるaiohttp extraは HTTPX2ネイティブトランスポート を利用
  • 旧httpxやhttpx-aiohttpアダプタは インストール不要
  • pip install 'openai[aiohttp]'で導入、DefaultAioHttpClient()はhttpx2.AsyncClient相当

モック・テスト

  • モックはHTTPX2リクエスト/レスポンスをインターセプト する必要
    • 例:
      def handler(request: httpx2.Request) -> httpx2.Response:
          return httpx2.Response(200, request=request, json={"object": "list", "data": []})
      client = OpenAI(http_client=httpx2.Client(transport=httpx2.MockTransport(handler)))
      
  • テストスイートでRESPXを使う場合は HTTPX2対応版へのアップデート が必要
  • 移行が難しい場合は 一時的なレガシーHTTPXクライアント注入 による回避策あり

レガシーHTTPXクライアントの一時的利用

  • レガシーHTTPXのみ対応のトランスポートやモックライブラリ 利用時は旧httpxを明示インストールしクライアント注入
    • 例:
      from typing import Any, cast
      import httpx
      from openai import OpenAI
      client = OpenAI(http_client=cast(Any, httpx.Client()))
      
  • 非同期版も同様にcast(Any, httpx.AsyncClient())を利用
  • 型チェック(mypy, Pyright等)には cast(Any, ...)やtype-ignore で対応
  • レスポンス型もcast_to=cast(Any, httpx.Response)で指定
  • cast_to=httpx2.Responseでは型変換不可
  • レガシー依存は 自己管理、将来的にサポート終了予定

既存httpx-aiohttpアダプタ利用

  • 旧httpx-aiohttp統合が必要な場合は 明示的にインストールし、cast(Any, ...)で注入
    • 例:
      from typing import Any, cast
      from httpx_aiohttp import HttpxAiohttpClient
      from openai import AsyncOpenAI
      client = AsyncOpenAI(http_client=cast(Any, HttpxAiohttpClient()))
      
  • 互換テストはされているが 一時的な回避策 として提供
  • 新規コードでは openai[aiohttp]とDefaultAioHttpClient()の利用推奨

Hackerたちの意見

ちなみに、今はオペレーティングシステムのTLSトラストストアが使われてるよ(certifiの代わりに)。

nbって何?

これ、(一部の企業ネットワーク環境では)壊れる変更になるかも。

うわぁ、certifiってほんとにイライラする。いろんなPythonの依存関係に忍び込んで、何も良くならないし、junior devたちを混乱させるだけ。彼らのvenvsやコンテナが内部のCA署名リソースにアクセスできないときに、何をすればいいかを9000回以上説明したかも。で、何のために?「更新されたルートCAを提供するために」って。はぁ、毎日CAの信頼ストアの更新なんていらないよ。もしあなたのCAルートがそんなに新しいなら、関わりたくない。

いろいろデメリットが挙げられてるみたいだけど…この変更のメリットは何なの?

https://github.com/encode/httpx/discussions/3784

「問題とディスカッションへのアクセスを閉じました。」 「こんなに偏った性別の表現があるオンライン環境を続けたくないんです。すごく居心地が悪いし、私が大切にしている働き方とは全然違うから。」

自分のルートCAをサポートするために、もう手間をかける必要はないよ。

AnthropicもOpenAIの後に同じ変更をしたんだね。 https://github.com/anthropics/anthropic-sdk-python/releases/... httpxを依存関係にするのは問題があって、今1.0リリースに向けて進んでるけど、壊れる変更が多いんだ。httpx2プロジェクトは、既存のAPIを壊さないことを約束したフォークで、より安定した依存関係として使えるよ。去年、壊れる1.0バージョンについての懸念を長いコメントで書いたんだけど - https://github.com/encode/httpx/discussions/3344#discussionc... - そのコメントでは、HTTPXプロジェクトが1.0をhttpx2というパッケージ名でリリースすることを勧めたんだ。でも、1年後に別のメンテナーによって古いAPIを保ったhttpx2がリリースされたね。

Pythonコミュニティはバージョニングがややこしいのが好きだよね。だって、明らかにPython 2.7の方が新しいのにPython 3.1より。Python3に移行するなんて絶対にしないって誓ったのに、気づいたら移行してたよ(でも、djangoが大きな役割を果たしたのは覚えてる)。

じゃあ、HTTPX2(https://github.com/pydantic/httpx2)がHTTPXYZ(https://codeberg.org/httpxyz/httpxyz)に勝ってるってこと?フォーク後にHTTPXYZには切り替えなかったけど、見守ってるよ。(私がやったのは、urllib.requestをもっと使って、足りないところはRustのwreqを使ったことかな。https://github.com/0x676e67/wreq-python)

httpxの問題は、めちゃくちゃ厄介で毒舌なメンテナーがいることだよね。

「HTTPXプロジェクトが1.0をhttpx2というパッケージ名でリリースすることを勧めたけど、1年後には別のメンテナーがリリースしたhttpx2が古いAPIをそのまま使ってる」って、何が起こってるんだ?

Hacker Newsで議論の続きを見る