From 64cf3d7b427338aa03224d61a8a238b2e038c836 Mon Sep 17 00:00:00 2001
From: Davide <43080019+edivados@users.noreply.github.com>
Date: Thu, 11 Jan 2024 22:05:53 +0100
Subject: [PATCH 1/7] restore h3's toWebRequest
---
packages/vinxi/runtime/server.js | 22 ++--------------------
1 file changed, 2 insertions(+), 20 deletions(-)
diff --git a/packages/vinxi/runtime/server.js b/packages/vinxi/runtime/server.js
index adf4c515..bea2f153 100644
--- a/packages/vinxi/runtime/server.js
+++ b/packages/vinxi/runtime/server.js
@@ -97,6 +97,7 @@ import {
toNodeListener,
toPlainHandler,
toWebHandler,
+ toWebRequest,
unsealSession,
updateSession,
use,
@@ -133,26 +134,6 @@ export function defineMiddleware(options) {
return options;
}
-export function toWebRequest(/** @type {H3Event} */ event) {
- /**
- * @type {ReadableStream | undefined}
- */
- let readableStream;
- return new Request(getRequestURL(event), {
- // @ts-ignore Undici option
- duplex: "half",
- method: event.method,
- headers: event.headers,
- get body() {
- if (readableStream) {
- return readableStream;
- }
- readableStream = getRequestWebStream(event);
- return readableStream;
- },
- });
-}
-
export {
H3Error,
H3Event,
@@ -252,6 +233,7 @@ export {
toNodeListener,
toPlainHandler,
toWebHandler,
+ toWebRequest,
unsealSession,
updateSession,
use,
From 4a59a05cb7889a618145411a69079285335076dd Mon Sep 17 00:00:00 2001
From: Davide <43080019+edivados@users.noreply.github.com>
Date: Sat, 13 Jan 2024 00:52:01 +0100
Subject: [PATCH 2/7] Revert "restore h3's toWebRequest"
This reverts commit 64cf3d7b427338aa03224d61a8a238b2e038c836.
---
packages/vinxi/runtime/server.js | 22 ++++++++++++++++++++--
1 file changed, 20 insertions(+), 2 deletions(-)
diff --git a/packages/vinxi/runtime/server.js b/packages/vinxi/runtime/server.js
index bea2f153..adf4c515 100644
--- a/packages/vinxi/runtime/server.js
+++ b/packages/vinxi/runtime/server.js
@@ -97,7 +97,6 @@ import {
toNodeListener,
toPlainHandler,
toWebHandler,
- toWebRequest,
unsealSession,
updateSession,
use,
@@ -134,6 +133,26 @@ export function defineMiddleware(options) {
return options;
}
+export function toWebRequest(/** @type {H3Event} */ event) {
+ /**
+ * @type {ReadableStream | undefined}
+ */
+ let readableStream;
+ return new Request(getRequestURL(event), {
+ // @ts-ignore Undici option
+ duplex: "half",
+ method: event.method,
+ headers: event.headers,
+ get body() {
+ if (readableStream) {
+ return readableStream;
+ }
+ readableStream = getRequestWebStream(event);
+ return readableStream;
+ },
+ });
+}
+
export {
H3Error,
H3Event,
@@ -233,7 +252,6 @@ export {
toNodeListener,
toPlainHandler,
toWebHandler,
- toWebRequest,
unsealSession,
updateSession,
use,
From 4f596185bec97d14705e19cef18854fbc5463636 Mon Sep 17 00:00:00 2001
From: Davide <43080019+edivados@users.noreply.github.com>
Date: Sat, 13 Jan 2024 01:57:20 +0100
Subject: [PATCH 3/7] add test showing pending request issue with toWebRequest
---
pnpm-lock.yaml | 34 +-
.../react-to-web-request/CHANGELOG.md | 435 ++++++++++++++++++
test/templates/react-to-web-request/README.md | 0
.../react-to-web-request/app.config.js | 24 +
.../react-to-web-request/app/App.tsx | 14 +
.../react-to-web-request/app/client.tsx | 5 +
.../react-to-web-request/app/middleware.ts | 7 +
.../templates/react-to-web-request/index.html | 13 +
.../react-to-web-request/package.json | 24 +
.../react-to-web-request/public/favicon.ico | Bin 0 -> 664 bytes
.../react-to-web-request/tsconfig.json | 14 +
test/to-web-request.test.ts | 43 ++
12 files changed, 611 insertions(+), 2 deletions(-)
create mode 100644 test/templates/react-to-web-request/CHANGELOG.md
create mode 100644 test/templates/react-to-web-request/README.md
create mode 100644 test/templates/react-to-web-request/app.config.js
create mode 100644 test/templates/react-to-web-request/app/App.tsx
create mode 100644 test/templates/react-to-web-request/app/client.tsx
create mode 100644 test/templates/react-to-web-request/app/middleware.ts
create mode 100644 test/templates/react-to-web-request/index.html
create mode 100644 test/templates/react-to-web-request/package.json
create mode 100644 test/templates/react-to-web-request/public/favicon.ico
create mode 100644 test/templates/react-to-web-request/tsconfig.json
create mode 100644 test/to-web-request.test.ts
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bea4e4fd..d2990171 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -1514,6 +1514,37 @@ importers:
specifier: ^5.2.2
version: 5.2.2
+ test/templates/react-to-web-request:
+ dependencies:
+ '@vinxi/react':
+ specifier: workspace:*
+ version: link:../../../packages/vinxi-react
+ '@vinxi/server-functions':
+ specifier: workspace:*
+ version: link:../../../packages/vinxi-server-functions
+ '@vitejs/plugin-react':
+ specifier: ^4.0.4
+ version: 4.1.1(vite@4.5.0)
+ path-to-regexp:
+ specifier: ^6.2.1
+ version: 6.2.1
+ react:
+ specifier: 0.0.0-experimental-035a41c4e-20230704
+ version: 0.0.0-experimental-035a41c4e-20230704
+ react-dom:
+ specifier: 0.0.0-experimental-035a41c4e-20230704
+ version: 0.0.0-experimental-035a41c4e-20230704(react@0.0.0-experimental-035a41c4e-20230704)
+ vinxi:
+ specifier: workspace:*
+ version: link:../../../packages/vinxi
+ devDependencies:
+ '@types/react':
+ specifier: ^18.2.21
+ version: 18.2.37
+ '@types/react-dom':
+ specifier: ^18.2.7
+ version: 18.2.14
+
packages:
/@adobe/css-tools@4.3.1:
@@ -1685,7 +1716,7 @@ packages:
'@babel/helper-compilation-targets': 7.22.15
'@babel/helper-module-transforms': 7.23.0(@babel/core@7.23.2)
'@babel/helpers': 7.23.2
- '@babel/parser': 7.23.0
+ '@babel/parser': 7.23.5
'@babel/template': 7.22.15
'@babel/traverse': 7.23.2
'@babel/types': 7.23.0
@@ -1885,7 +1916,6 @@ packages:
hasBin: true
dependencies:
'@babel/types': 7.23.0
- dev: false
/@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.23.2):
resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==}
diff --git a/test/templates/react-to-web-request/CHANGELOG.md b/test/templates/react-to-web-request/CHANGELOG.md
new file mode 100644
index 00000000..e032d339
--- /dev/null
+++ b/test/templates/react-to-web-request/CHANGELOG.md
@@ -0,0 +1,435 @@
+# app
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [769a055]
+- Updated dependencies [08cd450]
+- Updated dependencies [2e85423]
+- Updated dependencies [bb16563]
+- Updated dependencies [a011795]
+ - vinxi@0.1.2
+ - @vinxi/react@0.1.1
+ - @vinxi/server-functions@0.1.1
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [9c60b73]
+ - vinxi@0.1.1
+ - @vinxi/react@0.1.0
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [e31abb2]
+- Updated dependencies [b2ef06f]
+ - vinxi@0.1.0
+ - @vinxi/react@0.1.0
+ - @vinxi/server-functions@1.0.0
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [2c65c91]
+- Updated dependencies [8c87b24]
+ - vinxi@0.0.64
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.61
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [6f695e2]
+ - vinxi@0.0.63
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.60
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [b236b2a]
+ - vinxi@0.0.62
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.59
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [86982a4]
+- Updated dependencies [b7332a6]
+ - @vinxi/server-functions@0.0.58
+ - vinxi@0.0.61
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [1261c16]
+ - vinxi@0.0.60
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.57
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [44f46ae]
+ - vinxi@0.0.59
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.56
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [b654e60]
+ - vinxi@0.0.58
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.55
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [ff03255]
+- Updated dependencies [783d22b]
+- Updated dependencies [0160b5c]
+ - vinxi@0.0.57
+ - @vinxi/server-functions@0.0.54
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [d5262b3]
+- Updated dependencies [5694f29]
+ - vinxi@0.0.56
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.53
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [88201f3]
+- Updated dependencies [cbba2d7]
+- Updated dependencies [c5a94cf]
+- Updated dependencies [e53f24a]
+- Updated dependencies [9325a54]
+- Updated dependencies [a0974f0]
+- Updated dependencies [c4b76ed]
+- Updated dependencies [7af0a15]
+ - vinxi@0.0.55
+ - @vinxi/server-functions@0.0.52
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [7ec78e2]
+ - vinxi@0.0.54
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.51
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [b601463]
+- Updated dependencies [68cab94]
+ - vinxi@0.0.53
+ - @vinxi/server-functions@0.0.50
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [366b29b]
+ - vinxi@0.0.52
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.49
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [7276f73]
+ - vinxi@0.0.51
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.48
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [e4a6251]
+ - vinxi@0.0.50
+ - @vinxi/react@0.0.12
+ - @vinxi/server-functions@0.0.47
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [0f9a5df]
+- Updated dependencies [e6205a4]
+- Updated dependencies [d8ef7c9]
+- Updated dependencies [e7313f4]
+ - @vinxi/server-functions@0.0.46
+ - vinxi@0.0.49
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [800f557]
+ - @vinxi/server-functions@0.0.45
+
+## null
+
+### Patch Changes
+
+- @vinxi/server-functions@0.0.44
+
+## null
+
+### Patch Changes
+
+- @vinxi/server-functions@0.0.43
+
+## null
+
+### Patch Changes
+
+- @vinxi/server-functions@0.0.42
+
+## null
+
+### Patch Changes
+
+- @vinxi/server-functions@0.0.41
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [fc7494d]
+- Updated dependencies [4e4c047]
+- Updated dependencies [8ef044b]
+ - vinxi@0.0.48
+ - @vinxi/server-functions@0.0.40
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [8d24beb]
+ - vinxi@0.0.47
+ - @vinxi/server-functions@0.0.39
+ - @vinxi/react@0.0.12
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [978b04a]
+ - vinxi@0.0.43
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [e8fdad4]
+- Updated dependencies [291a5cf]
+ - vinxi@0.0.42
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [2e52d87]
+ - vinxi@0.0.41
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [0335776]
+ - vinxi@0.0.40
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [f237894]
+- Updated dependencies [d620072]
+ - vinxi@0.0.39
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [1284791]
+ - vinxi@0.0.38
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [6ff575e]
+- Updated dependencies [f2cbc3c]
+- Updated dependencies [b437331]
+- Updated dependencies [e87800e]
+ - vinxi@0.0.37
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [49e4e03]
+- Updated dependencies [a009733]
+ - vinxi@0.0.36
+
+## null
+
+### Patch Changes
+
+- vinxi@0.0.35
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [355daea]
+ - vinxi@0.0.34
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [1dec590]
+ - vinxi@0.0.33
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [982147a]
+ - vinxi@0.0.32
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [94f59aa]
+- Updated dependencies [bc82d8e]
+- Updated dependencies [1d8b542]
+- Updated dependencies [5bf5e03]
+- Updated dependencies [4c7fd35]
+- Updated dependencies [0f4b3ee]
+- Updated dependencies [ad62318]
+- Updated dependencies [c223ab6]
+- Updated dependencies [94f59aa]
+ - vinxi@0.0.31
+ - @vinxi/react@0.0.11
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [fd06048]
+- Updated dependencies [0f14555]
+- Updated dependencies [82267c5]
+ - vinxi@0.0.30
+ - @vinxi/react@0.0.10
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [8058084]
+ - vinxi@0.0.29
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [b934e84]
+- Updated dependencies [17693dc]
+- Updated dependencies [d6305b8]
+- Updated dependencies [cb91c48]
+- Updated dependencies [085116d]
+- Updated dependencies [f1ee5b8]
+ - vinxi@0.0.28
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [7803042]
+ - vinxi@0.0.27
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [2b17e0d]
+ - vinxi@0.0.26
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [552d8ca]
+ - vinxi@0.0.25
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [47abc3c]
+ - vinxi@0.0.24
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [ec37a2e]
+ - @vinxi/react@0.0.9
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [76da329]
+ - @vinxi/react@0.0.8
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [46f3426]
+ - @vinxi/react@0.0.7
+ - vinxi@0.0.23
+
+## null
+
+### Patch Changes
+
+- Updated dependencies [5834c1a]
+ - @vinxi/react@0.0.6
+ - vinxi@0.0.22
diff --git a/test/templates/react-to-web-request/README.md b/test/templates/react-to-web-request/README.md
new file mode 100644
index 00000000..e69de29b
diff --git a/test/templates/react-to-web-request/app.config.js b/test/templates/react-to-web-request/app.config.js
new file mode 100644
index 00000000..af778a85
--- /dev/null
+++ b/test/templates/react-to-web-request/app.config.js
@@ -0,0 +1,24 @@
+import reactRefresh from "@vitejs/plugin-react";
+import { serverFunctions } from "@vinxi/server-functions/plugin";
+import { createApp } from "vinxi";
+
+export default createApp({
+ routers: [
+ {
+ name: "public",
+ mode: "static",
+ dir: "./public",
+ base: "/",
+ },
+ {
+ name: "client",
+ mode: "spa",
+ handler: "./index.html",
+ target: "browser",
+ plugins: () => [serverFunctions.client(), reactRefresh()],
+ },
+ serverFunctions.router({
+ middleware: "./app/middleware.ts"
+ })
+ ],
+});
diff --git a/test/templates/react-to-web-request/app/App.tsx b/test/templates/react-to-web-request/app/App.tsx
new file mode 100644
index 00000000..96a41359
--- /dev/null
+++ b/test/templates/react-to-web-request/app/App.tsx
@@ -0,0 +1,14 @@
+async function getData() {
+ "use server";
+ console.log(`I have not been blocked.`);
+}
+
+export function App() {
+ return (
+
+
+
+ );
+}
diff --git a/test/templates/react-to-web-request/app/client.tsx b/test/templates/react-to-web-request/app/client.tsx
new file mode 100644
index 00000000..1f24dbd9
--- /dev/null
+++ b/test/templates/react-to-web-request/app/client.tsx
@@ -0,0 +1,5 @@
+///
+import ReactDOM from "react-dom/client";
+import { App } from "./App";
+
+ReactDOM.createRoot(document.getElementById("root")).render();
diff --git a/test/templates/react-to-web-request/app/middleware.ts b/test/templates/react-to-web-request/app/middleware.ts
new file mode 100644
index 00000000..24fe6ee7
--- /dev/null
+++ b/test/templates/react-to-web-request/app/middleware.ts
@@ -0,0 +1,7 @@
+import { defineMiddleware, getRequestURL, toWebRequest } from "vinxi/server";
+
+export default defineMiddleware({
+ onRequest: event => {
+ toWebRequest(event);
+ }
+});
\ No newline at end of file
diff --git a/test/templates/react-to-web-request/index.html b/test/templates/react-to-web-request/index.html
new file mode 100644
index 00000000..7a6d0b58
--- /dev/null
+++ b/test/templates/react-to-web-request/index.html
@@ -0,0 +1,13 @@
+
+
+
+
+
+ Document
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/test/templates/react-to-web-request/package.json b/test/templates/react-to-web-request/package.json
new file mode 100644
index 00000000..afd50997
--- /dev/null
+++ b/test/templates/react-to-web-request/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "test-react-to-web-request",
+ "type": "module",
+ "private": true,
+ "version": null,
+ "scripts": {
+ "dev": "vinxi dev",
+ "build": "vinxi build",
+ "start": "node .output/server/index.mjs"
+ },
+ "dependencies": {
+ "@vinxi/react": "workspace:*",
+ "@vitejs/plugin-react": "^4.0.4",
+ "@vinxi/server-functions": "workspace:*",
+ "path-to-regexp": "^6.2.1",
+ "react": "0.0.0-experimental-035a41c4e-20230704",
+ "react-dom": "0.0.0-experimental-035a41c4e-20230704",
+ "vinxi": "workspace:*"
+ },
+ "devDependencies": {
+ "@types/react": "^18.2.21",
+ "@types/react-dom": "^18.2.7"
+ }
+}
diff --git a/test/templates/react-to-web-request/public/favicon.ico b/test/templates/react-to-web-request/public/favicon.ico
new file mode 100644
index 0000000000000000000000000000000000000000..fb282da0719ef6ab4c1732df93be6216b0d85520
GIT binary patch
literal 664
zcmV;J0%!e+P)m9ebk1R
zejT~~6f_`?;`cEd!+`7(hw@%%2;?RN8gX-L?z6cM(
zKoG@&w+0}f@Pfvwc+deid)qgE!L$ENKYjViZC_Zcr>L(`2oXUT8f0mRQ(6-=HN_Ai
zeBBEz3WP+1Cw`m!49Wf!MnZzp5bH8VkR~BcJ1s-j90TAS2Yo4j!J|KodxYR%3Numw
zA?gq6e`5@!W~F$_De3yt&uspo&2yLb$(NwcPPI-4LGc!}HdY%jfq@AFs8LiZ4k(p}
zZ!c9o+qbWYs-Mg
zgdyTALzJX&7QXHdI_DPTFL33;w}88{e6Zk)MX0kN{3DX9uz#O_L58&XRH$Nvvu;fO
zf&)7@?C~$z1K<>j0ga$$MIg+5xN;eQ?1-CA=`^Y169@Ab6!vcaNP=hxfKN%@Ly^R*
zK1iv*s1Yl6_dVyz8>ZqYhz6J4|3fQ@2LQeX@^%W(B~8>=MoEmBEGGD1;gHXlpX>!W
ym)!leA2L@`cpb^hy)P75=I!`pBYxP7<2VfQ3j76qLgzIA0000 {
+ let fixture: Fixture;
+ let appFixture: AppFixture;
+
+ test.beforeAll(async () => {
+ fixture = await createDevFixture({
+ files: {},
+ template: "react-to-web-request",
+ });
+
+ appFixture = await fixture.createServer();
+ });
+
+ test.afterAll(async () => {
+ await appFixture.close();
+ });
+
+ let logs: string[] = [];
+
+ test.beforeEach(({ page }) => {
+ page.on("console", (msg) => {
+ logs.push(msg.text());
+ });
+ });
+
+ test("readBody call after toWebRequest does not block", async ({ page }) => {
+ let app = new PlaywrightFixture(appFixture, page);
+ await app.goto("/", true);
+
+ const el = await page.$("[data-test-id=button]");
+ await el.click();
+
+ const responses = app.collectResponses();
+ await (new Promise(resolve => setTimeout(resolve, 200)));
+ test.expect(responses.length).toBe(1);
+ });
+});
+
From 02142f593b401557af9c2135ec52eadd687cc118 Mon Sep 17 00:00:00 2001
From: Davide <43080019+edivados@users.noreply.github.com>
Date: Sat, 13 Jan 2024 02:23:08 +0100
Subject: [PATCH 4/7] patch toWebRequest
---
packages/vinxi/runtime/server.js | 30 ++++++++-----------
.../react-to-web-request/app/middleware.ts | 2 +-
2 files changed, 13 insertions(+), 19 deletions(-)
diff --git a/packages/vinxi/runtime/server.js b/packages/vinxi/runtime/server.js
index adf4c515..02a432a4 100644
--- a/packages/vinxi/runtime/server.js
+++ b/packages/vinxi/runtime/server.js
@@ -97,6 +97,7 @@ import {
toNodeListener,
toPlainHandler,
toWebHandler,
+ toWebRequest as toWebRequestH3,
unsealSession,
updateSession,
use,
@@ -133,24 +134,17 @@ export function defineMiddleware(options) {
return options;
}
-export function toWebRequest(/** @type {H3Event} */ event) {
- /**
- * @type {ReadableStream | undefined}
- */
- let readableStream;
- return new Request(getRequestURL(event), {
- // @ts-ignore Undici option
- duplex: "half",
- method: event.method,
- headers: event.headers,
- get body() {
- if (readableStream) {
- return readableStream;
- }
- readableStream = getRequestWebStream(event);
- return readableStream;
- },
- });
+/**
+ * @param {H3Event} event
+ * @returns {Request}
+ */
+export function toWebRequest(event) {
+ event.web ??= {
+ request: toWebRequestH3(event),
+ url: getRequestURL(event)
+ };
+ // @ts-ignore
+ return event.web.request;
}
export {
diff --git a/test/templates/react-to-web-request/app/middleware.ts b/test/templates/react-to-web-request/app/middleware.ts
index 24fe6ee7..52e93471 100644
--- a/test/templates/react-to-web-request/app/middleware.ts
+++ b/test/templates/react-to-web-request/app/middleware.ts
@@ -1,4 +1,4 @@
-import { defineMiddleware, getRequestURL, toWebRequest } from "vinxi/server";
+import { defineMiddleware, toWebRequest } from "vinxi/server";
export default defineMiddleware({
onRequest: event => {
From a725c692342b70a48e9bf30305ab1b772e666741 Mon Sep 17 00:00:00 2001
From: Davide <43080019+edivados@users.noreply.github.com>
Date: Sat, 13 Jan 2024 03:08:55 +0100
Subject: [PATCH 5/7] remove jsdoc from toWebRequest
---
packages/vinxi/runtime/server.js | 5 -----
1 file changed, 5 deletions(-)
diff --git a/packages/vinxi/runtime/server.js b/packages/vinxi/runtime/server.js
index 02a432a4..14e55097 100644
--- a/packages/vinxi/runtime/server.js
+++ b/packages/vinxi/runtime/server.js
@@ -134,16 +134,11 @@ export function defineMiddleware(options) {
return options;
}
-/**
- * @param {H3Event} event
- * @returns {Request}
- */
export function toWebRequest(event) {
event.web ??= {
request: toWebRequestH3(event),
url: getRequestURL(event)
};
- // @ts-ignore
return event.web.request;
}
From fd5740c1d68aede3440d9bbfe3ad2a3706a1b6ef Mon Sep 17 00:00:00 2001
From: Nikhil Saraf
Date: Sun, 14 Jan 2024 15:22:00 +0530
Subject: [PATCH 6/7] Create twelve-falcons-hang.md
---
.changeset/twelve-falcons-hang.md | 7 +++++++
1 file changed, 7 insertions(+)
create mode 100644 .changeset/twelve-falcons-hang.md
diff --git a/.changeset/twelve-falcons-hang.md b/.changeset/twelve-falcons-hang.md
new file mode 100644
index 00000000..04e04d13
--- /dev/null
+++ b/.changeset/twelve-falcons-hang.md
@@ -0,0 +1,7 @@
+---
+"vinxi": patch
+"test-react-to-web-request": patch
+"test-react": patch
+---
+
+fix: non-blocking `readBody` with web requests
From 432013cd223b8c96d25c29e21fb8c15d81c70bd1 Mon Sep 17 00:00:00 2001
From: Nikhil Saraf
Date: Sun, 14 Jan 2024 16:34:57 +0530
Subject: [PATCH 7/7] fix server.js
---
packages/vinxi/runtime/server.js | 482 ++++++++++++++++---------------
1 file changed, 247 insertions(+), 235 deletions(-)
diff --git a/packages/vinxi/runtime/server.js b/packages/vinxi/runtime/server.js
index 5e199eaf..e34c9556 100644
--- a/packages/vinxi/runtime/server.js
+++ b/packages/vinxi/runtime/server.js
@@ -51,8 +51,7 @@ import {
getResponseStatus,
getResponseStatusText,
getRouterParam,
- getRouterParams,
- getSession,
+ getRouterParams, // getSession,
getValidatedQuery,
getValidatedRouterParams,
handleCacheHeaders,
@@ -76,8 +75,7 @@ import {
readValidatedBody,
removeResponseHeader,
sanitizeStatusCode,
- sanitizeStatusMessage,
- sealSession,
+ sanitizeStatusMessage, // sealSession,
send,
sendError,
sendNoContent,
@@ -98,11 +96,9 @@ import {
toPlainHandler,
toWebHandler,
toWebRequest as toWebRequestH3,
- unsealSession,
- updateSession,
+ unsealSession, // updateSession,
use,
- useBase,
- useSession,
+ useBase, // useSession,
writeEarlyHints,
} from "h3";
import { seal, defaults as sealDefaults } from "iron-webcrypto";
@@ -115,7 +111,7 @@ import crypto from "uncrypto";
* @param {any} value
*/
export function setContext(event, key, value) {
- event.context[key] = value;
+ event.context[key] = value;
}
/**
@@ -124,7 +120,7 @@ export function setContext(event, key, value) {
* @param {string} key
*/
export function getContext(event, key) {
- return event.context[key];
+ return event.context[key];
}
/**
@@ -133,251 +129,267 @@ export function getContext(event, key) {
* @returns
*/
export function defineMiddleware(options) {
- return options;
+ return options;
}
-export function toWebRequest(event) {
+export function toWebRequest(/** @type {import('h3').H3Event} */ event) {
event.web ??= {
request: toWebRequestH3(event),
- url: getRequestURL(event)
+ url: getRequestURL(event),
};
return event.web.request;
}
const DEFAULT_NAME = "h3";
const DEFAULT_COOKIE = {
- path: "/",
- secure: true,
- httpOnly: true,
+ path: "/",
+ secure: true,
+ httpOnly: true,
};
-export async function useSession(event, config) {
- // Create a synced wrapper around the session
- const sessionName = config.name || DEFAULT_NAME;
- await getSession(event, config); // Force init
- const sessionManager = {
- get id() {
- return event.context.sessions?.[sessionName]?.id;
- },
- get data() {
- return (event.context.sessions?.[sessionName]?.data || {});
- },
- update: async (update) => {
- await updateSession(event, config, update);
- return sessionManager;
- },
- clear: async () => {
- await clearSession(event, config);
- return sessionManager;
- },
- };
- return sessionManager;
+export async function useSession(
+ /** @type {import('h3').H3Event} */ event,
+ /** @type {import('h3').SessionConfig} */ config,
+) {
+ // Create a synced wrapper around the session
+ const sessionName = config.name || DEFAULT_NAME;
+ await getSession(event, config); // Force init
+
+ /** @type {Awaited>} */
+ const sessionManager = {
+ get id() {
+ return event.context.sessions?.[sessionName]?.id;
+ },
+ get data() {
+ return event.context.sessions?.[sessionName]?.data || {};
+ },
+ update: async (update) => {
+ await updateSession(event, config, update);
+ return sessionManager;
+ },
+ clear: async () => {
+ await clearSession(event, config);
+ return sessionManager;
+ },
+ };
+ return sessionManager;
}
-export async function getSession(event, config) {
- const sessionName = config.name || DEFAULT_NAME;
- // Return existing session if available
- if (!event.context.sessions) {
- event.context.sessions = Object.create(null);
- }
- if (!event.context.sessionLocks) {
- event.context.sessionLocks = Object.create(null);
- }
- // Wait for existing session to load
- if (event.context.sessionLocks[sessionName]) {
- await event.context.sessionLocks[sessionName];
- }
- if (event.context.sessions[sessionName]) {
- return event.context.sessions[sessionName];
- }
- // Prepare an empty session object and store in context
- const session = {
- id: "",
- createdAt: 0,
- data: Object.create(null),
- };
- event.context.sessions[sessionName] = session;
- // Try to load session
- let sealedSession;
- // Try header first
- if (config.sessionHeader !== false) {
- const headerName = typeof config.sessionHeader === "string"
- ? config.sessionHeader.toLowerCase()
- : `x-${sessionName.toLowerCase()}-session`;
- const headerValue = event.node.req.headers[headerName];
- if (typeof headerValue === "string") {
- sealedSession = headerValue;
- }
- }
- // Fallback to cookies
- if (!sealedSession) {
- sealedSession = getCookie(event, sessionName);
- }
- if (sealedSession) {
- // Unseal session data from cookie
- const lock = unsealSession(event, config, sealedSession)
- .catch(() => {})
- .then((unsealed) => {
- Object.assign(session, unsealed);
- // make sure deletion occurs before promise resolves
- delete event.context.sessionLocks[sessionName];
- });
+export async function getSession(
+ /** @type {import('h3').H3Event} */ event,
+ /** @type {import('h3').SessionConfig} */ config,
+) {
+ const sessionName = config.name || DEFAULT_NAME;
+ // Return existing session if available
+ if (!event.context.sessions) {
+ event.context.sessions = Object.create(null);
+ }
+ if (!event.context.sessionLocks) {
+ event.context.sessionLocks = Object.create(null);
+ }
+ // Wait for existing session to load
+ if (event.context.sessionLocks[sessionName]) {
+ await event.context.sessionLocks[sessionName];
+ }
+ if (event.context.sessions[sessionName]) {
+ return event.context.sessions[sessionName];
+ }
+ // Prepare an empty session object and store in context
+ const session = {
+ id: "",
+ createdAt: 0,
+ data: Object.create(null),
+ };
+ event.context.sessions[sessionName] = session;
+ // Try to load session
+ let sealedSession;
+ // Try header first
+ if (config.sessionHeader !== false) {
+ const headerName =
+ typeof config.sessionHeader === "string"
+ ? config.sessionHeader.toLowerCase()
+ : `x-${sessionName.toLowerCase()}-session`;
+ const headerValue = event.node.req.headers[headerName];
+ if (typeof headerValue === "string") {
+ sealedSession = headerValue;
+ }
+ }
+ // Fallback to cookies
+ if (!sealedSession) {
+ sealedSession = getCookie(event, sessionName);
+ }
+ if (sealedSession) {
+ // Unseal session data from cookie
+ const lock = unsealSession(event, config, sealedSession)
+ .catch(() => {})
+ .then((unsealed) => {
+ Object.assign(session, unsealed);
+ // make sure deletion occurs before promise resolves
+ delete event.context.sessionLocks[sessionName];
+ });
- event.context.sessionLocks[sessionName] = lock;
- await lock;
- }
- // New session store in response cookies
- if (!session.id) {
- session.id =
- config.generateId?.() ?? (config.crypto || crypto).randomUUID();
- session.createdAt = Date.now();
- await updateSession(event, config);
- }
- return session;
+ event.context.sessionLocks[sessionName] = lock;
+ await lock;
+ }
+ // New session store in response cookies
+ if (!session.id) {
+ session.id =
+ config.generateId?.() ?? (config.crypto || crypto).randomUUID();
+ session.createdAt = Date.now();
+ await updateSession(event, config);
+ }
+ return session;
}
-export async function updateSession(event, config, update) {
- const sessionName = config.name || DEFAULT_NAME;
- // Access current session
- const session = event.context.sessions?.[sessionName] ||
- (await getSession(event, config));
- // Update session data if provided
- if (typeof update === "function") {
- update = update(session.data);
- }
- if (update) {
- Object.assign(session.data, update);
- }
- // Seal and store in cookie
- if (config.cookie !== false) {
- const sealed = await sealSession(event, config);
- setCookie(event, sessionName, sealed, {
- ...DEFAULT_COOKIE,
- expires: config.maxAge
- ? new Date(session.createdAt + config.maxAge * 1000)
- : undefined,
- ...config.cookie,
- });
- }
- return session;
+export async function updateSession(
+ /** @type {import('h3').H3Event} */ event,
+ /** @type {import('h3').SessionConfig} */ config,
+ update,
+) {
+ const sessionName = config.name || DEFAULT_NAME;
+ // Access current session
+ const session =
+ event.context.sessions?.[sessionName] || (await getSession(event, config));
+ // Update session data if provided
+ if (typeof update === "function") {
+ update = update(session.data);
+ }
+ if (update) {
+ Object.assign(session.data, update);
+ }
+ // Seal and store in cookie
+ if (config.cookie !== false) {
+ const sealed = await sealSession(event, config);
+ setCookie(event, sessionName, sealed, {
+ ...DEFAULT_COOKIE,
+ expires: config.maxAge
+ ? new Date(session.createdAt + config.maxAge * 1000)
+ : undefined,
+ ...config.cookie,
+ });
+ }
+ return session;
}
-export async function sealSession(event, config) {
- const sessionName = config.name || DEFAULT_NAME;
- // Access current session
- const session = event.context.sessions?.[sessionName] ||
- (await getSession(event, config));
- const sealed = await seal(config.crypto || crypto, session, config.password, {
- ...sealDefaults,
- ttl: config.maxAge ? config.maxAge * 1000 : 0,
- ...config.seal,
- });
- return sealed;
+export async function sealSession(
+ /** @type {import('h3').H3Event} */ event,
+ /** @type {import('h3').SessionConfig} */ config,
+) {
+ const sessionName = config.name || DEFAULT_NAME;
+ // Access current session
+ const session =
+ event.context.sessions?.[sessionName] || (await getSession(event, config));
+ const sealed = await seal(config.crypto || crypto, session, config.password, {
+ ...sealDefaults,
+ ttl: config.maxAge ? config.maxAge * 1000 : 0,
+ ...config.seal,
+ });
+ return sealed;
}
export {
- H3Error,
- H3Event,
- MIMES,
- appendCorsHeaders,
- appendCorsPreflightHeaders,
- appendHeader,
- appendHeaders,
- appendResponseHeader,
- appendResponseHeaders,
- assertMethod,
- callNodeListener,
- clearResponseHeaders,
- clearSession,
- createApp,
- createAppEventHandler,
- createError,
- createEvent,
- createRouter,
- defaultContentType,
- defineEventHandler,
- defineLazyEventHandler,
- defineNodeListener,
- defineNodeMiddleware,
- defineRequestMiddleware,
- defineResponseMiddleware,
- deleteCookie,
- dynamicEventHandler,
- eventHandler,
- fetchWithEvent,
- fromNodeMiddleware,
- fromPlainHandler,
- fromWebHandler,
- getCookie,
- getHeader,
- getHeaders,
- getMethod,
- getProxyRequestHeaders,
- getQuery,
- getRequestFingerprint,
- getRequestHeader,
- getRequestHeaders,
- getRequestHost,
- getRequestIP,
- getRequestPath,
- getRequestProtocol,
- getRequestURL,
- getRequestWebStream,
- getResponseHeader,
- getResponseHeaders,
- getResponseStatus,
- getResponseStatusText,
- getRouterParam,
- getRouterParams,
- // getSession,
- getValidatedQuery,
- getValidatedRouterParams,
- handleCacheHeaders,
- handleCors,
- isCorsOriginAllowed,
- isError,
- isEvent,
- isEventHandler,
- isMethod,
- isPreflightRequest,
- isStream,
- isWebResponse,
- lazyEventHandler,
- parseCookies,
- promisifyNodeListener,
- proxyRequest,
- readBody,
- readFormData,
- readMultipartFormData,
- readRawBody,
- readValidatedBody,
- removeResponseHeader,
- sanitizeStatusCode,
- sanitizeStatusMessage,
- // sealSession,
- send,
- sendError,
- sendNoContent,
- sendProxy,
- sendRedirect,
- sendStream,
- sendWebResponse,
- serveStatic,
- setCookie,
- setHeader,
- setHeaders,
- setResponseHeader,
- setResponseHeaders,
- setResponseStatus,
- splitCookiesString,
- toEventHandler,
- toNodeListener,
- toPlainHandler,
- toWebHandler,
- unsealSession,
- // updateSession,
- use,
- useBase,
- // useSession,
- writeEarlyHints,
+ H3Error,
+ H3Event,
+ MIMES,
+ appendCorsHeaders,
+ appendCorsPreflightHeaders,
+ appendHeader,
+ appendHeaders,
+ appendResponseHeader,
+ appendResponseHeaders,
+ assertMethod,
+ callNodeListener,
+ clearResponseHeaders,
+ clearSession,
+ createApp,
+ createAppEventHandler,
+ createError,
+ createEvent,
+ createRouter,
+ defaultContentType,
+ defineEventHandler,
+ defineLazyEventHandler,
+ defineNodeListener,
+ defineNodeMiddleware,
+ defineRequestMiddleware,
+ defineResponseMiddleware,
+ deleteCookie,
+ dynamicEventHandler,
+ eventHandler,
+ fetchWithEvent,
+ fromNodeMiddleware,
+ fromPlainHandler,
+ fromWebHandler,
+ getCookie,
+ getHeader,
+ getHeaders,
+ getMethod,
+ getProxyRequestHeaders,
+ getQuery,
+ getRequestFingerprint,
+ getRequestHeader,
+ getRequestHeaders,
+ getRequestHost,
+ getRequestIP,
+ getRequestPath,
+ getRequestProtocol,
+ getRequestURL,
+ getRequestWebStream,
+ getResponseHeader,
+ getResponseHeaders,
+ getResponseStatus,
+ getResponseStatusText,
+ getRouterParam,
+ getRouterParams,
+ // getSession,
+ getValidatedQuery,
+ getValidatedRouterParams,
+ handleCacheHeaders,
+ handleCors,
+ isCorsOriginAllowed,
+ isError,
+ isEvent,
+ isEventHandler,
+ isMethod,
+ isPreflightRequest,
+ isStream,
+ isWebResponse,
+ lazyEventHandler,
+ parseCookies,
+ promisifyNodeListener,
+ proxyRequest,
+ readBody,
+ readFormData,
+ readMultipartFormData,
+ readRawBody,
+ readValidatedBody,
+ removeResponseHeader,
+ sanitizeStatusCode,
+ sanitizeStatusMessage,
+ // sealSession,
+ send,
+ sendError,
+ sendNoContent,
+ sendProxy,
+ sendRedirect,
+ sendStream,
+ sendWebResponse,
+ serveStatic,
+ setCookie,
+ setHeader,
+ setHeaders,
+ setResponseHeader,
+ setResponseHeaders,
+ setResponseStatus,
+ splitCookiesString,
+ toEventHandler,
+ toNodeListener,
+ toPlainHandler,
+ toWebHandler,
+ unsealSession,
+ // updateSession,
+ use,
+ useBase,
+ // useSession,
+ writeEarlyHints,
};