Skip to content

Conversation

@florimondmanca
Copy link
Contributor

@florimondmanca florimondmanca commented Dec 17, 2019

@tomchristie This is an implementation of the intuition I mentioned on Gitter — that it might be possible to use generators for #644.

Pros:

  • A linear, coroutine-like style, instead of a callback-based style (I think human brains have a hard time thinking in callbacks).
  • We never have to think about "we might have already sent an authenticated request before" — the auth flow is always excuted from top to bottom.
  • We don't even need classes — any callable that returns a generator will do. So, a function is perfectly valid:
def my_custom_auth(request):
    request.headers["Authorization"] = "Custom: 1234"
    yield request

I really think it's worth considering, although it relies on some advanced knowledge of the generator protocol.

@florimondmanca florimondmanca added the refactor Issues and PRs related to code refactoring label Dec 17, 2019
@florimondmanca florimondmanca changed the title Generator-based authentication flow Generator-based authentication flows Dec 17, 2019
@florimondmanca florimondmanca changed the title Generator-based authentication flows Generator-based, no-I/O authentication flows Dec 17, 2019
@florimondmanca florimondmanca changed the title Generator-based, no-I/O authentication flows No-I/O generator-based authentication flows Dec 17, 2019
@florimondmanca
Copy link
Contributor Author

florimondmanca commented Dec 17, 2019

One pending question — if this gets in, do we want users to be able to provide a custom auth function as a generator function as well?

def my_custom_auth(request):
    request.headers["Authorization"] = "Custom: 1234"
    yield request

r = await client.get(..., auth=my_custom_auth)

This would require exposing the AuthFlow type so that the above can be annotated using `-> httpx.AuthFlow.

That said, even allowing users to create an Auth subclass would require exposing AuthFlow to properly type-hint the __call__() definition, so I guess I should add this here?

@lovelydinosaur
Copy link
Contributor

My suggestion at the moment would be that we come back to considering this at another point.

I think it's probably a bit too much of an atypical style to be obvious to users, tho might be up for being convinced on it?

We can punt on it at the moment, since custom auth classes are currently private API, with our public API being...

  • Passing a BasicAuth or DigestAuth instance.
  • Passing a request->request callable for custom auth.
  • Passing a username/password tuple.

Granted we don't support custom multi-request auth as a public API at the moment, but that's okay.

@florimondmanca
Copy link
Contributor Author

Well, it can very much stay an internal style for now — were not exposing Auth yet anyway, so I can withdraw the change that adds generator functions to the public API.

I’d just prefer this over the on_request/on_response callbacks anyway, even for private use, because it enforces the order of requests much more cleanly and easily than a callback style does.

@lovelydinosaur
Copy link
Contributor

Gotcha. How about...

  • We don't expose AuthFlow at the moment, or support passing a generator just yet.
  • Internally, we don't overload FunctionAuth. (We can add a GeneratorAuth class once we add that style to the public API.)

That way we can make sure that the generator style flow gets a PR that includes documentation and public API changes, seperately from the internal work of "DigestAuth can now be used with a sync or async client".

?

@lovelydinosaur
Copy link
Contributor

Ah, re-reads and sees this...

so I can withdraw the change that adds generator functions to the public API.

Ya. 😃

@florimondmanca
Copy link
Contributor Author

@tomchristie Updated the PR. :-)

@lovelydinosaur lovelydinosaur merged commit 7e378e7 into no-io-auth Dec 18, 2019
@lovelydinosaur lovelydinosaur deleted the no-io-auth--generator-based-flow branch December 18, 2019 11:19
@lovelydinosaur
Copy link
Contributor

Neato. Working on this highlighted a couple of things to me:

  • In multi-request flows, really we ought to check if a request is replayable, and error otherwise.
  • In multi-request flows, it'd be nice to maintain .history properly.

I'd suggest we treat those seperately, since we're not regressing any behavior here, just noticing edges that we ought deal with more gracefully.

@lovelydinosaur lovelydinosaur mentioned this pull request Dec 18, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

refactor Issues and PRs related to code refactoring

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants