Skip to content

User question: respx and the httpx forks #316

Open

Description

@rgant

Hi; I'm a respx user trying to make an informed decision about my own project and I'd appreciate any read you have on this.

Context

I've been moving an internal project off upstream httpx for supply-chain reasons — no release since November 2024, issues and discussions closed, focus moved to a private rewrite. A community-maintained stability fork called httpxyz has emerged and is actively shipping. It registers itself under the httpx import name via a sys.modules alias plus a pytest plugin, with the goal of being a transparent drop-in.

When I tried it with respx 0.23.1, HTTPCoreMocker-based mocks stopped intercepting — calls fell through to the real network. After some digging the cause turned out to be on the httpxyz side: their sys.modules alias only covers the top-level package names, and respx patches by submodule path (httpcore._sync.connection_pool.ConnectionPool, etc.), which causes Python to load a duplicate module under the alias name. I filed httpxyz#53 with a reproducer and a proposed fix; once that lands upstream, respx should work against httpxyz with no changes here.

What I'd value hearing

So this isn't a respx bug, and I'm not asking you to do anything about it. But as I've been working through it, I realised I don't actually know how you think about the broader situation. So figured I'd ask:

As more httpx users move to httpxyz (or stay on stagnating upstream), do you have a sense of where respx wants to sit?

Even an answer like "we track upstream httpx exclusively; users on forks are on their own" is genuinely useful — it helps me and others plan, and it's a reasonable position. I'm not advocating for any particular outcome.

What I'm not assuming

  • That you should care about httpxyz, support it, or change anything in respx. Each of those adds real maintenance load, and you're best placed to judge whether that's worth it.
  • That a "no" needs justification. "Not interested" or "we follow upstream only" is a complete answer.
  • That the technical compatibility issue I bumped into needs respx engagement; it's being handled upstream at httpxyz.

An offer, if it'd be welcome

If you'd find it useful, I'd be glad to put together a PR that makes respx work against either upstream httpx or httpxyz at the same install — i.e. respx detects which one the user has and mocks the right thing, with no behaviour change for users on plain httpx. The smallest version of that change looks small to me, but I want to flag plainly that even an accepted PR commits respx to a slightly larger surface (two packaging conventions to keep in mind when respx or httpcore internals change), so this is a real maintenance ask, not a free lunch. I don't want to presume — but if it'd be welcome, I'm here.

A "no, please don't" is just as useful an answer as a "yes, send it."

A standalone reproducer (only if curious)

If you ever want to verify the interaction yourself, there's a self-contained pytest reproducer (sync + async cases, one toggle that demonstrates a workaround). It also runs cleanly against current respx without modification — it just illustrates the failure mode.

Thanks for respx, and thanks for whatever read you can share on this. No reply needed if you'd rather not engage; closing this issue with no comment is also a perfectly fine answer.

