diff --git a/.yarn/cache/@fastify-busboy-npm-2.1.1-455d8b6bf5-42c32ef75e.zip b/.yarn/cache/@fastify-busboy-npm-2.1.1-455d8b6bf5-42c32ef75e.zip new file mode 100644 index 0000000..16026e2 Binary files /dev/null and b/.yarn/cache/@fastify-busboy-npm-2.1.1-455d8b6bf5-42c32ef75e.zip differ diff --git a/.yarn/cache/undici-npm-6.7.0-72b23a7b9b-bc03abd66d.zip b/.yarn/cache/undici-npm-6.7.0-72b23a7b9b-bc03abd66d.zip new file mode 100644 index 0000000..7292e1a Binary files /dev/null and b/.yarn/cache/undici-npm-6.7.0-72b23a7b9b-bc03abd66d.zip differ diff --git a/CHANGELOG.md b/CHANGELOG.md index cc66f68..f092e0b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.0 - Add support for native `fetch` proxying + +- feat: Support `globalThis.fetch` proxying, allowing native fetch requests to be cached/stubbed/etc + ## 0.1.3 - Match paths containing dots, serialize browser config values - fix: match pathnames with dot('.') literals in them diff --git a/package.json b/package.json index ada0402..94a923f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jambox", - "version": "0.1.3", + "version": "0.2.0", "description": "Tool for recording and playing back HTTP requests.", "bin": { "jam": "./jam.mjs", @@ -47,6 +47,7 @@ "svelte-routing": "^1.11.0", "svelte-table": "^0.6.1", "tail-file": "^1.4.15", + "undici": "6.7.0", "wait-on": "^6.0.1", "zen-observable": "^0.9.0" }, diff --git a/recipes/nextjs-graphql-example/.jambox/default.tape.zip b/recipes/nextjs-graphql-example/.jambox/default.tape.zip new file mode 100644 index 0000000..279653a Binary files /dev/null and b/recipes/nextjs-graphql-example/.jambox/default.tape.zip differ diff --git a/recipes/nextjs-graphql-example/.yarn/cache/@next-swc-darwin-arm64-npm-12.3.4-3c587df0e7-8.zip b/recipes/nextjs-graphql-example/.yarn/cache/@next-swc-darwin-arm64-npm-12.3.4-3c587df0e7-8.zip new file mode 100644 index 0000000..bee0acb Binary files /dev/null and b/recipes/nextjs-graphql-example/.yarn/cache/@next-swc-darwin-arm64-npm-12.3.4-3c587df0e7-8.zip differ diff --git a/recipes/nextjs-graphql-example/.yarn/install-state.gz b/recipes/nextjs-graphql-example/.yarn/install-state.gz index dcd5263..44dfb92 100644 Binary files a/recipes/nextjs-graphql-example/.yarn/install-state.gz and b/recipes/nextjs-graphql-example/.yarn/install-state.gz differ diff --git a/recipes/nextjs-graphql-example/pages/_app.js b/recipes/nextjs-graphql-example/pages/_app.js index 39b86cd..a86fad2 100644 --- a/recipes/nextjs-graphql-example/pages/_app.js +++ b/recipes/nextjs-graphql-example/pages/_app.js @@ -1,3 +1,11 @@ export default function App({ Component, pageProps }) { - return ; + return ( + <> + + + + ); } diff --git a/recipes/nextjs-graphql-example/pages/server-render.js b/recipes/nextjs-graphql-example/pages/server-render.js new file mode 100644 index 0000000..2b369c4 --- /dev/null +++ b/recipes/nextjs-graphql-example/pages/server-render.js @@ -0,0 +1,88 @@ +import { useState } from 'react'; + +const query = `query Pokemon($name: String) { + pokemon(name: $name) { + name + image + } +}`; + +export default function ServerRenderPage({data: initialData}) { + const [name, setName] = useState('Pikachu'); + const [data, setData] = useState(initialData); + const [loading, setLoading] = useState(false); + + const handleSearch = (e) => { + e.preventDefault(); + setLoading(true); + fetch('https://graphql-pokemon2.vercel.app', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + query, + variables: { + name, + }, + }), + }) + .then((res) => res.json()) + .then(({ data }) => { + setLoading(false); + setData(data); + }); + }; + + const handleInput = (e) => { + e.preventDefault(); + setName(e.target.value); + }; + + return ( + <> +
+ + +
+
+ {data ? ( + <> +

{data.pokemon.name}

+ {data.pokemon.name} + + ) : loading ? ( +

Loading…

+ ) : ( +

Search for an image

+ )} +
+ + ); +} + + +export async function getServerSideProps() { + const res = await fetch('https://graphql-pokemon2.vercel.app', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + query, + variables: { + name: 'Pikachu', + }, + }), + }); + + const { data } = await res.json(); + console.log(data) + return { + props: { + data, + }, + }; +} diff --git a/src/__mocks__/cache-dir/16068043c24805b3a5ab193fa4a23b8c.json b/src/__mocks__/cache-dir/16068043c24805b3a5ab193fa4a23b8c.json index 08048ee..1e29dfe 100644 --- a/src/__mocks__/cache-dir/16068043c24805b3a5ab193fa4a23b8c.json +++ b/src/__mocks__/cache-dir/16068043c24805b3a5ab193fa4a23b8c.json @@ -1 +1,130 @@ -{"request":{"id":"ebf337e5-ccdf-46be-b629-4651fefa8ad7","matchedRuleId":"2963a70a-837b-4563-bc96-e9049673f097","protocol":"https","httpVersion":"1.1","method":"POST","url":"https://graphql-pokemon2.vercel.app/","path":"/","remoteIpAddress":"::1","remotePort":50448,"headers":{"host":"graphql-pokemon2.vercel.app","connection":"keep-alive","content-length":"125","sec-ch-ua":"\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\"","accept":"application/json","content-type":"application/json","sec-ch-ua-mobile":"?0","user-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36","sec-ch-ua-platform":"\"Linux\"","origin":"https://jambox-demo-graphql.vercel.app","sec-fetch-site":"cross-site","sec-fetch-mode":"cors","sec-fetch-dest":"empty","referer":"https://jambox-demo-graphql.vercel.app/","accept-encoding":"gzip, deflate, br","accept-language":"en-US,en;q=0.9"},"rawHeaders":[["Host","graphql-pokemon2.vercel.app"],["Connection","keep-alive"],["Content-Length","125"],["sec-ch-ua","\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\""],["Accept","application/json"],["Content-Type","application/json"],["sec-ch-ua-mobile","?0"],["User-Agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"],["sec-ch-ua-platform","\"Linux\""],["Origin","https://jambox-demo-graphql.vercel.app"],["Sec-Fetch-Site","cross-site"],["Sec-Fetch-Mode","cors"],["Sec-Fetch-Dest","empty"],["Referer","https://jambox-demo-graphql.vercel.app/"],["Accept-Encoding","gzip, deflate, br"],["Accept-Language","en-US,en;q=0.9"]],"tags":[],"timingEvents":{"startTime":1673212233255,"startTimestamp":2040117.9996999986,"bodyReceivedTimestamp":2040118.9439219981},"body":{"buffer":{"type":"Buffer","data":[123,34,113,117,101,114,121,34,58,34,113,117,101,114,121,32,80,111,107,101,109,111,110,40,36,110,97,109,101,58,32,83,116,114,105,110,103,41,32,123,92,110,32,112,111,107,101,109,111,110,40,110,97,109,101,58,32,36,110,97,109,101,41,32,123,92,110,32,32,32,110,97,109,101,92,110,32,32,32,105,109,97,103,101,92,110,32,125,92,110,125,34,44,34,118,97,114,105,97,98,108,101,115,34,58,123,34,110,97,109,101,34,58,34,83,108,111,119,112,111,107,101,34,125,125]}}},"response":{"id":"ebf337e5-ccdf-46be-b629-4651fefa8ad7","statusCode":200,"timingEvents":{"startTime":1673212233255,"startTimestamp":2040117.9996999986,"bodyReceivedTimestamp":2040118.9439219981,"headersSentTimestamp":2040368.6721789986,"responseSentTimestamp":2040372.3621459976},"tags":[],"statusMessage":"OK","headers":{"access-control-allow-methods":"GET,HEAD,PUT,POST,DELETE","access-control-allow-origin":"https://jambox-demo-graphql.vercel.app","cache-control":"public, max-age=0, must-revalidate","connection":"keep-alive","content-length":"97","content-type":"application/json; charset=utf-8","date":"Sun, 08 Jan 2023 21:10:33 GMT","server":"Vercel","strict-transport-security":"max-age=63072000; includeSubDomains; preload","x-vercel-cache":"MISS","x-vercel-id":"iad1::sfo1::qnkr7-1673212233783-e24fced79c98"},"rawHeaders":[["Access-Control-Allow-Methods","GET,HEAD,PUT,POST,DELETE"],["Access-Control-Allow-Origin","https://jambox-demo-graphql.vercel.app"],["Cache-Control","public, max-age=0, must-revalidate"],["Connection","keep-alive"],["Content-Length","97"],["Content-Type","application/json; charset=utf-8"],["Date","Sun, 08 Jan 2023 21:10:33 GMT"],["Server","Vercel"],["Strict-Transport-Security","max-age=63072000; includeSubDomains; preload"],["X-Vercel-Cache","MISS"],["X-Vercel-Id","iad1::sfo1::qnkr7-1673212233783-e24fced79c98"]],"body":{"buffer":{"type":"Buffer","data":[123,34,100,97,116,97,34,58,123,34,112,111,107,101,109,111,110,34,58,123,34,110,97,109,101,34,58,34,83,108,111,119,112,111,107,101,34,44,34,105,109,97,103,101,34,58,34,104,116,116,112,115,58,47,47,105,109,103,46,112,111,107,101,109,111,110,100,98,46,110,101,116,47,97,114,116,119,111,114,107,47,115,108,111,119,112,111,107,101,46,106,112,103,34,125,125,125]}}}} \ No newline at end of file +{ + "request": { + "id": "ebf337e5-ccdf-46be-b629-4651fefa8ad7", + "matchedRuleId": "2963a70a-837b-4563-bc96-e9049673f097", + "protocol": "https", + "httpVersion": "1.1", + "method": "POST", + "url": "https://graphql-pokemon2.vercel.app/", + "path": "/", + "remoteIpAddress": "::1", + "remotePort": 50448, + "headers": { + "host": "graphql-pokemon2.vercel.app", + "connection": "keep-alive", + "content-length": "125", + "sec-ch-ua": "\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\"", + "accept": "application/json", + "content-type": "application/json", + "sec-ch-ua-mobile": "?0", + "user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36", + "sec-ch-ua-platform": "\"Linux\"", + "origin": "https://jambox-demo-graphql.vercel.app", + "sec-fetch-site": "cross-site", + "sec-fetch-mode": "cors", + "sec-fetch-dest": "empty", + "referer": "https://jambox-demo-graphql.vercel.app/", + "accept-encoding": "gzip, deflate, br", + "accept-language": "en-US,en;q=0.9" + }, + "rawHeaders": [ + ["Host", "graphql-pokemon2.vercel.app"], + ["Connection", "keep-alive"], + ["Content-Length", "125"], + ["sec-ch-ua", "\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\""], + ["Accept", "application/json"], + ["Content-Type", "application/json"], + ["sec-ch-ua-mobile", "?0"], + [ + "User-Agent", + "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" + ], + ["sec-ch-ua-platform", "\"Linux\""], + ["Origin", "https://jambox-demo-graphql.vercel.app"], + ["Sec-Fetch-Site", "cross-site"], + ["Sec-Fetch-Mode", "cors"], + ["Sec-Fetch-Dest", "empty"], + ["Referer", "https://jambox-demo-graphql.vercel.app/"], + ["Accept-Encoding", "gzip, deflate, br"], + ["Accept-Language", "en-US,en;q=0.9"] + ], + "tags": [], + "timingEvents": { + "startTime": 1673212233255, + "startTimestamp": 2040117.9996999986, + "bodyReceivedTimestamp": 2040118.9439219981 + }, + "body": { + "buffer": { + "type": "Buffer", + "data": [ + 123, 34, 113, 117, 101, 114, 121, 34, 58, 34, 113, 117, 101, 114, 121, + 32, 80, 111, 107, 101, 109, 111, 110, 40, 36, 110, 97, 109, 101, 58, + 32, 83, 116, 114, 105, 110, 103, 41, 32, 123, 92, 110, 32, 112, 111, + 107, 101, 109, 111, 110, 40, 110, 97, 109, 101, 58, 32, 36, 110, 97, + 109, 101, 41, 32, 123, 92, 110, 32, 32, 32, 110, 97, 109, 101, 92, + 110, 32, 32, 32, 105, 109, 97, 103, 101, 92, 110, 32, 125, 92, 110, + 125, 34, 44, 34, 118, 97, 114, 105, 97, 98, 108, 101, 115, 34, 58, + 123, 34, 110, 97, 109, 101, 34, 58, 34, 83, 108, 111, 119, 112, 111, + 107, 101, 34, 125, 125 + ] + } + } + }, + "response": { + "id": "ebf337e5-ccdf-46be-b629-4651fefa8ad7", + "statusCode": 200, + "timingEvents": { + "startTime": 1673212233255, + "startTimestamp": 2040117.9996999986, + "bodyReceivedTimestamp": 2040118.9439219981, + "headersSentTimestamp": 2040368.6721789986, + "responseSentTimestamp": 2040372.3621459976 + }, + "tags": [], + "statusMessage": "OK", + "headers": { + "access-control-allow-methods": "GET,HEAD,PUT,POST,DELETE", + "access-control-allow-origin": "https://jambox-demo-graphql.vercel.app", + "cache-control": "public, max-age=0, must-revalidate", + "connection": "keep-alive", + "content-length": "97", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 08 Jan 2023 21:10:33 GMT", + "server": "Vercel", + "strict-transport-security": "max-age=63072000; includeSubDomains; preload", + "x-vercel-cache": "MISS", + "x-vercel-id": "iad1::sfo1::qnkr7-1673212233783-e24fced79c98" + }, + "rawHeaders": [ + ["Access-Control-Allow-Methods", "GET,HEAD,PUT,POST,DELETE"], + ["Access-Control-Allow-Origin", "https://jambox-demo-graphql.vercel.app"], + ["Cache-Control", "public, max-age=0, must-revalidate"], + ["Connection", "keep-alive"], + ["Content-Length", "97"], + ["Content-Type", "application/json; charset=utf-8"], + ["Date", "Sun, 08 Jan 2023 21:10:33 GMT"], + ["Server", "Vercel"], + [ + "Strict-Transport-Security", + "max-age=63072000; includeSubDomains; preload" + ], + ["X-Vercel-Cache", "MISS"], + ["X-Vercel-Id", "iad1::sfo1::qnkr7-1673212233783-e24fced79c98"] + ], + "body": { + "buffer": { + "type": "Buffer", + "data": [ + 123, 34, 100, 97, 116, 97, 34, 58, 123, 34, 112, 111, 107, 101, 109, + 111, 110, 34, 58, 123, 34, 110, 97, 109, 101, 34, 58, 34, 83, 108, + 111, 119, 112, 111, 107, 101, 34, 44, 34, 105, 109, 97, 103, 101, 34, + 58, 34, 104, 116, 116, 112, 115, 58, 47, 47, 105, 109, 103, 46, 112, + 111, 107, 101, 109, 111, 110, 100, 98, 46, 110, 101, 116, 47, 97, 114, + 116, 119, 111, 114, 107, 47, 115, 108, 111, 119, 112, 111, 107, 101, + 46, 106, 112, 103, 34, 125, 125, 125 + ] + } + } + } +} diff --git a/src/script-helper.js b/src/script-helper.js index 6ce95f5..3a2fd4e 100644 --- a/src/script-helper.js +++ b/src/script-helper.js @@ -1,2 +1,12 @@ +const undici = require('undici'); const globalAgent = require('global-agent'); + globalAgent.bootstrap(); + +// Configure "native" `fetch` (e.g. `globalThis.fetch` in Node.js) +// to work with the `global-agent` proxy +// @see: https://github.com/gajus/global-agent/issues/52#issuecomment-1134525621 +const ProxyAgent = undici.ProxyAgent; +const setGlobalDispatcher = undici.setGlobalDispatcher; + +setGlobalDispatcher(new ProxyAgent(process.env.GLOBAL_AGENT_HTTP_PROXY)); diff --git a/yarn.lock b/yarn.lock index 041b72f..97a5e0b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1421,6 +1421,13 @@ __metadata: languageName: node linkType: hard +"@fastify/busboy@npm:^2.0.0": + version: 2.1.1 + resolution: "@fastify/busboy@npm:2.1.1" + checksum: 42c32ef75e906c9a4809c1e1930a5ca6d4ddc8d138e1a8c8ba5ea07f997db32210617d23b2e4a85fe376316a41a1a0439fc6ff2dedf5126d96f45a9d80754fb2 + languageName: node + linkType: hard + "@floating-ui/core@npm:^1.1.0, @floating-ui/core@npm:^1.3.1": version: 1.3.1 resolution: "@floating-ui/core@npm:1.3.1" @@ -6145,6 +6152,7 @@ __metadata: svelte-watch-resize: ^1.0.3 tail-file: ^1.4.15 typescript: ^5.1.3 + undici: 6.7.0 wait-on: ^6.0.1 webextension-polyfill: ^0.10.0 webpack: ^5.74.0 @@ -9745,6 +9753,15 @@ __metadata: languageName: node linkType: hard +"undici@npm:6.7.0": + version: 6.7.0 + resolution: "undici@npm:6.7.0" + dependencies: + "@fastify/busboy": ^2.0.0 + checksum: bc03abd66d2a5db49e46e80453cf32793933db4a56aea5cd5957614e15762a83ef8a00fc54058c8c5fa9c4f4777060b67f37cc98860f49f95f191075cf076d0b + languageName: node + linkType: hard + "unicode-canonical-property-names-ecmascript@npm:^2.0.0": version: 2.0.0 resolution: "unicode-canonical-property-names-ecmascript@npm:2.0.0"