Skip to content

Improve UnsupportedProtocol error messaging. #1644

Closed
@tomchristie

Description

@tomchristie
Member

Prompted by this discussion #1643

We should have clearer error messaging for the trivially simple case of an incomplete URL, where the scheme is ommitted...

>>> httpx.get("/test")
Traceback (most recent call last):
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 61, in map_httpcore_exceptions
    yield
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 183, in handle_request
    extensions=extensions,
  File "/Users/tomchristie/GitHub/encode/httpx/venv/lib/python3.7/site-packages/httpcore/_sync/connection_pool.py", line 204, in handle_request
    raise UnsupportedProtocol(f"Unsupported URL protocol {scheme!r}")
httpcore.UnsupportedProtocol: Unsupported URL protocol ''

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_api.py", line 196, in get
    trust_env=trust_env,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_api.py", line 110, in request
    allow_redirects=allow_redirects,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 758, in request
    request, auth=auth, allow_redirects=allow_redirects, timeout=timeout
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 846, in send
    history=[],
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 880, in _send_handling_auth
    history=history,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 910, in _send_handling_redirects
    response = self._send_single_request(request, timeout)
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 949, in _send_single_request
    extensions={"timeout": timeout.as_dict()},
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 183, in handle_request
    extensions=extensions,
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/contextlib.py", line 130, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 78, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.UnsupportedProtocol: Unsupported URL protocol ''

Also the case of an invalid protocol could also benefit from at least including the full URL string in the error...

>>> httpx.get("htt://example/test")
Traceback (most recent call last):
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 61, in map_httpcore_exceptions
    yield
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 183, in handle_request
    extensions=extensions,
  File "/Users/tomchristie/GitHub/encode/httpx/venv/lib/python3.7/site-packages/httpcore/_sync/connection_pool.py", line 204, in handle_request
    raise UnsupportedProtocol(f"Unsupported URL protocol {scheme!r}")
httpcore.UnsupportedProtocol: Unsupported URL protocol 'htt'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_api.py", line 196, in get
    trust_env=trust_env,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_api.py", line 110, in request
    allow_redirects=allow_redirects,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 758, in request
    request, auth=auth, allow_redirects=allow_redirects, timeout=timeout
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 846, in send
    history=[],
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 880, in _send_handling_auth
    history=history,
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 910, in _send_handling_redirects
    response = self._send_single_request(request, timeout)
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_client.py", line 949, in _send_single_request
    extensions={"timeout": timeout.as_dict()},
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 183, in handle_request
    extensions=extensions,
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/contextlib.py", line 130, in __exit__
    self.gen.throw(type, value, traceback)
  File "/Users/tomchristie/GitHub/encode/httpx/httpx/_transports/default.py", line 78, in map_httpcore_exceptions
    raise mapped_exc(message) from exc
httpx.UnsupportedProtocol: Unsupported URL protocol 'htt'

Activity

ajayd-san

ajayd-san commented on May 29, 2021

@ajayd-san

hey, I'd like to work on this.

tomchristie

tomchristie commented on Jun 1, 2021

@tomchristie
MemberAuthor

@default-303 Okay, grand. That exception is raised by httpcore... https://github.com/encode/httpcore/blob/911d61c3495918e4f4fa72a7d32f335d79e1e798/httpcore/_async/connection_pool.py#L204

If the protocol is an empty string, then we probably want to issue a message like this...

  • httpx.UnsupportedProtocol: The request to "://www.example.com/" is missing either an 'http://' or 'https://' protocol.

If the protocol is not one of http or https, then we probably want to issue a message like this...

  • httpx.UnsupportedProtocol: The request to "htt://www.example.com/" has an unsupported protocol 'htt://'.
ajayd-san

ajayd-san commented on Jun 1, 2021

@ajayd-san

so, i should be updating the httpcore module, instead of httpx ?

tomchristie

tomchristie commented on Jun 1, 2021

@tomchristie
MemberAuthor

Yup

ajayd-san

ajayd-san commented on Jun 1, 2021

@ajayd-san

okay sure, I cloned it I'm ready to make changes but how do I know if its working right? I mean I need to test this with httpx so that I know its working as expected. How do you say I do so ? tests ?

tomchristie

tomchristie commented on Jun 2, 2021

@tomchristie
MemberAuthor

@default-303 You'll need to add a test similar to this one... https://github.com/encode/httpcore/blob/master/tests/async_tests/test_interfaces.py#L32

Note that httpcore includes both async and sync version of the codebase. The workflow you'll need is to write the async code and tests only, and run the scripts/unsync script to autogenerate the corresponding sync version.

You don't need to test this against a full integration with httpx, it's enough to unit test some stuff simply at the httpcore layer of the interface.

ajayd-san

ajayd-san commented on Jun 3, 2021

@ajayd-san

@tomchristie I have trouble understanding this line https://github.com/encode/httpcore/blob/3f33e159f8802a191d09a186ae816aa7a8e37062/tests/async_tests/test_interfaces.py#L36

What is actually happening here ? I mean I followed the trail and turns out netlock is supposed to raise error and somehow server.netlock is being unpacked. This is the same case with other attributes of the Server class.

ajayd-san

ajayd-san commented on Jun 7, 2021

@ajayd-san

can i get that thing clarified ? Anyone?

tomchristie

tomchristie commented on Jun 7, 2021

@tomchristie
MemberAuthor

You might find that line easier to understand if it was re-written like so...

host, port = server.netloc
status_code, headers, stream, extensions = await http.handle_async_request(
    method=b"GET",
    url=(b"http", host, port, b"/"),
    headers=[server.host_header],
    stream=httpcore.ByteStream(b""),
    extensions={},
)
ajayd-san

ajayd-san commented on Jun 9, 2021

@ajayd-san

hey, I did a pr in httpcore, can you check and give an update ?

tomchristie

tomchristie commented on Jun 9, 2021

@tomchristie
MemberAuthor
Keyurkch

Keyurkch commented on Jan 18, 2024

@Keyurkch

I am getting similar error for pymssql requests while working with SQL DB using SQLDatabaseChain. URL example mssql+pymssql://{database_user}:{database_password}@{database_server}/{database_db}

Error:
httpx.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

File "D:\Program\Python\Python311\Lib\site-packages\httpcore_sync\connection_pool.py", line 208, in handle_request
raise UnsupportedProtocol(
httpcore.UnsupportedProtocol: Request URL is missing an 'http://' or 'https://' protocol.

Not sure if SQLDatabaseChain should invoke httpcore_sync\connection_pool.py? And it should then should there be another condition to allow requests starting with mssql+pymssql? Any thoughts by anyone?

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

    user-experienceEnsuring that users have a good experience using the library

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @tomchristie@Keyurkch@ajayd-san

        Issue actions

          Improve `UnsupportedProtocol` error messaging. · Issue #1644 · encode/httpx