Skip to content

Python: Fix header conversion to byte-pair on scope building - #2125

Closed
morganabc wants to merge 2 commits into
cloudflare:mainfrom
morganabc:patch-1
Closed

morganabc wants to merge 2 commits into
cloudflare:mainfrom
morganabc:patch-1

Conversation

@morganabc

@morganabc morganabc commented May 14, 2024 •

Copy link
Copy Markdown

headers: These are byte strings of the exact byte sequences sent by the client/to be sent by the server. While modern HTTP standards say that headers should be ASCII, older ones did not and allowed a wider range of characters. Frameworks/applications should decode headers as they deem appropriate.
(https://asgi.readthedocs.io/en/latest/specs/www.html#wsgi-compatibility)

Workerd uses Pyodide JSProxy object when passing fetch(request, env) to Python, but JSProxy objects translates into string, not byte-string.

In order to match ASGI specification, it needs to be translated into byte-pair when building scopes.

@github-actions

github-actions Bot commented May 14, 2024 •

Copy link
Copy Markdown

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@morganabc

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

github-actions Bot added a commit that referenced this pull request May 14, 2024
@morganabc
morganabc marked this pull request as ready for review May 14, 2024 23:21
@morganabc
morganabc requested review from a team as code owners May 14, 2024 23:21
@morganabc
morganabc requested review from hoodmane and jasnell May 14, 2024 23:21

@hoodmane hoodmane left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code change makes sense. Ideally we ought to add a test.

@morganabc
morganabc requested a review from hoodmane May 29, 2024 08:57
from js import URL

headers = [tuple(x) for x in req.headers]
headers = [(k.lower().encode(), v.encode()) for k, v in req.headers]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In lieu of adding a test, can we add a comment here with an example that cares about this being bytes so that we can add a test ourselves later?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It assumes FastAPI so that would be a main concern, but its for ASGI spec though so should I add for FastAPI or just asserting for spec?

Like, anything for

@app.get("/example")
  async def example(request: Request):
    request.headers.get("content-type") # this will error if header is not bytes.

perhaps?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also is there way to test this locally? I want to build miniflare with master workerd, but building workers-sdk doesnt works..

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can build workerd by itself and then set an environment variable to tell wrangler to use your custom build. @dom96 are there good instructions somewhere that we can point contributors to?

I guess I should check it out and test it myself...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May be easier to build and run workerd locally. These are probably the best instructions we have for doing this: https://github.com/cloudflare/workerd?tab=readme-ov-file#configuring-workerd.

We also have some sample Python worker configs in the repo already, for example https://github.com/cloudflare/workerd/tree/main/samples/pyodide-fastapi

@morganabc morganabc May 30, 2024 •

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, so I can use workerd directly! Thanks, now I can test few things.

@jasnell jasnell added the python Issues/PRs relating to Python Workers label May 30, 2024
@leobuskin

Copy link
Copy Markdown

That's not the only trouble w/ ASGI and binary strings. We also need to decode resulting headers in asgi.py, if I understand correctly:

async def send(got):
        ...
        if got['type'] == 'http.response.start':
            status = got['status']
            headers = [(k.decode(), v.decode()) for k, v in got['headers']]

@spikerwork

Copy link
Copy Markdown

That's not the only trouble w/ ASGI and binary strings. We also need to decode resulting headers in asgi.py, if I understand correctly:

async def send(got):
        ...
        if got['type'] == 'http.response.start':
            status = got['status']
            headers = [(k.decode(), v.decode()) for k, v in got['headers']]

Confirmed! This patch fixed the problem with b'' I've seen before

Screenshot from 2024-06-05 11-03-09

@morganabc

Copy link
Copy Markdown
Author

That's not the only trouble w/ ASGI and binary strings. We also need to decode resulting headers in asgi.py, if I understand correctly:

async def send(got):
        ...
        if got['type'] == 'http.response.start':
            status = got['status']
            headers = [(k.decode(), v.decode()) for k, v in got['headers']]

Yes, right. I fixed it. Thanks!

Comment thread src/pyodide/internal/asgi.py Outdated
if got["type"] == "http.response.start":
status = got["status"]
headers = got["headers"]
headers = [(k.decode(), v.decode()) for k, v in got['headers']]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@morgan9e I'd use double quotes here to be compliant w/ folks' formatting standards

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Working on it!

@hoodmane

hoodmane commented Jun 5, 2024

Copy link
Copy Markdown
Contributor

Since #2096 merged, we're actually running Python tests on workerd so it should be possible to add a test now.

@morganabc

Copy link
Copy Markdown
Author

@hoodmane: Since #2096 merged, we're actually running Python tests on workerd so it should be possible to add a test now.

Should I add test for ASGI only or if its working with Starlette? I think it might be better if we make asgi.py independant to FastAPI

@hoodmane

hoodmane commented Jun 6, 2024

Copy link
Copy Markdown
Contributor

Agreed we should make it independent. Currently the only thing in there that is dependent on fastapi is Env. Perhaps we can just delete that for now and we can figure out the appropriate place to add it later.

@dom96

dom96 commented Nov 18, 2024

Copy link
Copy Markdown
Contributor

Hey @morgan9e, would love to get this merged in, are you still planning to create a test for this?

@morganabc

Copy link
Copy Markdown
Author

Hey @morgan9e, would love to get this merged in, are you still planning to create a test for this?

Yep, thanks I'll do it ASAP.

@morganabc

Copy link
Copy Markdown
Author

Hey @morgan9e, would love to get this merged in, are you still planning to create a test for this?

Yep, thanks I'll do it ASAP.

I added the test, I wrote sample ASGI Application rather than using FastAPI because I thought it was better to seperate it from FastAPI.

@morganabc morganabc closed this Nov 20, 2024
@morganabc
morganabc deleted the patch-1 branch November 20, 2024 07:38
@morganabc

morganabc commented Nov 20, 2024 •

Copy link
Copy Markdown
Author

Sorry, I accidently merged and removed upstream branch, I reopened it. #3142

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

Labels

python Issues/PRs relating to Python Workers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants