asgiref icon indicating copy to clipboard operation
asgiref copied to clipboard

Proposal: "http.response.template" extension.

Open lovelydinosaur opened this issue 5 years ago • 16 comments

In situations where an application server is happens to be returning template-rendered data, it's hugely valuable for the template and context information to be sent in the ASGI messaging, alongside the actual rendered content.

Right now we use this in Starlette, so that an ASGI-based test client is able to provide response.template and response.context information back to the user.

Formalising this, would allow us to support this kind of usage:

# This client calls directly into an ASGI app, rather than making network requests.
client = httpx.AsyncClient(app=app)

# Make the request.
response = await client.get("http://testserver/")
assert response.status_code == 200

# This information is made available through the "http.response.template" extension.
# Ensure that we're on the homepage, and that no messages are displayed.
assert response.template == "homepage.html"
assert response.context["user_messages"] == []

It's not totally obvious if an extension such as this should strictly focus on template/context info, or if there's a more general purpose "extra info" extension that ought to be considered here, but I figure it's worth opening this for discussion.

Informally, here's ~how the existing Starlette implementation looks...

# If the ASGI `http.response.template` extension is supported,
# then we can send this style of message...
{
    "type": "http.response.template",
    "template": "homepage.html",
    "context": {"user_messages": []}
}

lovelydinosaur avatar Nov 15 '19 12:11 lovelydinosaur

If it were a list of templates (so ["homepage.html"] in the example here) it would match Django's TestClient behaviour somewhat.

carltongibson avatar Nov 15 '19 12:11 carltongibson

@carltongibson - Surely only one template gets selected in the end? Does that interface mean "a list of all templates used during the rendering process, both the parent, and any included child templates"? Or something else?

lovelydinosaur avatar Nov 15 '19 13:11 lovelydinosaur

A list of Template instances used to render the final content, in the order they were rendered.

From extends and includes usage — so you end up with more that one.

carltongibson avatar Nov 15 '19 13:11 carltongibson

What would an ASGI server do with this information though? I don't think it's useful outside of test cases, is it not?

andrewgodwin avatar Nov 15 '19 19:11 andrewgodwin

(i.e. - is the proposal to add this to a response message and have servers ignore it?)

andrewgodwin avatar Nov 15 '19 19:11 andrewgodwin

Servers implementations would ignore it, yeah. (Or not support the extension). The usage is aimed at test clients. (Perhaps also debug middlewares or similar)

lovelydinosaur avatar Nov 15 '19 19:11 lovelydinosaur

It seems too narrow to define this specifically for templates. Perhaps a "execution_info" extension instead, so an app could provide whatever they want back to the test client.

davidism avatar Nov 15 '19 19:11 davidism

I agree with @davidism. If we're going to have a "test info please ignore" extension, let's make it more generic and nest template information inside it.

It's worth noting that this may not be backwards compatible, though, as ASGI servers are supposed to error on message types they don't understand. If that error is always a local traceback on send, though, then catching that error and absorbing it in the framework, combined with only during it during tests, might make it fine.

andrewgodwin avatar Nov 15 '19 21:11 andrewgodwin

It's worth noting that this may not be backwards compatible, though, as ASGI servers are supposed to error on message types they don't understand.

So long as it’s an extension it’s okay. Applications shouldn’t send the message unless the Web Server (or test client, or whatever) has advertised that it supports the extension.

lovelydinosaur avatar Nov 15 '19 22:11 lovelydinosaur

Things I can see falling naturally into this category:

  • template / context - Basic template rendering info.
  • user - The authenticated user.
  • endpoint - The function or class that was routed to.

lovelydinosaur avatar Nov 15 '19 22:11 lovelydinosaur

So, if this is an extension I think I'm happy with it conceptually and we should make sure we agree on a name for it that's not .template and then start getting the spec change written.

andrewgodwin avatar Nov 17 '19 05:11 andrewgodwin

I guess options here might be...

  • http.execution_info
  • http.extra_info

Anything else?

lovelydinosaur avatar Nov 26 '19 11:11 lovelydinosaur

I might suggest http.debug_info or http.test_info so that it's clear it's not for communication with normal servers?

andrewgodwin avatar Nov 29 '19 22:11 andrewgodwin

Of those two, http.test_info seems better to me.

lovelydinosaur avatar Nov 30 '19 14:11 lovelydinosaur

Agreed, that makes it clearer that it's for testing only. Let's go with that.

Do you want to write the PR to add it to the spec?

andrewgodwin avatar Dec 01 '19 16:12 andrewgodwin

Happily, yup. I'm not in any great rush but I'll aim to get around to it sometime.

lovelydinosaur avatar Dec 03 '19 09:12 lovelydinosaur

I'm interested in this. I want to solve an issue on Starlette, and I think having a conclusion here would be helpful there.

This is 3 years old now, so I'd like a confirmation that I can work on a PR for it. :pray:

Kludex avatar Dec 27 '22 08:12 Kludex