@jsenv/server 17.7.0 → 17.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/jsenv_server.js +16 -5
- package/docs/handling_requests.md +2 -0
- package/package.json +2 -2
- package/src/router/router.js +16 -5
package/dist/jsenv_server.js
CHANGED
|
@@ -6317,9 +6317,7 @@ const createRouter = (
|
|
|
6317
6317
|
};
|
|
6318
6318
|
};
|
|
6319
6319
|
const forEachMethodAllowed = (route, onMethodAllowed) => {
|
|
6320
|
-
const
|
|
6321
|
-
route.method === "*" ? HTTP_METHODS : [route.method];
|
|
6322
|
-
for (const supportedMethod of supportedMethods) {
|
|
6320
|
+
for (const supportedMethod of route.methods) {
|
|
6323
6321
|
onMethodAllowed(supportedMethod);
|
|
6324
6322
|
}
|
|
6325
6323
|
};
|
|
@@ -6555,7 +6553,9 @@ It should be should be one of route.${routePropertyName}: ${availableValues.join
|
|
|
6555
6553
|
// matching every resource ("GET *", "GET /*") names no resource, so
|
|
6556
6554
|
// it cannot make that assertion and an unknown address stays a 404
|
|
6557
6555
|
if (!route.isFallback && !route.matchesEveryResource) {
|
|
6558
|
-
|
|
6556
|
+
for (const routeMethod of route.methods) {
|
|
6557
|
+
wouldHaveMatched.methodSet.add(routeMethod);
|
|
6558
|
+
}
|
|
6559
6559
|
}
|
|
6560
6560
|
continue;
|
|
6561
6561
|
}
|
|
@@ -6876,6 +6876,14 @@ const createRoute = ({
|
|
|
6876
6876
|
) {
|
|
6877
6877
|
availableMediaTypes.push(extensionWellKnownContentType);
|
|
6878
6878
|
}
|
|
6879
|
+
// HEAD is GET without the body (RFC 9110 §9.3.2): a GET route answers it and
|
|
6880
|
+
// the server drops the body when sending
|
|
6881
|
+
const methods =
|
|
6882
|
+
method === "*"
|
|
6883
|
+
? HTTP_METHODS
|
|
6884
|
+
: method === "GET"
|
|
6885
|
+
? ["GET", "HEAD"]
|
|
6886
|
+
: [method];
|
|
6879
6887
|
const resourcePattern = createResourcePattern(resource);
|
|
6880
6888
|
const headersPattern = headers ? createHeadersPattern(headers) : null;
|
|
6881
6889
|
|
|
@@ -6895,8 +6903,11 @@ const createRoute = ({
|
|
|
6895
6903
|
availableVersions,
|
|
6896
6904
|
availableEncodings,
|
|
6897
6905
|
acceptedMediaTypes,
|
|
6906
|
+
methods,
|
|
6898
6907
|
matchMethod:
|
|
6899
|
-
method === "*"
|
|
6908
|
+
method === "*"
|
|
6909
|
+
? () => true
|
|
6910
|
+
: (requestMethod) => methods.includes(requestMethod),
|
|
6900
6911
|
matchResource:
|
|
6901
6912
|
resource === "*"
|
|
6902
6913
|
? () => true
|
|
@@ -31,6 +31,8 @@ await startServer({
|
|
|
31
31
|
| `GET /*` | anything, with the path in `request.params[0]` |
|
|
32
32
|
| `GET *` | anything: a catch-all, put it last |
|
|
33
33
|
|
|
34
|
+
A `GET` route also answers `HEAD`: the response is built the same way and sent without its body.
|
|
35
|
+
|
|
34
36
|
Only `*` widens a pattern. Routes are tried in order, so a route covering others (`GET /docs/*`, `GET *`) goes after them. `fetch` can be async; returning `null` or `undefined` declines the request and the next route is tried.
|
|
35
37
|
|
|
36
38
|
When no route answers, the router builds the response from what almost matched:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jsenv/server",
|
|
3
|
-
"version": "17.7.
|
|
3
|
+
"version": "17.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A modern Node.js HTTP server with declarative routing, content negotiation, and WebSocket support",
|
|
6
6
|
"repository": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"prepublishOnly": "npm run build"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"launch-editor": "2.14.
|
|
40
|
+
"launch-editor": "2.14.2"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@jsenv/abort": "../../tooling/abort",
|
package/src/router/router.js
CHANGED
|
@@ -121,9 +121,7 @@ export const createRouter = (
|
|
|
121
121
|
};
|
|
122
122
|
};
|
|
123
123
|
const forEachMethodAllowed = (route, onMethodAllowed) => {
|
|
124
|
-
const
|
|
125
|
-
route.method === "*" ? HTTP_METHODS : [route.method];
|
|
126
|
-
for (const supportedMethod of supportedMethods) {
|
|
124
|
+
for (const supportedMethod of route.methods) {
|
|
127
125
|
onMethodAllowed(supportedMethod);
|
|
128
126
|
}
|
|
129
127
|
};
|
|
@@ -359,7 +357,9 @@ It should be should be one of route.${routePropertyName}: ${availableValues.join
|
|
|
359
357
|
// matching every resource ("GET *", "GET /*") names no resource, so
|
|
360
358
|
// it cannot make that assertion and an unknown address stays a 404
|
|
361
359
|
if (!route.isFallback && !route.matchesEveryResource) {
|
|
362
|
-
|
|
360
|
+
for (const routeMethod of route.methods) {
|
|
361
|
+
wouldHaveMatched.methodSet.add(routeMethod);
|
|
362
|
+
}
|
|
363
363
|
}
|
|
364
364
|
continue;
|
|
365
365
|
}
|
|
@@ -683,6 +683,14 @@ const createRoute = ({
|
|
|
683
683
|
) {
|
|
684
684
|
availableMediaTypes.push(extensionWellKnownContentType);
|
|
685
685
|
}
|
|
686
|
+
// HEAD is GET without the body (RFC 9110 §9.3.2): a GET route answers it and
|
|
687
|
+
// the server drops the body when sending
|
|
688
|
+
const methods =
|
|
689
|
+
method === "*"
|
|
690
|
+
? HTTP_METHODS
|
|
691
|
+
: method === "GET"
|
|
692
|
+
? ["GET", "HEAD"]
|
|
693
|
+
: [method];
|
|
686
694
|
const resourcePattern = createResourcePattern(resource);
|
|
687
695
|
const headersPattern = headers ? createHeadersPattern(headers) : null;
|
|
688
696
|
|
|
@@ -702,8 +710,11 @@ const createRoute = ({
|
|
|
702
710
|
availableVersions,
|
|
703
711
|
availableEncodings,
|
|
704
712
|
acceptedMediaTypes,
|
|
713
|
+
methods,
|
|
705
714
|
matchMethod:
|
|
706
|
-
method === "*"
|
|
715
|
+
method === "*"
|
|
716
|
+
? () => true
|
|
717
|
+
: (requestMethod) => methods.includes(requestMethod),
|
|
707
718
|
matchResource:
|
|
708
719
|
resource === "*"
|
|
709
720
|
? () => true
|