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

Added whatwg-node-server adapter for grafserv #2288

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kzlar
Copy link
Contributor

@kzlar kzlar commented Dec 23, 2024

Description

@whatwg-node/server is an adapter that helps create generic servers across runtimes (https://www.npmjs.com/package/@whatwg-node/server). It could, at least in theory, replace all of the servers currently implemented, while supporting several more. If this all works out it should help integrations while having to maintain less code.

Note: This doesn't support web-sockets, I'm still looking for a way to do that in a generic fashion, but I see some of the other adapters don't support web-sockets either so I believe this is good enough for now.

Performance impact

unknown, but this PR won't affect anything by itself, it's just adding the adapter.

Security impact

None

Checklist

  • My code matches the project's code style and yarn lint:fix passes.
  • I've added tests for the new feature, and yarn test passes (Well, sort of - I ran the grafserv tests with it and it passed)
  • I have detailed the new feature in the relevant documentation.
  • I have added this feature to 'Pending' in the RELEASE_NOTES.md file (if one exists).
  • If this is a breaking change I've explained why.

Copy link

changeset-bot bot commented Dec 23, 2024

⚠️ No Changeset found

Latest commit: 296821f

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Member

@benjie benjie left a comment

Choose a reason for hiding this comment

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

Thanks for starting work on this; it would be great to add @whatwg-node/server as a supported server framework!

Please be sure to format your code; you can run yarn lint:fix in the root. May be worth installing a prettier extension into your editor of choice and configuring it so that it happens automatically on save.

We will also need some tests before this can be merged. Probably makes sense for makeExampleServer() in this file:

https://github.com/graphile/crystal/blob/36c41e80bfe312f584af42545688fb78d3adaf3f/grafast/grafserv/__tests__/graphql-http.test.ts

to accept an argument choosing the server framework to use - then we can test it on each different adaptor easily using the same test suite.

@@ -4,7 +4,7 @@ import type { AddressInfo } from "node:net";
import { constant, error, makeGrafastSchema } from "grafast";
import { resolvePreset } from "graphile-config";

import { grafserv } from "../src/servers/node/index.js";
import { grafserv } from "../src/servers/whtatwg-node-server";
Copy link
Member

@benjie benjie Dec 23, 2024

Choose a reason for hiding this comment

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

Typo? Should be whatwg?

@@ -36,8 +36,7 @@ export async function makeExampleServer(
});

const serv = grafserv({ schema, preset });
const server = createServer();
serv.addTo(server);
const server = createServer(serv.createHandler());
Copy link
Member

Choose a reason for hiding this comment

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

Please don't make this change, it does not handle websockets and other concerns. It means that serv is not passed an instance of server and thus cannot add any event listeners.

@@ -115,6 +115,7 @@
"@types/koa": "^2.13.8",
"@types/koa-bodyparser": "^4.3.10",
"@whatwg-node/fetch": "^0.9.10",
"@whatwg-node/server": "^0.9.64",
Copy link
Member

Choose a reason for hiding this comment

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

Looking at the code, this should also be an optional peer dependency, otherwise createServerAdaptor cannot be imported? (The other adaptors do not require anything but types be imported.)

Comment on lines +28 to +29
httpVersionMajor: 1,
httpVersionMinor: 0,
Copy link
Member

Choose a reason for hiding this comment

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

1.0 seems unlikely, that's ancient! Are we not able to determine the HTTP version from a WHATWG server?

return {
httpVersionMajor: 1,
httpVersionMinor: 0,
isSecure: url.protocol === 'https://',
Copy link
Member

Choose a reason for hiding this comment

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

Are you sure this is correct? The protocol is actually https:, the // is not part of the protocol itself (see for example location.protocol in a browser).

https://developer.mozilla.org/en-US/docs/Web/API/URL/protocol

Comment on lines +38 to +42
const text = await request.text()
return {
type: "text",
text,
};
Copy link
Member

Choose a reason for hiding this comment

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

Are we certain the body will always be text?

};
},
requestContext: {
whatwg: {request}
Copy link
Member

Choose a reason for hiding this comment

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

This should include a version number: whatwgv1 or similar.

requestContext: {
whatwg: {request}
},
preferJSON: true,
Copy link
Member

Choose a reason for hiding this comment

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

Disappointing, this opts out of some performance enhancements.

case "buffer": {
const { statusCode, headers, buffer } = response;
const respHeaders = new Headers(headers)
return new Response(buffer.toString('utf8'), {status: statusCode, headers:respHeaders})
Copy link
Member

Choose a reason for hiding this comment

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

There's no guarantee that the buffer can safely be represented as a utf8 string; is it not possible to return binary data directly to the response?

),
);
})
}
Copy link
Member

Choose a reason for hiding this comment

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

Please also implement an addTo method to follow convention; e.g.:

async addTo(
server: HTTPServer | HTTPSServer,
addExclusiveWebsocketHandler = true,
) {
const handler = this._createHandler();
server.on("request", handler);
this.onRelease(() => {
server.off("request", handler);
});

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: 🌱 In Progress
Development

Successfully merging this pull request may close these issues.

2 participants