@php-wasm/universal 3.1.1 → 3.1.2
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/index.cjs +6 -6
- package/index.cjs.map +1 -1
- package/index.js +220 -137
- package/index.js.map +1 -1
- package/lib/php-request-handler.d.ts +13 -1
- package/lib/php-response.d.ts +16 -4
- package/lib/php-worker.d.ts +11 -0
- package/package.json +7 -7
package/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var
|
|
1
|
+
var G = (r) => {
|
|
2
2
|
throw TypeError(r);
|
|
3
3
|
};
|
|
4
|
-
var
|
|
5
|
-
var u = (r, e, t) => (
|
|
4
|
+
var W = (r, e, t) => e.has(r) || G("Cannot " + t);
|
|
5
|
+
var u = (r, e, t) => (W(r, e, "read from private field"), t ? t.call(r) : e.get(r)), y = (r, e, t) => e.has(r) ? G("Cannot add the same private member more than once") : e instanceof WeakSet ? e.add(r) : e.set(r, t), g = (r, e, t, s) => (W(r, e, "write to private field"), s ? s.call(r, t) : e.set(r, t), t), m = (r, e, t) => (W(r, e, "access private method"), t);
|
|
6
6
|
import "@php-wasm/node-polyfills";
|
|
7
7
|
import { logger } from "@php-wasm/logger";
|
|
8
8
|
import { dirname, joinPaths, Semaphore, createSpawnHandler, basename, normalizePath, AcquireTimeoutError, splitShellCommand } from "@php-wasm/util";
|
|
@@ -431,6 +431,19 @@ class PHPWorker {
|
|
|
431
431
|
async request(e) {
|
|
432
432
|
return await _private.get(this).requestHandler.request(e);
|
|
433
433
|
}
|
|
434
|
+
/**
|
|
435
|
+
* Handles a request with streaming support for large responses.
|
|
436
|
+
* Returns a StreamedPHPResponse that allows processing the response
|
|
437
|
+
* body incrementally without buffering the entire response in memory.
|
|
438
|
+
*
|
|
439
|
+
* This is useful for large file downloads (>2GB) that would otherwise
|
|
440
|
+
* exceed JavaScript's Uint8Array size limits.
|
|
441
|
+
*
|
|
442
|
+
* @param request - PHP Request data.
|
|
443
|
+
*/
|
|
444
|
+
async requestStreamed(e) {
|
|
445
|
+
return await _private.get(this).requestHandler.requestStreamed(e);
|
|
446
|
+
}
|
|
434
447
|
/** @inheritDoc @php-wasm/universal!/PHP.run */
|
|
435
448
|
async run(e) {
|
|
436
449
|
const { php: t, reap: s } = await this.acquirePHPInstance();
|
|
@@ -623,9 +636,54 @@ const currentJsRuntime = function() {
|
|
|
623
636
|
201: "Created",
|
|
624
637
|
200: "OK"
|
|
625
638
|
};
|
|
626
|
-
|
|
639
|
+
var C;
|
|
640
|
+
const D = class D {
|
|
627
641
|
constructor(e, t, s, n) {
|
|
628
|
-
|
|
642
|
+
/**
|
|
643
|
+
* Response headers stream (internal).
|
|
644
|
+
*/
|
|
645
|
+
y(this, C);
|
|
646
|
+
this.parsedHeaders = null, this.cachedStdoutBytes = null, this.cachedStderrText = null, g(this, C, e), this.stdout = t, this.stderr = s, this.exitCode = n;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Creates a StreamedPHPResponse from a buffered PHPResponse.
|
|
650
|
+
* Useful for unifying response handling when both types may be returned.
|
|
651
|
+
*/
|
|
652
|
+
static fromPHPResponse(e) {
|
|
653
|
+
const t = new ReadableStream({
|
|
654
|
+
start(i) {
|
|
655
|
+
i.enqueue(e.bytes), i.close();
|
|
656
|
+
}
|
|
657
|
+
}), s = () => new ReadableStream({
|
|
658
|
+
start(i) {
|
|
659
|
+
i.close();
|
|
660
|
+
}
|
|
661
|
+
}), n = new D(
|
|
662
|
+
s(),
|
|
663
|
+
t,
|
|
664
|
+
s(),
|
|
665
|
+
Promise.resolve(e.exitCode)
|
|
666
|
+
);
|
|
667
|
+
return n.parsedHeaders = Promise.resolve({
|
|
668
|
+
headers: e.headers,
|
|
669
|
+
httpStatusCode: e.httpStatusCode
|
|
670
|
+
}), n;
|
|
671
|
+
}
|
|
672
|
+
/**
|
|
673
|
+
* Creates a StreamedPHPResponse for a given HTTP status code.
|
|
674
|
+
* Shorthand for `StreamedPHPResponse.fromPHPResponse(PHPResponse.forHttpCode(...))`.
|
|
675
|
+
*/
|
|
676
|
+
static forHttpCode(e, t = "") {
|
|
677
|
+
return D.fromPHPResponse(
|
|
678
|
+
PHPResponse.forHttpCode(e, t)
|
|
679
|
+
);
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Returns the raw headers stream for serialization purposes.
|
|
683
|
+
* For parsed headers, use the `headers` property instead.
|
|
684
|
+
*/
|
|
685
|
+
getHeadersStream() {
|
|
686
|
+
return u(this, C);
|
|
629
687
|
}
|
|
630
688
|
/**
|
|
631
689
|
* True if the response is successful (HTTP status code 200-399),
|
|
@@ -685,9 +743,11 @@ class StreamedPHPResponse {
|
|
|
685
743
|
return this.cachedStderrText || (this.cachedStderrText = streamToText(this.stderr)), this.cachedStderrText;
|
|
686
744
|
}
|
|
687
745
|
async getParsedHeaders() {
|
|
688
|
-
return this.parsedHeaders || (this.parsedHeaders = parseHeadersStream(this
|
|
746
|
+
return this.parsedHeaders || (this.parsedHeaders = parseHeadersStream(u(this, C))), await this.parsedHeaders;
|
|
689
747
|
}
|
|
690
|
-
}
|
|
748
|
+
};
|
|
749
|
+
C = new WeakMap();
|
|
750
|
+
let StreamedPHPResponse = D;
|
|
691
751
|
async function parseHeadersStream(r) {
|
|
692
752
|
const e = await streamToText(r);
|
|
693
753
|
let t;
|
|
@@ -961,7 +1021,7 @@ class PHPExecutionFailureError extends Error {
|
|
|
961
1021
|
}
|
|
962
1022
|
}
|
|
963
1023
|
const PHP_INI_PATH = "/internal/shared/php.ini", AUTO_PREPEND_SCRIPT = "/internal/shared/auto_prepend_file.php", OPCACHE_FILE_FOLDER = "/internal/shared/opcache";
|
|
964
|
-
var M, R, b, S,
|
|
1024
|
+
var M, R, b, S, H, T, w, h, J, Y, X, Q, K, Z, ee, te, j, re, q, z;
|
|
965
1025
|
class PHP {
|
|
966
1026
|
/**
|
|
967
1027
|
* Initializes a PHP runtime.
|
|
@@ -979,8 +1039,8 @@ class PHP {
|
|
|
979
1039
|
// Listen to all events
|
|
980
1040
|
["*", /* @__PURE__ */ new Set()]
|
|
981
1041
|
]));
|
|
982
|
-
y(this,
|
|
983
|
-
y(this,
|
|
1042
|
+
y(this, H, []);
|
|
1043
|
+
y(this, T, {});
|
|
984
1044
|
y(this, w, {
|
|
985
1045
|
enabled: !1,
|
|
986
1046
|
recreateRuntime: () => 0,
|
|
@@ -1058,8 +1118,8 @@ class PHP {
|
|
|
1058
1118
|
* @param listener Callback function to handle the message.
|
|
1059
1119
|
*/
|
|
1060
1120
|
onMessage(r) {
|
|
1061
|
-
return u(this,
|
|
1062
|
-
g(this,
|
|
1121
|
+
return u(this, H).push(r), async () => {
|
|
1122
|
+
g(this, H, u(this, H).filter(
|
|
1063
1123
|
(e) => e !== r
|
|
1064
1124
|
));
|
|
1065
1125
|
};
|
|
@@ -1153,7 +1213,7 @@ class PHP {
|
|
|
1153
1213
|
}
|
|
1154
1214
|
`
|
|
1155
1215
|
), e.onMessage = async (t) => {
|
|
1156
|
-
for (const s of u(this,
|
|
1216
|
+
for (const s of u(this, H)) {
|
|
1157
1217
|
const n = await s(t);
|
|
1158
1218
|
if (n)
|
|
1159
1219
|
return n;
|
|
@@ -1396,7 +1456,7 @@ class PHP {
|
|
|
1396
1456
|
async runStream(r) {
|
|
1397
1457
|
const e = await this.semaphore.acquire();
|
|
1398
1458
|
let t;
|
|
1399
|
-
const s = m(this, h,
|
|
1459
|
+
const s = m(this, h, z).call(this, async () => {
|
|
1400
1460
|
if (u(this, R) || (await this[__private__dont__use].ccall(
|
|
1401
1461
|
"php_wasm_init",
|
|
1402
1462
|
null,
|
|
@@ -1409,22 +1469,22 @@ class PHP {
|
|
|
1409
1469
|
throw new Error(
|
|
1410
1470
|
`The script path "${r.scriptPath}" does not exist.`
|
|
1411
1471
|
);
|
|
1412
|
-
m(this, h,
|
|
1413
|
-
const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, h,
|
|
1414
|
-
if (m(this, h,
|
|
1415
|
-
this.writeFile("/internal/eval.php", r.code), m(this, h,
|
|
1472
|
+
m(this, h, Y).call(this, r.relativeUri || ""), m(this, h, Z).call(this, r.method || "GET");
|
|
1473
|
+
const i = normalizeHeaders(r.headers || {}), o = i.host || "example.com:443", a = m(this, h, K).call(this, o, r.protocol || "http");
|
|
1474
|
+
if (m(this, h, X).call(this, o), m(this, h, Q).call(this, a), m(this, h, ee).call(this, i), r.body && (t = m(this, h, te).call(this, r.body)), typeof r.code == "string")
|
|
1475
|
+
this.writeFile("/internal/eval.php", r.code), m(this, h, j).call(this, "/internal/eval.php");
|
|
1416
1476
|
else if (typeof r.scriptPath == "string")
|
|
1417
|
-
m(this, h,
|
|
1477
|
+
m(this, h, j).call(this, r.scriptPath || "");
|
|
1418
1478
|
else
|
|
1419
1479
|
throw new TypeError(
|
|
1420
1480
|
"The request object must have either a `code` or a `scriptPath` property."
|
|
1421
1481
|
);
|
|
1422
|
-
const c = m(this, h,
|
|
1482
|
+
const c = m(this, h, J).call(this, r.$_SERVER, i, a);
|
|
1423
1483
|
for (const d in c)
|
|
1424
|
-
m(this, h,
|
|
1484
|
+
m(this, h, re).call(this, d, c[d]);
|
|
1425
1485
|
const l = r.env || {};
|
|
1426
1486
|
for (const d in l)
|
|
1427
|
-
m(this, h,
|
|
1487
|
+
m(this, h, q).call(this, d, l[d]);
|
|
1428
1488
|
return await this[__private__dont__use].ccall(
|
|
1429
1489
|
"wasm_sapi_handle_request",
|
|
1430
1490
|
NUMBER,
|
|
@@ -1672,13 +1732,13 @@ class PHP {
|
|
|
1672
1732
|
async hotSwapPHPRuntime(r) {
|
|
1673
1733
|
const e = this[__private__dont__use].FS, t = this.listFiles("/").map((c) => `/${c}`), s = this[__private__dont__use].spawnProcess, n = e.cwd();
|
|
1674
1734
|
e.chdir("/");
|
|
1675
|
-
const i = Object.entries(u(this,
|
|
1735
|
+
const i = Object.entries(u(this, T)).map(
|
|
1676
1736
|
([c, l]) => ({
|
|
1677
1737
|
mountHandler: l.mountHandler,
|
|
1678
1738
|
vfsPath: c
|
|
1679
1739
|
})
|
|
1680
1740
|
), o = Object.values(
|
|
1681
|
-
u(this,
|
|
1741
|
+
u(this, T)
|
|
1682
1742
|
).reverse();
|
|
1683
1743
|
for (const c of o)
|
|
1684
1744
|
await c.unmount();
|
|
@@ -1718,10 +1778,10 @@ class PHP {
|
|
|
1718
1778
|
), s = {
|
|
1719
1779
|
mountHandler: e,
|
|
1720
1780
|
unmount: async () => {
|
|
1721
|
-
await t(), delete u(this,
|
|
1781
|
+
await t(), delete u(this, T)[r];
|
|
1722
1782
|
}
|
|
1723
1783
|
};
|
|
1724
|
-
return u(this,
|
|
1784
|
+
return u(this, T)[r] = s, () => {
|
|
1725
1785
|
s.unmount();
|
|
1726
1786
|
};
|
|
1727
1787
|
}
|
|
@@ -1743,10 +1803,10 @@ class PHP {
|
|
|
1743
1803
|
return this.subProcess(r, e);
|
|
1744
1804
|
u(this, R) && (u(this, w).needsRotating = !0);
|
|
1745
1805
|
const t = await this.semaphore.acquire();
|
|
1746
|
-
return await m(this, h,
|
|
1806
|
+
return await m(this, h, z).call(this, () => {
|
|
1747
1807
|
const s = e.env || {};
|
|
1748
1808
|
for (const [n, i] of Object.entries(s))
|
|
1749
|
-
m(this, h,
|
|
1809
|
+
m(this, h, q).call(this, n, i);
|
|
1750
1810
|
r = [r[0], "-c", PHP_INI_PATH, ...r.slice(1)];
|
|
1751
1811
|
for (const n of r)
|
|
1752
1812
|
this[__private__dont__use].ccall(
|
|
@@ -1837,7 +1897,7 @@ class PHP {
|
|
|
1837
1897
|
this.exit(0);
|
|
1838
1898
|
}
|
|
1839
1899
|
}
|
|
1840
|
-
M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(),
|
|
1900
|
+
M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(), H = new WeakMap(), T = new WeakMap(), w = new WeakMap(), h = new WeakSet(), /**
|
|
1841
1901
|
* Prepares the $_SERVER entries for the PHP runtime.
|
|
1842
1902
|
*
|
|
1843
1903
|
* @param defaults Default entries to include in $_SERVER.
|
|
@@ -1846,7 +1906,7 @@ M = new WeakMap(), R = new WeakMap(), b = new WeakMap(), S = new WeakMap(), T =
|
|
|
1846
1906
|
* was provided.
|
|
1847
1907
|
* @returns Computed $_SERVER entries.
|
|
1848
1908
|
*/
|
|
1849
|
-
|
|
1909
|
+
J = function(r, e, t) {
|
|
1850
1910
|
const s = {
|
|
1851
1911
|
...r || {}
|
|
1852
1912
|
};
|
|
@@ -1856,7 +1916,7 @@ V = function(r, e, t) {
|
|
|
1856
1916
|
["content-type", "content-length"].includes(n.toLowerCase()) && (i = ""), s[`${i}${n.toUpperCase().replace(/-/g, "_")}`] = e[n];
|
|
1857
1917
|
}
|
|
1858
1918
|
return s;
|
|
1859
|
-
},
|
|
1919
|
+
}, Y = function(r) {
|
|
1860
1920
|
this[__private__dont__use].ccall(
|
|
1861
1921
|
"wasm_set_request_uri",
|
|
1862
1922
|
null,
|
|
@@ -1870,35 +1930,35 @@ V = function(r, e, t) {
|
|
|
1870
1930
|
[STRING],
|
|
1871
1931
|
[e]
|
|
1872
1932
|
);
|
|
1873
|
-
},
|
|
1933
|
+
}, X = function(r) {
|
|
1874
1934
|
this[__private__dont__use].ccall(
|
|
1875
1935
|
"wasm_set_request_host",
|
|
1876
1936
|
null,
|
|
1877
1937
|
[STRING],
|
|
1878
1938
|
[r]
|
|
1879
1939
|
);
|
|
1880
|
-
},
|
|
1940
|
+
}, Q = function(r) {
|
|
1881
1941
|
this[__private__dont__use].ccall(
|
|
1882
1942
|
"wasm_set_request_port",
|
|
1883
1943
|
null,
|
|
1884
1944
|
[NUMBER],
|
|
1885
1945
|
[r]
|
|
1886
1946
|
);
|
|
1887
|
-
},
|
|
1947
|
+
}, K = function(r, e) {
|
|
1888
1948
|
let t;
|
|
1889
1949
|
try {
|
|
1890
1950
|
t = parseInt(new URL(r).port, 10);
|
|
1891
1951
|
} catch {
|
|
1892
1952
|
}
|
|
1893
1953
|
return (!t || isNaN(t) || t === 80) && (t = e === "https" ? 443 : 80), t;
|
|
1894
|
-
},
|
|
1954
|
+
}, Z = function(r) {
|
|
1895
1955
|
this[__private__dont__use].ccall(
|
|
1896
1956
|
"wasm_set_request_method",
|
|
1897
1957
|
null,
|
|
1898
1958
|
[STRING],
|
|
1899
1959
|
[r]
|
|
1900
1960
|
);
|
|
1901
|
-
},
|
|
1961
|
+
}, ee = function(r) {
|
|
1902
1962
|
r.cookie && this[__private__dont__use].ccall(
|
|
1903
1963
|
"wasm_set_cookies",
|
|
1904
1964
|
null,
|
|
@@ -1915,7 +1975,7 @@ V = function(r, e, t) {
|
|
|
1915
1975
|
[NUMBER],
|
|
1916
1976
|
[parseInt(r["content-length"], 10)]
|
|
1917
1977
|
);
|
|
1918
|
-
},
|
|
1978
|
+
}, te = function(r) {
|
|
1919
1979
|
let e, t;
|
|
1920
1980
|
typeof r == "string" ? (logger.warn(
|
|
1921
1981
|
"Passing a string as the request body is deprecated. Please use a Uint8Array instead. See https://github.com/WordPress/wordpress-playground/issues/997 for more details"
|
|
@@ -1938,28 +1998,28 @@ V = function(r, e, t) {
|
|
|
1938
1998
|
[NUMBER],
|
|
1939
1999
|
[t]
|
|
1940
2000
|
), s;
|
|
1941
|
-
},
|
|
2001
|
+
}, j = function(r) {
|
|
1942
2002
|
this[__private__dont__use].ccall(
|
|
1943
2003
|
"wasm_set_path_translated",
|
|
1944
2004
|
null,
|
|
1945
2005
|
[STRING],
|
|
1946
2006
|
[r]
|
|
1947
2007
|
);
|
|
1948
|
-
},
|
|
2008
|
+
}, re = function(r, e) {
|
|
1949
2009
|
this[__private__dont__use].ccall(
|
|
1950
2010
|
"wasm_add_SERVER_entry",
|
|
1951
2011
|
null,
|
|
1952
2012
|
[STRING, STRING],
|
|
1953
2013
|
[r, e]
|
|
1954
2014
|
);
|
|
1955
|
-
},
|
|
2015
|
+
}, q = function(r, e) {
|
|
1956
2016
|
this[__private__dont__use].ccall(
|
|
1957
2017
|
"wasm_add_ENV_entry",
|
|
1958
2018
|
null,
|
|
1959
2019
|
[STRING, STRING],
|
|
1960
2020
|
[r, e]
|
|
1961
2021
|
);
|
|
1962
|
-
},
|
|
2022
|
+
}, z = async function(r) {
|
|
1963
2023
|
u(this, w).enabled && u(this, w).needsRotating && await this.rotateRuntime(), ++u(this, w).requestsMade, u(this, w).requestsMade >= u(this, w).maxRequests && (u(this, w).needsRotating = !0);
|
|
1964
2024
|
const e = this[__private__dont__use], t = await createInvertedReadableStream();
|
|
1965
2025
|
e.onHeaders = (p) => {
|
|
@@ -1983,10 +2043,10 @@ V = function(r, e, t) {
|
|
|
1983
2043
|
return await Promise.race([
|
|
1984
2044
|
r(),
|
|
1985
2045
|
new Promise((_, F) => {
|
|
1986
|
-
var
|
|
1987
|
-
c = (
|
|
1988
|
-
isExitCode(
|
|
1989
|
-
}, (
|
|
2046
|
+
var $;
|
|
2047
|
+
c = (V) => {
|
|
2048
|
+
isExitCode(V.error) || F(V.error);
|
|
2049
|
+
}, ($ = u(this, b)) == null || $.addEventListener(
|
|
1990
2050
|
"error",
|
|
1991
2051
|
c,
|
|
1992
2052
|
{ once: !0 }
|
|
@@ -2468,7 +2528,7 @@ const _default = "application/octet-stream", asx = "video/x-ms-asf", atom = "app
|
|
|
2468
2528
|
xspf,
|
|
2469
2529
|
zip
|
|
2470
2530
|
};
|
|
2471
|
-
var v,
|
|
2531
|
+
var v, I, O, L, A, E, N, k, U, P, se, B, ne, ie, oe;
|
|
2472
2532
|
class PHPRequestHandler {
|
|
2473
2533
|
/**
|
|
2474
2534
|
* The request handler needs to decide whether to serve a static asset or
|
|
@@ -2484,14 +2544,14 @@ class PHPRequestHandler {
|
|
|
2484
2544
|
constructor(e) {
|
|
2485
2545
|
y(this, P);
|
|
2486
2546
|
y(this, v);
|
|
2487
|
-
y(this, C);
|
|
2488
|
-
y(this, N);
|
|
2489
|
-
y(this, L);
|
|
2490
2547
|
y(this, I);
|
|
2491
|
-
y(this,
|
|
2548
|
+
y(this, O);
|
|
2549
|
+
y(this, L);
|
|
2492
2550
|
y(this, A);
|
|
2551
|
+
y(this, E);
|
|
2552
|
+
y(this, N);
|
|
2493
2553
|
y(this, k);
|
|
2494
|
-
y(this,
|
|
2554
|
+
y(this, U);
|
|
2495
2555
|
const {
|
|
2496
2556
|
documentRoot: t = "/www/",
|
|
2497
2557
|
absoluteUrl: s = typeof location == "object" ? location.href : DEFAULT_BASE_URL,
|
|
@@ -2522,16 +2582,16 @@ class PHPRequestHandler {
|
|
|
2522
2582
|
);
|
|
2523
2583
|
g(this, k, e.cookieStore === void 0 ? new HttpCookieStore() : e.cookieStore), g(this, v, t);
|
|
2524
2584
|
const c = new URL(s);
|
|
2525
|
-
g(this,
|
|
2585
|
+
g(this, O, c.hostname), g(this, L, c.port ? Number(c.port) : c.protocol === "https:" ? 443 : 80), g(this, I, (c.protocol || "").replace(":", ""));
|
|
2526
2586
|
const l = u(this, L) !== 443 && u(this, L) !== 80;
|
|
2527
|
-
g(this,
|
|
2528
|
-
u(this,
|
|
2587
|
+
g(this, A, [
|
|
2588
|
+
u(this, O),
|
|
2529
2589
|
l ? `:${u(this, L)}` : ""
|
|
2530
|
-
].join("")), g(this, E, c.pathname.replace(/\/+$/, "")), g(this,
|
|
2531
|
-
`${u(this,
|
|
2532
|
-
u(this,
|
|
2590
|
+
].join("")), g(this, E, c.pathname.replace(/\/+$/, "")), g(this, N, [
|
|
2591
|
+
`${u(this, I)}://`,
|
|
2592
|
+
u(this, A),
|
|
2533
2593
|
u(this, E)
|
|
2534
|
-
].join("")), this.rewriteRules = n, g(this,
|
|
2594
|
+
].join("")), this.rewriteRules = n, g(this, U, i), this.getFileNotFoundAction = o;
|
|
2535
2595
|
}
|
|
2536
2596
|
async getPrimaryPhp() {
|
|
2537
2597
|
return await this.instanceManager.getPrimaryPhp();
|
|
@@ -2561,7 +2621,7 @@ class PHPRequestHandler {
|
|
|
2561
2621
|
* The absolute URL of this PHPRequestHandler instance.
|
|
2562
2622
|
*/
|
|
2563
2623
|
get absoluteUrl() {
|
|
2564
|
-
return u(this,
|
|
2624
|
+
return u(this, N);
|
|
2565
2625
|
}
|
|
2566
2626
|
/**
|
|
2567
2627
|
* The directory in the PHP filesystem where the server will look
|
|
@@ -2619,11 +2679,32 @@ class PHPRequestHandler {
|
|
|
2619
2679
|
* @param request - PHP Request data.
|
|
2620
2680
|
*/
|
|
2621
2681
|
async request(e) {
|
|
2682
|
+
const t = await this.requestStreamed(e), s = await PHPResponse.fromStreamedResponse(t);
|
|
2683
|
+
return s.ok() && s.exitCode !== 0 ? new PHPResponse(
|
|
2684
|
+
500,
|
|
2685
|
+
s.headers,
|
|
2686
|
+
s.bytes,
|
|
2687
|
+
s.errors,
|
|
2688
|
+
s.exitCode
|
|
2689
|
+
) : s;
|
|
2690
|
+
}
|
|
2691
|
+
/**
|
|
2692
|
+
* Serves the request with streaming support – returns a StreamedPHPResponse
|
|
2693
|
+
* that allows processing the response body incrementally without buffering
|
|
2694
|
+
* the entire response in memory.
|
|
2695
|
+
*
|
|
2696
|
+
* This is useful for large file downloads (>2GB) that would otherwise
|
|
2697
|
+
* exceed JavaScript's Uint8Array size limits.
|
|
2698
|
+
*
|
|
2699
|
+
* @param request - PHP Request data.
|
|
2700
|
+
* @returns A StreamedPHPResponse.
|
|
2701
|
+
*/
|
|
2702
|
+
async requestStreamed(e) {
|
|
2622
2703
|
const t = looksLikeAbsoluteUrl(e.url), s = new URL(
|
|
2623
2704
|
// Remove the hash part of the URL as it's not meant for the server.
|
|
2624
2705
|
e.url.split("#")[0],
|
|
2625
2706
|
t ? void 0 : DEFAULT_BASE_URL
|
|
2626
|
-
), n = m(this, P,
|
|
2707
|
+
), n = m(this, P, se).call(this, s), i = await this.getPrimaryPhp(), o = removePathPrefix(
|
|
2627
2708
|
/**
|
|
2628
2709
|
* URL.pathname returns a URL-encoded path. We need to decode it
|
|
2629
2710
|
* before using it as a filesystem path.
|
|
@@ -2631,13 +2712,15 @@ class PHPRequestHandler {
|
|
|
2631
2712
|
decodeURIComponent(n.pathname),
|
|
2632
2713
|
u(this, E)
|
|
2633
2714
|
);
|
|
2634
|
-
let a = m(this, P,
|
|
2715
|
+
let a = m(this, P, B).call(this, o);
|
|
2635
2716
|
if (i.isDir(a)) {
|
|
2636
2717
|
if (!o.endsWith("/"))
|
|
2637
|
-
return
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2718
|
+
return StreamedPHPResponse.fromPHPResponse(
|
|
2719
|
+
new PHPResponse(
|
|
2720
|
+
301,
|
|
2721
|
+
{ Location: [`${n.pathname}/`] },
|
|
2722
|
+
new Uint8Array(0)
|
|
2723
|
+
)
|
|
2641
2724
|
);
|
|
2642
2725
|
for (const c of ["index.php", "index.html"]) {
|
|
2643
2726
|
const l = joinPaths(a, c);
|
|
@@ -2654,10 +2737,10 @@ class PHPRequestHandler {
|
|
|
2654
2737
|
let c = o;
|
|
2655
2738
|
for (; c.startsWith("/") && c !== dirname(c); ) {
|
|
2656
2739
|
c = dirname(c);
|
|
2657
|
-
const l = m(this, P,
|
|
2740
|
+
const l = m(this, P, B).call(this, c);
|
|
2658
2741
|
if (i.isFile(l) && // Only run partial path resolution for PHP files.
|
|
2659
2742
|
l.endsWith(".php")) {
|
|
2660
|
-
a = m(this, P,
|
|
2743
|
+
a = m(this, P, B).call(this, c);
|
|
2661
2744
|
break;
|
|
2662
2745
|
}
|
|
2663
2746
|
}
|
|
@@ -2668,32 +2751,23 @@ class PHPRequestHandler {
|
|
|
2668
2751
|
);
|
|
2669
2752
|
switch (c.type) {
|
|
2670
2753
|
case "response":
|
|
2671
|
-
return
|
|
2754
|
+
return StreamedPHPResponse.fromPHPResponse(
|
|
2755
|
+
c.response
|
|
2756
|
+
);
|
|
2672
2757
|
case "internal-redirect":
|
|
2673
2758
|
a = joinPaths(u(this, v), c.uri);
|
|
2674
2759
|
break;
|
|
2675
2760
|
case "404":
|
|
2676
|
-
return
|
|
2761
|
+
return StreamedPHPResponse.forHttpCode(404);
|
|
2677
2762
|
default:
|
|
2678
2763
|
throw new Error(
|
|
2679
2764
|
`Unsupported file-not-found action type: '${c.type}'`
|
|
2680
2765
|
);
|
|
2681
2766
|
}
|
|
2682
2767
|
}
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
return c.ok() && c.exitCode !== 0 ? new PHPResponse(
|
|
2687
|
-
500,
|
|
2688
|
-
c.headers,
|
|
2689
|
-
c.bytes,
|
|
2690
|
-
c.errors,
|
|
2691
|
-
c.exitCode
|
|
2692
|
-
) : c;
|
|
2693
|
-
} else
|
|
2694
|
-
return m(this, P, re).call(this, i, a);
|
|
2695
|
-
else
|
|
2696
|
-
return PHPResponse.forHttpCode(404);
|
|
2768
|
+
return i.isFile(a) ? a.endsWith(".php") ? await m(this, P, ie).call(this, e, s, n, a) : StreamedPHPResponse.fromPHPResponse(
|
|
2769
|
+
m(this, P, ne).call(this, i, a)
|
|
2770
|
+
) : StreamedPHPResponse.forHttpCode(404);
|
|
2697
2771
|
}
|
|
2698
2772
|
/**
|
|
2699
2773
|
* Computes the essential $_SERVER entries for a request.
|
|
@@ -2787,7 +2861,7 @@ class PHPRequestHandler {
|
|
|
2787
2861
|
const n = {
|
|
2788
2862
|
REMOTE_ADDR: "127.0.0.1",
|
|
2789
2863
|
DOCUMENT_ROOT: u(this, v),
|
|
2790
|
-
HTTPS: u(this,
|
|
2864
|
+
HTTPS: u(this, N).startsWith("https://") ? "on" : ""
|
|
2791
2865
|
};
|
|
2792
2866
|
return n.REQUEST_URI = e.pathname + e.search, s.startsWith(u(this, v)) && (n.SCRIPT_NAME = s.substring(
|
|
2793
2867
|
u(this, v).length
|
|
@@ -2802,13 +2876,13 @@ class PHPRequestHandler {
|
|
|
2802
2876
|
await this.instanceManager[Symbol.asyncDispose]();
|
|
2803
2877
|
}
|
|
2804
2878
|
}
|
|
2805
|
-
v = new WeakMap(),
|
|
2879
|
+
v = new WeakMap(), I = new WeakMap(), O = new WeakMap(), L = new WeakMap(), A = new WeakMap(), E = new WeakMap(), N = new WeakMap(), k = new WeakMap(), U = new WeakMap(), P = new WeakSet(), /**
|
|
2806
2880
|
* Apply the rewrite rules to the original request URL.
|
|
2807
2881
|
*
|
|
2808
2882
|
* @param originalRequestUrl - The original request URL.
|
|
2809
2883
|
* @returns The rewritten request URL.
|
|
2810
2884
|
*/
|
|
2811
|
-
|
|
2885
|
+
se = function(e) {
|
|
2812
2886
|
const t = removePathPrefix(
|
|
2813
2887
|
decodeURIComponent(e.pathname),
|
|
2814
2888
|
u(this, E)
|
|
@@ -2831,8 +2905,8 @@ te = function(e) {
|
|
|
2831
2905
|
* @param urlPath - The URL path to resolve (e.g., '/phpmyadmin/index.php')
|
|
2832
2906
|
* @returns The resolved filesystem path
|
|
2833
2907
|
*/
|
|
2834
|
-
|
|
2835
|
-
for (const t of u(this,
|
|
2908
|
+
B = function(e) {
|
|
2909
|
+
for (const t of u(this, U))
|
|
2836
2910
|
if (e === t.urlPrefix || e.startsWith(t.urlPrefix + "/")) {
|
|
2837
2911
|
const s = e.slice(t.urlPrefix.length);
|
|
2838
2912
|
return joinPaths(t.fsPath, s);
|
|
@@ -2844,7 +2918,7 @@ U = function(e) {
|
|
|
2844
2918
|
* @param fsPath - Absolute path of the static file to serve.
|
|
2845
2919
|
* @returns The response.
|
|
2846
2920
|
*/
|
|
2847
|
-
|
|
2921
|
+
ne = function(e, t) {
|
|
2848
2922
|
const s = e.readFileAsBuffer(t);
|
|
2849
2923
|
return new PHPResponse(
|
|
2850
2924
|
200,
|
|
@@ -2859,57 +2933,58 @@ re = function(e, t) {
|
|
|
2859
2933
|
},
|
|
2860
2934
|
s
|
|
2861
2935
|
);
|
|
2862
|
-
},
|
|
2936
|
+
}, ie = async function(e, t, s, n) {
|
|
2863
2937
|
let i;
|
|
2864
2938
|
try {
|
|
2865
2939
|
i = await this.instanceManager.acquirePHPInstance();
|
|
2866
|
-
} catch (
|
|
2867
|
-
return
|
|
2940
|
+
} catch (a) {
|
|
2941
|
+
return a instanceof MaxPhpInstancesError ? StreamedPHPResponse.forHttpCode(502) : StreamedPHPResponse.forHttpCode(500);
|
|
2868
2942
|
}
|
|
2943
|
+
let o;
|
|
2869
2944
|
try {
|
|
2870
|
-
|
|
2871
|
-
}
|
|
2872
|
-
i.reap();
|
|
2873
|
-
}
|
|
2874
|
-
|
|
2945
|
+
o = await m(this, P, oe).call(this, i.php, e, t, s, n);
|
|
2946
|
+
} catch (a) {
|
|
2947
|
+
throw i.reap(), a;
|
|
2948
|
+
}
|
|
2949
|
+
return o.finished.finally(() => {
|
|
2950
|
+
i == null || i.reap();
|
|
2951
|
+
}), o;
|
|
2952
|
+
}, oe = async function(e, t, s, n, i) {
|
|
2875
2953
|
let o = "GET";
|
|
2876
2954
|
const a = {
|
|
2877
|
-
host: u(this,
|
|
2955
|
+
host: u(this, A),
|
|
2878
2956
|
...normalizeHeaders(t.headers || {})
|
|
2879
2957
|
};
|
|
2880
2958
|
u(this, k) && (a.cookie = u(this, k).getCookieRequestHeader());
|
|
2881
2959
|
let c = t.body;
|
|
2882
2960
|
if (typeof c == "object" && !(c instanceof Uint8Array)) {
|
|
2883
2961
|
o = "POST";
|
|
2884
|
-
const { bytes:
|
|
2885
|
-
c =
|
|
2962
|
+
const { bytes: d, contentType: p } = await encodeAsMultipart(c);
|
|
2963
|
+
c = d, a["content-type"] = p;
|
|
2886
2964
|
}
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|
|
2902
|
-
|
|
2965
|
+
const l = await e.runStream({
|
|
2966
|
+
relativeUri: ensurePathPrefix(
|
|
2967
|
+
toRelativeUrl(new URL(n.toString())),
|
|
2968
|
+
u(this, E)
|
|
2969
|
+
),
|
|
2970
|
+
protocol: u(this, I),
|
|
2971
|
+
method: t.method || o,
|
|
2972
|
+
$_SERVER: this.prepare_$_SERVER_superglobal(
|
|
2973
|
+
s,
|
|
2974
|
+
n,
|
|
2975
|
+
i
|
|
2976
|
+
),
|
|
2977
|
+
body: c,
|
|
2978
|
+
scriptPath: i,
|
|
2979
|
+
headers: a
|
|
2980
|
+
});
|
|
2981
|
+
if (u(this, k)) {
|
|
2982
|
+
const d = u(this, k);
|
|
2983
|
+
l.headers.then((p) => {
|
|
2984
|
+
d.rememberCookiesFromResponseHeaders(p);
|
|
2903
2985
|
});
|
|
2904
|
-
return u(this, k) && u(this, k).rememberCookiesFromResponseHeaders(
|
|
2905
|
-
l.headers
|
|
2906
|
-
), l;
|
|
2907
|
-
} catch (l) {
|
|
2908
|
-
const d = l;
|
|
2909
|
-
if (d != null && d.response)
|
|
2910
|
-
return d.response;
|
|
2911
|
-
throw l;
|
|
2912
2986
|
}
|
|
2987
|
+
return l;
|
|
2913
2988
|
};
|
|
2914
2989
|
function inferMimeType(r) {
|
|
2915
2990
|
const e = r.split(".").pop();
|
|
@@ -3792,25 +3867,33 @@ function setupTransferHandlers() {
|
|
|
3792
3867
|
}, transferHandlers.set("StreamedPHPResponse", {
|
|
3793
3868
|
canHandle: (t) => t instanceof StreamedPHPResponse,
|
|
3794
3869
|
serialize(t) {
|
|
3795
|
-
const s = supportsTransferableStreams(), n = promiseToPort(t.exitCode);
|
|
3870
|
+
const s = supportsTransferableStreams(), n = promiseToPort(t.exitCode), i = t.getHeadersStream();
|
|
3796
3871
|
if (s)
|
|
3797
|
-
return [
|
|
3798
|
-
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
|
|
3872
|
+
return [
|
|
3873
|
+
{
|
|
3874
|
+
__type: "StreamedPHPResponse",
|
|
3875
|
+
headers: i,
|
|
3876
|
+
stdout: t.stdout,
|
|
3877
|
+
stderr: t.stderr,
|
|
3878
|
+
exitCodePort: n
|
|
3879
|
+
},
|
|
3880
|
+
[
|
|
3881
|
+
i,
|
|
3882
|
+
t.stdout,
|
|
3883
|
+
t.stderr,
|
|
3884
|
+
n
|
|
3885
|
+
]
|
|
3886
|
+
];
|
|
3887
|
+
const o = streamToPort(i), a = streamToPort(t.stdout), c = streamToPort(t.stderr);
|
|
3805
3888
|
return [
|
|
3806
3889
|
{
|
|
3807
3890
|
__type: "StreamedPHPResponse",
|
|
3808
|
-
headersPort:
|
|
3809
|
-
stdoutPort:
|
|
3810
|
-
stderrPort:
|
|
3891
|
+
headersPort: o,
|
|
3892
|
+
stdoutPort: a,
|
|
3893
|
+
stderrPort: c,
|
|
3811
3894
|
exitCodePort: n
|
|
3812
3895
|
},
|
|
3813
|
-
[
|
|
3896
|
+
[o, a, c, n]
|
|
3814
3897
|
];
|
|
3815
3898
|
},
|
|
3816
3899
|
deserialize(t) {
|