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

Support Fetch API Request and Response #79

Open
MatthewWid opened this issue Nov 5, 2024 · 2 comments
Open

Support Fetch API Request and Response #79

MatthewWid opened this issue Nov 5, 2024 · 2 comments
Assignees
Labels
enhancement New feature or request

Comments

@MatthewWid
Copy link
Owner

MatthewWid commented Nov 5, 2024

Update the Session to be able to take in a Request object from the Fetch API and return in some way a Response object.

Web streams and the Fetch API appear to be the predominant standard with JavaScript moving forward, and as such this will enable compatibility with the many libraries (#70, #78, #83) that expose Request/Response interfaces rather than the Node IncomingMessage and ServerResponse objects.


The new API would simply add another overload to the session constructor, so you could now do one of:

createSession(IncomingMessage, ServerResponse, options)
createSession(Http2ServerRequest, Http2ServerResponse, options)
createSession(Request, Response, options)

Which would be used like the following:

import { createSession } from "better-sse";

const session = await createSession(request);

return session.getResponse();

If the session detects that it is passed a Request object it will defer calling the internal initialize method - which flushes the response head and sends preamble data - until the getResponse method has been called.

When it is finally invoked, a new Response object with a ReadableStream as its body will be returned, given the parameters from the session constructor options argument as well as any additional parameters given to the method itself which are passed through to the Response constructor, and the library will begin streaming data through it.

This may involve a refactor to where, even the if the IncomingMessage/ServerResponse objects are given, they are converted to be Request/Response objects internally so that a single, standardized interface can be used across different frameworks and runtimes rather than repeatedly running down conditional trees with slow and janky instanceof checks.


This may obsolete #77 as instead of making adapters implement a now-abstract Session class you would instead write an adapter to fit your runtime/frameworks lifecycle into the standard Request/Response objects, requiring no breaking changes to the current package API and overall being a much cleaner implementation.

@MatthewWid MatthewWid added the enhancement New feature or request label Nov 5, 2024
@MatthewWid MatthewWid self-assigned this Nov 5, 2024
@go4cas
Copy link

go4cas commented Nov 15, 2024

@MatthewWid ... first off, thanks for the great library!

Question: once this issue has been implemented, will better-sse work in a Hono NodeJS app?

@MatthewWid
Copy link
Owner Author

MatthewWid commented Nov 18, 2024

@go4cas yes, that would be the case.

In theory you should even be able to use Hono with non-Node runtimes such as Deno and Bun, but I need to do more research and testing on that.


I don't have a fully formed idea of what the API would and could look like at the moment, but something resembling this is the general workflow:

app.get("/sse", async (c) => {
  const session = await createSession(c.req);

  // register to channels and/or push events

  return session.getResponse();
});

There might be some strangeness, however, with the order of things being returned whereby data is pushed to the session before the response is returned and headers are flushed. In which case, there needs to be some mechanism where we can access the session only after the response has been returned. For example:

const session = await createSession(c.req); // flushing headers is deferred until `getResponse` is called

session.once("connected", () => {
  // safe to send data
});

return session.getResponse();

or, mimicking how hono/streaming looks:

return (await createSession(c.req)).getResponse((session) => {
  // safe to send data
});

I'll have to give it more thought when I can find the time.

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

When branches are created from issues, their pull requests are automatically linked.

2 participants