Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal transport discussion #1

Closed
theacodes opened this issue Sep 27, 2016 · 4 comments
Closed

Internal transport discussion #1

theacodes opened this issue Sep 27, 2016 · 4 comments
Assignees
Labels
discussion 🚨 This issue needs some love. triage me I really want to be triaged.

Comments

@theacodes
Copy link
Contributor

theacodes commented Sep 27, 2016

This library needs to satisfy two orthogonal goals related to HTTP:

  1. It needs to be able to make HTTP requests internally (e.g., in refresh())
  2. It needs to allow users to attach credentials to an HTTP object of their choosing.

If there were only one Python HTTP library this would all be trivial. If the library was called unicorn, we could just use unicorn.request directly everywhere internally for (1). For (2), we would just write a single function to attach the credentials to unicorn.

This discussion is exclusively about (1), but care should be made not to limit our options for (2).

Use Case (1)

Use case (1) boils down to the need for a consistent way to make an http request and get response information. This use-case is only for library internals.

What's done today

transport.request takes any http object and then uses isinstance to figure out which transport should be used to call. Basically:

# Calling code
credentials.refresh(http, ...)

# credentials.py
def refresh(http):
    ...
    r = transport.request(http, ...)
    ...

# transport.py
def request(http, method, uri, ...):
    transport_module = get_transport_for_http(http)
    return transport_module.request(http, method, uri, ...)

# urllib3_transport.py
def request(http, method, uri, ...):
    return http.request(method, uri)

The indirection has the benefit that we can accept any supported http object at the call sites of methods like refresh(). The drawback is the indirection and the cost of the lookup for every request.

What we could do

Use http.client

We could easily use the built-in http.client - but urlilb3 and requests have significant benefits, and properly doing ssl with http.client can be error prone. It also leads us to situation where the http client the user is using and the http client we're using can be different.

Set credentials.http

Presently credentials are completely independent of http. Any methods that need to make requests must accept an http parameter. This proposes adding credentials.http that is set to a new private interface transport._HTTP. None of the request-making methods need http as an argument anymore.

This has the distinct drawback that credentials can now only be associated with a single http object. It also introduces a new interface (and subclasses for every transport).

Just pass in transport_impl.request

Instead of passing in an http object and letting the lookup happen, make the argument to refresh() et al be an interface that matches transport.request like this:

def request(method, uri, ...)

Since the caller of refresh knows the transport implementation that's currently being used it can just pass in, for example, functools.partial(urlilb3_transport.request, bare_http). The call stack would then look like this:

# Calling code
bound_request = functools.partial(urllib3_transport.request, self)
credentials.refresh(bound_request)

# credentials.py
def refresh(request):
    ...
    r = request(...)
    ...

# urllib3_transport.py
# http provided by functools.partial above.
def request(http, method, uri, ...):
    return http.request(method, uri)

This has a lot of benefits:

  1. The interface for request can be made public without making any other part of our transport implementation public.
  2. No lookup penalty.
  3. refresh() et al will have well defined argument types.
  4. Gives implementors of use case (2) the option of passing in something else for request. :)
@theacodes
Copy link
Contributor Author

@dhermes

@dhermes
Copy link
Contributor

dhermes commented Sep 27, 2016

@jonparrott the "Bind credentials to http" describes binding an http to credentials

@theacodes
Copy link
Contributor Author

@dhermes updated.

@theacodes
Copy link
Contributor Author

Resolved, at least for use case (1).

helen-fornazier pushed a commit to helen-fornazier/google-auth-library-python that referenced this issue Apr 20, 2018
Updated the Docstring and corrected it for next_chunk()
@yoshi-automation yoshi-automation added triage me I really want to be triaged. 🚨 This issue needs some love. labels Apr 6, 2020
arithmetic1728 added a commit that referenced this issue May 3, 2022
* [Bug 193694420] adding validation of token url and service account impersonation url (#1)

[b-193694420] adding url validation for token url and service account impersonation url
  * adding coverage of empty hostname to invalid token url
  * Add more tests to enlarge the coverage
Co-authored-by: Jin Qin <qinjin@google.com>

* adding coverage for service account impersonate url validation

* using urllib3 instead of urllib since it's the project test requirements included

* fix format

* addressing comments

* remove redundant

* fix tests since python 3.6 cannot have same string constants interpret as 3.7+

* fix lint and fix the flaky test in an alternate way

* revert the debugging output

* fix lint

Co-authored-by: Leo <39062083+lsirac@users.noreply.github.com>
Co-authored-by: Jin Qin <qinjin@google.com>
Co-authored-by: arithmetic1728 <58957152+arithmetic1728@users.noreply.github.com>
andrewsg added a commit that referenced this issue Oct 5, 2023
chore: Refresh system test creds.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
discussion 🚨 This issue needs some love. triage me I really want to be triaged.
Projects
None yet
Development

No branches or pull requests

3 participants