Activity

  1. lundberg commented on May 7, 2026

    @lundberg
    Owner

    Well, I'm not a fan of sys aliasing in the first place 😉, but start with trying out a respx mocker subclass with proper patch targets, maybe shipped in your pytest plugin module, e.g.

    from respx.mocks import HTTPCoreMocker
    
    
    class HTTPCoreXYZMocker(HTTPCoreMocker):
        name = "httpcorexyz"
        targets = [
            "httpcorexyz._sync.connection.HTTPConnection",
            "httpcorexyz._sync.connection_pool.ConnectionPool",
            "httpcorexyz._sync.http_proxy.HTTPProxy",
            "httpcorexyz._async.connection.AsyncHTTPConnection",
            "httpcorexyz._async.connection_pool.AsyncConnectionPool",
            "httpcorexyz._async.http_proxy.AsyncHTTPProxy",
        ]

    This should allow a user to use httpxyz with respx without any magic involved ..

    import httpxyz
    import respx
    
    with respx.mock(using="httpcorexyz"):
        httpxyz.get(...)

    There no current way of setting the respx default mocker.

  2. rgant commented on May 7, 2026

    @rgant
    Author

    Thanks — exactly what I needed.

    I tried the subclass pattern and it works cleanly for the patch-target side. Auto-registers via Mocker.__init_subclass__, so importing the module is enough; respx.mock(using="httpcorexyz") resolves correctly. Verified end-to-end with both sync and async fixtures.

    The wrinkle was on the global-router side. My tests use the bare @respx.mock decorator and respx.get(...) (~35 callsites), so threading using="httpcorexyz" through each one would mean a mass migration to the parenthesized form. The shortcut I used was to mutate the global router's _using after defining the subclass:

    respx.mock._using = HTTPCoreXYZMocker.name

    That makes every existing @respx.mock / respx.get(...) resolve to the new mocker with no callsite changes. Clearly a pragma — _using is private and you flagged exactly this gap.

    Two offers, separately, both fully optional:

    1. Docs. As far as I can tell from skimming docs/{api,guide,mocking,examples,migrate,upgrade,index}.md, there's no mention of HTTPCoreMocker, the Mocker subclass extension hook, or the using= parameter on respx.mock(...). If you'd find it useful, I'd be glad to write a short docs page on "subclassing HTTPCoreMocker to mock a forked httpcore," with the httpcorexyz subclass as the worked example. Skip if you'd rather not advertise this surface.

    2. The dual-support PR. I'm still working toward dropping httpx as a hard dependency on my end, so I'd still like to offer the PR I mentioned in the original message — a small change that lets respx work against either upstream httpx or httpxyz at the same install, with no behavior change for users on plain httpx. The maintenance trade-off still applies — two packaging conventions to keep in mind when respx or httpcore internals change. "No, please don't" is as good an answer now as it was then.

    Either, both, or neither — your call. Thanks again.

  3. lundberg commented on May 8, 2026

    @lundberg
    Owner

    If you want respx to auto use your custom mocker, I'd rather mutate the default mocker instead of _using, though not a public api either, but cleaner ..

    respx.mocks.DEFAULT_MOCKER = "httpcorexyz"

    About the docs etc, lets wait with that til really needed.

  4. homeworkprod commented on May 14, 2026

    @homeworkprod

    I'm also interested in switching from HTTPX to an actively supported fork while continuing to use RESPX.

    A few things I learned in the minutes after discovering this issue that might be of interest:

    Another thing: RESPX currently non-optionally depends on HTTPX; as long that is the case, moving to a fork of HTTPX won't completely get rid of the dependency on it (though it is "only" a dependency of the test scope now).

  5. Kludex commented on May 17, 2026

    @Kludex

    @lundberg anything I can do on httpx2 side to help you here?

  6. lundberg commented on May 18, 2026

    @lundberg
    Owner

    Great additional thoughts @homeworkprod !

    I think we need to decide on adding "forks" directly to respx default patching, or some new feature that simplifies the selection of tool, e.g. httpx, httpx2, httpxyz etc 🤔

    Pydantic is such a legit fork so I'm leaning towards just adding those paths by default .. though, some package detection would need to exist.

    Also the dependency on httpx is tricky .. any thoughts on how we should tackle that? Ideally, each package/fork will probably need different pinning versions in the future 🤔 .. maybe by extras? e.g. respx[httpx] vs respx[httpx2] etc?

  7. lundberg commented on May 18, 2026

    @lundberg
    Owner

    @Kludex mostly design decisions/ideas would be very welcome, e.g. how to solve respx dependency issue, respx api typing issue (httpx.Response etc)

  8. changed the title [-]User question: respx and the httpxyz fork — any thoughts?[/-] [+]User question: respx and the httpx forks[/+] on May 18, 2026
  9. lundberg commented on May 18, 2026

    @lundberg
    Owner

    @Kludex I've pushed a "crude" PR #317 for httpx2 support, as a starting point.

    As long as httpx2 and httpcore2 keeps current api, I guess this fix would work. Though, following issues needs to be figured out and adressed for a proper dev experience ..

    • Typing, e.g. httpx.Response
    • Dependency on specific http tool and related pinning .. extras?
    • Test suite and coverage against multiple tools
  10. Kludex commented on May 18, 2026

    @Kludex

    As long as httpx2 and httpcore2 keeps current api [...]

    If I add parameters to the clients at some point, is that a breaking change on your side? Or add methods e.g. websocket().

    Dependency on specific http tool and related pinning .. extras?

    I think you don't need to depend on any of those 2 client libraries, do you? 🤔 I think it's good to restrict the version of httpx being installed, but if it's optional, you can't really restrict. My point is that you can infer the package being used.

    Test suite and coverage against multiple tools

    I suggested something on the PR.

    Typing, e.g. httpx.Response

    I think this is a bit more tricky... I can offer you a httpx-protocol/httpx-types/httpx-shim library that would have just protocols of the httpx types and then you'd return this httpx_protocol.Response that has the httpx.Response shape... But I'm not sure if this would solve your issue? If it does, happy to provide that.

  11. lundberg commented on May 20, 2026

    @lundberg
    Owner

    If I add parameters to the clients at some point, is that a breaking change on your side? Or add methods e.g. websocket()

    Nope, that should be fine, most of patching is done in httpcore for that reason

    I think you don't need to depend on any of those 2 client libraries, do you? 🤔 I think it's good to restrict the version of httpx being installed, but if it's optional, you can't really restrict. My point is that you can infer the package being used.

    There are dependencies on the Request and Response models, e.g. instantiation and conversions, so changing init of those may break stuff.

    I think this is a bit more tricky... I can offer you a httpx-protocol/httpx-types/httpx-shim library that would have just protocols of the httpx types and then you'd return this httpx_protocol.Response that has the httpx.Response shape... But I'm not sure if this would solve your issue? If it does, happy to provide that.

    Not sure either what the best approach here is 🤔. If I uilize package extras, that adds different shims, maybe that would work?

    I'm thinking, installing respx[httpx2] includes/overrides a httpxlib respx module, which imports httpx2 as httpx .. and then all imports in respx imports httpx from that module .. a bit like httpx's jsonlib.

    Maybe event this solution could handle and "enable" correct mocker (patching) 🤔

  12. lundberg commented on May 22, 2026

    @lundberg
    Owner

    FYI, as a starter, I added a pytest-HTTPX2 plugin with a custom mocker that specifically targetshttpx2. Also added a docs PR to httpx2.

    My idea now is to keep that package a pytest plugin only, and move the mocker class to e.g. a respx-httpx2 package, that both that pytest plugin package could depend on, and respx[httpx2] extras.

  13. leosharer commented on Jun 21, 2026

    @leosharer

    Just chiming in with an alternative idea: respx2 ?

    It seems the community has accepted httpx2 as the legitimate successor and therefore httpx is effectively committed to the archives. Wouldn't it be more straightforward to fork respx too, rather than it accumulating detection, typing and packaging complexity?

    That may be a bad idea for reasons which haven't ocurred to me, but thought I would socialise for consideration anyway.

  14. lundberg commented on Jun 22, 2026

    @lundberg
    Owner

    Just chiming in with an alternative idea: respx2 ?

    I've thought some more since last and agree that httpx2 is the legit successor, regardless if it gets merged back to the origin httpx in the future. It should be possible to keep a single respx package that supports both .. just figuring out the final ditails 😅

  15. grigi commented on Jul 22, 2026

    @grigi

    Hi, any update on this?
    I would be happy with a new version of respx that only works on httpx2 if that's what simpler.

  16. voltagex commented on Aug 13, 2026

    @voltagex

    New version of respx, breaking change?

    FWIW it also seems to be holding up fastapi.

    fastapi/fastapi#16186 (comment)

    Of course, neither are my project but I would be moving to maintained dependencies as a priority.

  17. Joelius300 commented on Sep 8, 2026

    @Joelius300

    Any updates on the respx release to support httpx2 directly? Via pytest-httpx2 I was able to temporarily work around it, but I still need httpx.Response in the test code (#324).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions