From f3ec1f308d4e9335dc1e4dfed2a36dc1d07c38e8 Mon Sep 17 00:00:00 2001 From: Jeremy Danyow Date: Sun, 16 Dec 2018 08:49:43 -0800 Subject: [PATCH 1/3] feat(Worker): add cf-* headers to request --- app/__tests__/server_spec.js | 20 ++++++++++++++++++++ app/__tests__/worker_spec.js | 15 ++++++++------- app/server.js | 26 ++++++++++++++++++++------ app/worker.js | 5 +++-- 4 files changed, 51 insertions(+), 15 deletions(-) diff --git a/app/__tests__/server_spec.js b/app/__tests__/server_spec.js index c3f9da5..b54fea0 100644 --- a/app/__tests__/server_spec.js +++ b/app/__tests__/server_spec.js @@ -50,4 +50,24 @@ describe("server", () => { .expect(200, "goodbye") .then(() => done()); }); + + it('Builds request', done => { + const app = createApp( + `addEventListener('fetch', e => e.respondWith(new Response('hello', { + status: 201, + headers: e.request.headers } // echo request headers + )))` + ); + + supertest(app) + .get("/some-route") + .expect(201, "hello") + .expect('cf-connecting-ip', /^\d+\.\d+\.\d+\.\d+$/) + .expect('cf-ipcountry', 'XX') + .expect('cf-ray', '0000000000000000') + .expect('cf-visitor', '{"scheme":"http"}') + .expect('x-forwarded-proto', 'http') + .expect('x-real-ip', /^\d+\.\d+\.\d+\.\d+$/) + .then(() => done()); + }); }); diff --git a/app/__tests__/worker_spec.js b/app/__tests__/worker_spec.js index 95810c0..bcd9027 100644 --- a/app/__tests__/worker_spec.js +++ b/app/__tests__/worker_spec.js @@ -1,4 +1,5 @@ const express = require("express"); +const { Request } = require("node-fetch"); const { Worker } = require("../worker"); const { InMemoryKVStore } = require("../in-memory-kv-store"); @@ -94,7 +95,7 @@ describe("Workers", () => { test("It can stub out responses", async () => { const worker = new Worker("foo.com", 'addEventListener("fetch", (e) => e.respondWith(new Response("hello")))'); - const response = await worker.executeFetchEvent("http://foo.com"); + const response = await worker.executeFetchEvent(new Request("http://foo.com")); expect(response.status).toBe(200); expect(await response.text()).toBe("hello"); }); @@ -118,7 +119,7 @@ describe("Workers", () => { test("It Fetches Correctly", async done => { const worker = new Worker(upstreamHost, "", { upstreamHost: upstreamHost }); - const response = await worker.executeFetchEvent(`http://${upstreamHost}/success`); + const response = await worker.executeFetchEvent(new Request(`http://${upstreamHost}/success`)); expect(response.status).toBe(200); expect(await response.text()).toBe("OK"); done(); @@ -126,7 +127,7 @@ describe("Workers", () => { test("It does not follow redirects", async done => { const worker = new Worker(upstreamHost, "", { upstreamHost: upstreamHost }); - const response = await worker.executeFetchEvent(`http://${upstreamHost}/redirect`); + const response = await worker.executeFetchEvent(new Request(`http://${upstreamHost}/redirect`)); expect(response.status).toBe(301); expect(response.headers.get("Location")).toBe("https://www.google.com/"); done(); @@ -134,7 +135,7 @@ describe("Workers", () => { test("The worker forwards the request upstream", async done => { const worker = new Worker("foo.com", "", { upstreamHost: upstreamHost }); - const response = await worker.executeFetchEvent(`http://foo.com/success`); + const response = await worker.executeFetchEvent(new Request(`http://foo.com/success`)); expect(response.status).toBe(200); expect(await response.text()).toBe("OK"); done(); @@ -142,7 +143,7 @@ describe("Workers", () => { test("The worker does not keeps the host the same", async done => { const worker = new Worker("foo.com", "", { upstreamHost: upstreamHost }); - const response = await worker.executeFetchEvent(`http://foo.com/host`); + const response = await worker.executeFetchEvent(new Request(`http://foo.com/host`)); expect(response.status).toBe(200); expect(await response.text()).toBe("foo.com"); done(); @@ -154,7 +155,7 @@ describe("Workers", () => { `addEventListener("fetch", (e) => e.respondWith(fetch("http://${upstreamHost}/host")))`, { upstreamHost: null } ); - const response = await worker.executeFetchEvent(`http://foo.com/host`); + const response = await worker.executeFetchEvent(new Request(`http://foo.com/host`)); expect(response.status).toBe(200); expect(await response.text()).toBe(upstreamHost); done(); @@ -168,7 +169,7 @@ describe("Workers", () => { { kvStores: ["MYSTORE"], kvStoreFactory: kvStoreFactory } ); - const response = await worker.executeFetchEvent(`http://foo.com/blah`); + const response = await worker.executeFetchEvent(new Request(`http://foo.com/blah`)); expect(response.status).toBe(200); expect(await response.text()).toBe("foo"); expect(await kvStoreFactory.getClient("MYSTORE").get("foo")).toBe("bar"); diff --git a/app/server.js b/app/server.js index 6289677..3cc68fb 100644 --- a/app/server.js +++ b/app/server.js @@ -1,16 +1,30 @@ const express = require("express"); +const { Request } = require("node-fetch"); const bodyParser = require("body-parser"); const { Worker } = require("./worker"); const { InMemoryKVStore } = require("./in-memory-kv-store"); -async function callWorker(worker, req, res) { - const url = req.protocol + "://" + req.get("host") + req.originalUrl; - - const response = await worker.executeFetchEvent(url, { - headers: req.headers, +function buildRequest(req) { + const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`; + const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress.split(':').pop(); + return new Request(url, { + headers: { + ...req.headers, + 'cf-connecting-ip': ip, + 'cf-ipcountry': 'XX', + 'cf-ray': '0000000000000000', + 'cf-visitor': JSON.stringify({ scheme: req.protocol }), + 'x-forwarded-proto': req.protocol, + 'x-real-ip': ip + }, method: req.method, - body: ["GET", "HEAD"].includes(req.method) ? undefined : req.body + body: ['GET', 'HEAD'].includes(req.method) ? undefined : req.body }); +} + +async function callWorker(worker, req, res) { + const request = buildRequest(req); + const response = await worker.executeFetchEvent(request); const data = await response.arrayBuffer(); res.status(response.status); diff --git a/app/worker.js b/app/worker.js index 97253b9..9690e9d 100644 --- a/app/worker.js +++ b/app/worker.js @@ -59,12 +59,13 @@ class Worker { return fetch(request); } - async executeFetchEvent(url, opts) { + async executeFetchEvent(request) { + request = new Request(request, { redirect: 'manual' }); let response = null; let waitUntil = []; this.triggerEvent("fetch", { type: "fetch", - request: new Request(url, { redirect: "manual", ...opts }), + request, respondWith: r => (response = r), waitUntil: e => waitUntil.push(e) }); From cb34976491c481f9d4cf76a77051542b76623b29 Mon Sep 17 00:00:00 2001 From: Jeremy Danyow Date: Sun, 16 Dec 2018 09:06:57 -0800 Subject: [PATCH 2/3] simplify diff --- app/worker.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/worker.js b/app/worker.js index 9690e9d..b14e729 100644 --- a/app/worker.js +++ b/app/worker.js @@ -60,12 +60,11 @@ class Worker { } async executeFetchEvent(request) { - request = new Request(request, { redirect: 'manual' }); let response = null; let waitUntil = []; this.triggerEvent("fetch", { type: "fetch", - request, + request: new Request(request, { redirect: 'manual' }), respondWith: r => (response = r), waitUntil: e => waitUntil.push(e) }); From 0d0269eae7b584c33649a9aff59591ea1037b30c Mon Sep 17 00:00:00 2001 From: Jeremy Danyow Date: Sun, 16 Dec 2018 09:09:45 -0800 Subject: [PATCH 3/3] rename test --- app/__tests__/server_spec.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/__tests__/server_spec.js b/app/__tests__/server_spec.js index b54fea0..a1e5237 100644 --- a/app/__tests__/server_spec.js +++ b/app/__tests__/server_spec.js @@ -51,12 +51,12 @@ describe("server", () => { .then(() => done()); }); - it('Builds request', done => { + it('Builds request with cf-* headers', done => { const app = createApp( `addEventListener('fetch', e => e.respondWith(new Response('hello', { status: 201, - headers: e.request.headers } // echo request headers - )))` + headers: e.request.headers // echo request headers + })))` ); supertest(app)