A client initially opens a connection to an ASGI compliant server. The server forwards a Connect event
[asgi-spec] to the application. This event must be responded to with either an Accept event
[asgi-spec] or a Close event
. [asgi-spec] The server must send this event during the handshake phase of the WebSocket and not complete the handshake until it gets a reply.
If the application responds with a Close event
, the server must close the connection with a HTTP 403
status code and not complete the WebSocket handshake.
Why simply 403
? Not even a reason key is allowed to be part of the event responded. Just 403
. You would expect that it is during handshake that Authentication would be done hence a possible 401
.
The WebSocket Protocol specification allows any HTTP status code besides 101
.
Any status code other than
101
indicates that the WebSocket handshake has not completed and that the semantics of HTTP still apply.
What is the rationale behind ASGI’s specification?
As explained in ASGI Extensions spec (which allows using other HTTP status code on rejection), the rationale behind this decision seems to be for the sake of simplicity in most practical cases:
The core ASGI specification does not allow for any control over the denial response, instead specifying that the HTTP status code 403 should be returned, whereas this extension allows an ASGI framework to control the denial response. Rather than being a core part of ASGI, this is an extension for what is considered a niche feature as most clients do not utilise the denial response.
You may find more details regarding this matter in these comments:
And especially this one
Hmm, right, that situation makes sense, though it's still a bit strange. The question I'm asking is if it's worth asking servers to implement a LOT more complexity (in Daphne's case, this is going to require a lot of new code as the HTTP and WebSocket paths are very separate) for a very edge use-case.
ASGI already deliberately does not cover some of the more obscure parts of the HTTP spec - like sending headers mid-stream between chunks - because it's not worth supporting a 1% feature to make code more complex. Do you think this is? Would having it not be there be a make-or-break for you to help adopt it? Once something is in a spec it is near-impossible to remove.
Also, as for close codes, I agree mixing the namespace would be confusing. Could add a separate http_status option to the close instead to make it cleaner.