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

implement "Upgrade" as a function in a api route to support websocket #12358

Open
jacobbogers opened this issue Jun 15, 2024 · 7 comments · May be fixed by #12973
Open

implement "Upgrade" as a function in a api route to support websocket #12358

jacobbogers opened this issue Jun 15, 2024 · 7 comments · May be fixed by #12973
Labels
feature / enhancement New feature or request

Comments

@jacobbogers
Copy link

jacobbogers commented Jun 15, 2024

Describe the problem

One can easy implement GET, PUT in an api route by a function (see below)

import { json } from '@sveltejs/kit';

export function GET() {
	const number = Math.floor(Math.random() * 6) + 1;

	return json(number);
}

Describe the proposed solution

If we implement UPGRADE Protocol_upgrade_mechanism we could implement websockets aswell

this file is in src/route/chat-app/server.js connect with new WebSocket('/chap-app')

// if this file is in src/route/chat-app/server.js

import { json } from '@sveltejs/kit';

// called when http call wants to upgrade to websocket protocol
export function UPGRADE() {

      // this function will be called after successfull upgrade
       return function connection(ws: WebSocket) {
                         
 	       ws.send('hello');
               ws.onmessage = (event) => {..});
              // other handlers
      }
}

### Alternatives considered

_No response_

### Importance

would make my life easier

### Additional Information

Currently, customers expect some kind of live real time interaction,  a clean solution integrating with sveltekit would be a huge advantage
@eltigerchino
Copy link
Member

eltigerchino commented Jun 15, 2024

Would a conditional in the fallback method handler fit your needs? https://kit.svelte.dev/docs/routing#server-fallback-method-handler . Our motivation for adding this was so that sveltekit wouldn't need to check an indefinite list of named exports in the +server file (we only focus on the most commonly used ones)

@Conduitry
Copy link
Member

It wouldn't really help, no. Web Sockets are a two-way stream, and you can't make them fit into a Request/Response framework, which is what you'd still have to do with the fallback method handler.

This is basically #1491. It's a hard problem to come up with an API for, and we don't have a solution for it.

@jacobbogers
Copy link
Author

Would a conditional in the fallback method handler fit your needs? https://kit.svelte.dev/docs/routing#server-fallback-method-handler . Our motivation for adding this was so that sveltekit wouldn't need to check an indefinite list of named exports in the +server file (we only focus on the most commonly used ones)

That is not how websocket works (read the link in the OP), the UPGRADE request is not a HTTP method, I suggest this handler name because to me it fits more how the kit uses api routes.

@jacobbogers
Copy link
Author

jacobbogers commented Jun 15, 2024

It wouldn't really help, no. Web Sockets are a two-way stream, and you can't make them fit into a Request/Response framework, which is what you'd still have to do with the fallback method handler.

actually websockets are designed to piggy back on request/response framework, how we expose things to the developer is either we create a specific context per websocket connection and a singler handler function or a function factory that creates a PERMANENT lived function context for the duration of the websocket connection (the latter my proposed solution)

Fallback would not work because a websocket initial request is just a GET (with some special headers). and normal GET handlers have precedence in sveltekit. the only thing skit should not do is physically close the socket after the request.

I looked at kit code and you can add specific handler names if you want (ofc you need to change skit code for this).

@jacobbogers
Copy link
Author

So basically

if kit receives GET + websocket upgrade headerss -> call Upgrade handler
if kit receives GET (no specific websocket headers) -> call the usual GET handler

@eltigerchino
Copy link
Member

Thanks for all the information on websockets, especially since I don't have much understanding of it yet.
Reading through the main websocket issue, it seems there are a few workarounds the community has come up with, such as this one that also handles upgrading the GET requests.

Is it a good idea for the framework to handle these upgrades and for the developer to simply export a websocket function to handle these connections? But, reading the MDN docs on this it seems like more control is needed depending on the raw request or just the Upgrade header?

Might be a good idea to move this discussion to #1491 so that we can collect these ideas and brainstorm an API for this.

@jacobbogers
Copy link
Author

jacobbogers commented Jun 15, 2024

Last post here, moved to #1491

But, reading the MDN docs on this it seems like more control is needed depending on the raw request or just the Upgrade header?

No the upgrade header is what makes this piggy back on existing http transports (remember the billions of routers and proxies that dont need to be configured to handle websockets). other then this you enter the websocket space and ofc you have full duplex control mechancism and framing protocol you can read about full websocket here rfc6455

From Server perspective you need to:

  1. initiate sending data to client at any time
  2. close connection
  3. receive data from client

From Client perspective:

  1. create connection
  2. send data
  3. receive data from server
  4. close connection

there is no crazy magic going on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature / enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants