Skip to content

Commit c4e2e75

Browse files
committed
feat: US-178 - Add axios project-matrix fixture
1 parent 38aa577 commit c4e2e75

6 files changed

Lines changed: 92 additions & 3 deletions

File tree

docs/nodejs-compatibility.mdx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ The [project-matrix test suite](https://github.com/rivet-dev/secure-exec/tree/ma
7070
| [vite](https://npmjs.com/package/vite) | Build Tool | ESM, HMR server, plugin system |
7171
| [astro](https://npmjs.com/package/astro) | Web Framework | Island architecture, SSR, multi-framework |
7272
| [hono](https://npmjs.com/package/hono) | Web Framework | ESM imports, lightweight HTTP |
73+
| [axios](https://npmjs.com/package/axios) | HTTP Client | HTTP client requests via fetch adapter, JSON APIs |
7374
| [dotenv](https://npmjs.com/package/dotenv) | Configuration | Environment variable loading, fs reads |
7475
| [semver](https://npmjs.com/package/semver) | Utility | Version parsing and comparison |
7576
| [ssh2](https://npmjs.com/package/ssh2) | Networking | SSH client/server, crypto, streams, events |

packages/secure-exec-core/src/bridge/network.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,33 @@ interface FetchResponse {
6969
}
7070

7171
// Fetch polyfill
72-
export async function fetch(url: string | URL, options: FetchOptions = {}): Promise<FetchResponse> {
72+
export async function fetch(input: string | URL | Request, options: FetchOptions = {}): Promise<FetchResponse> {
7373
if (typeof _networkFetchRaw === 'undefined') {
7474
console.error('fetch requires NetworkAdapter to be configured');
7575
throw new Error('fetch requires NetworkAdapter to be configured');
7676
}
7777

78+
// Extract URL and options from Request object (used by axios fetch adapter)
79+
let resolvedUrl: string;
80+
if (input instanceof Request) {
81+
resolvedUrl = input.url;
82+
options = {
83+
method: input.method,
84+
headers: Object.fromEntries(input.headers.entries()),
85+
body: input.body,
86+
...options,
87+
};
88+
} else {
89+
resolvedUrl = String(input);
90+
}
91+
7892
const optionsJson = JSON.stringify({
7993
method: options.method || "GET",
8094
headers: options.headers || {},
8195
body: options.body || null,
8296
});
8397

84-
const responseJson = await _networkFetchRaw.apply(undefined, [String(url), optionsJson], {
98+
const responseJson = await _networkFetchRaw.apply(undefined, [resolvedUrl, optionsJson], {
8599
result: { promise: true },
86100
});
87101
const response = JSON.parse(responseJson) as {
@@ -100,7 +114,7 @@ export async function fetch(url: string | URL, options: FetchOptions = {}): Prom
100114
status: response.status,
101115
statusText: response.statusText,
102116
headers: new Map(Object.entries(response.headers || {})),
103-
url: response.url || String(url),
117+
url: response.url || resolvedUrl,
104118
redirected: response.redirected || false,
105119
type: "basic",
106120

packages/secure-exec-core/src/bridge/process.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,14 @@ process.off = process.removeListener;
929929
return 50 * 1024 * 1024;
930930
};
931931

932+
// Match Node.js Object.prototype.toString.call(process) === '[object process]'
933+
Object.defineProperty(process, Symbol.toStringTag, {
934+
value: "process",
935+
writable: false,
936+
configurable: true,
937+
enumerable: false,
938+
});
939+
932940
export default process as unknown as typeof nodeProcess;
933941

934942
// ============================================================================
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"entry": "src/index.js",
3+
"expectation": "pass"
4+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"name": "project-matrix-axios-pass",
3+
"private": true,
4+
"type": "commonjs",
5+
"dependencies": {
6+
"axios": "1.7.9"
7+
}
8+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
"use strict";
2+
3+
const http = require("http");
4+
const axios = require("axios");
5+
6+
const client = axios.create({ adapter: "fetch" });
7+
8+
const server = http.createServer((req, res) => {
9+
if (req.method === "GET" && req.url === "/hello") {
10+
res.writeHead(200, { "Content-Type": "application/json" });
11+
res.end(JSON.stringify({ message: "hello" }));
12+
} else if (req.method === "GET" && req.url === "/users/42") {
13+
res.writeHead(200, { "Content-Type": "application/json" });
14+
res.end(JSON.stringify({ id: "42", name: "test-user" }));
15+
} else if (req.method === "POST" && req.url === "/data") {
16+
let body = "";
17+
req.on("data", (chunk) => (body += chunk));
18+
req.on("end", () => {
19+
res.writeHead(200, { "Content-Type": "application/json" });
20+
res.end(JSON.stringify({ method: "POST", received: JSON.parse(body) }));
21+
});
22+
} else {
23+
res.writeHead(404);
24+
res.end();
25+
}
26+
});
27+
28+
async function main() {
29+
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
30+
const port = server.address().port;
31+
const base = "http://127.0.0.1:" + port;
32+
33+
try {
34+
const results = [];
35+
36+
const r1 = await client.get(base + "/hello");
37+
results.push({ route: "GET /hello", status: r1.status, body: r1.data });
38+
39+
const r2 = await client.get(base + "/users/42");
40+
results.push({ route: "GET /users/42", status: r2.status, body: r2.data });
41+
42+
const r3 = await client.post(base + "/data", { key: "value" });
43+
results.push({ route: "POST /data", status: r3.status, body: r3.data });
44+
45+
console.log(JSON.stringify(results));
46+
} finally {
47+
await new Promise((resolve) => server.close(resolve));
48+
}
49+
}
50+
51+
main().catch((err) => {
52+
console.error(err.message);
53+
process.exit(1);
54+
});

0 commit comments

Comments
 (0)