From 949689abbd537fea53b388e5efd62fa95d03dbec Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Tue, 15 Nov 2022 20:14:07 -0500 Subject: [PATCH 1/8] fix: add longitude, latitude to RequestData.geo --- cypress/integration/middleware/enhanced.spec.ts | 12 ++++++++++++ demos/middleware/middleware.ts | 10 ++++++++++ demos/middleware/pages/api/geo.js | 3 +++ packages/runtime/src/templates/edge/runtime.ts | 4 +++- 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 demos/middleware/pages/api/geo.js diff --git a/cypress/integration/middleware/enhanced.spec.ts b/cypress/integration/middleware/enhanced.spec.ts index e7541bca91..4296d7843c 100644 --- a/cypress/integration/middleware/enhanced.spec.ts +++ b/cypress/integration/middleware/enhanced.spec.ts @@ -1,3 +1,4 @@ +import { NextRequest } from 'next/server' describe('Enhanced middleware', () => { it('adds request headers', () => { cy.request('/api/hello').then((response) => { @@ -25,4 +26,15 @@ describe('Enhanced middleware', () => { .that.includes('This was static but has been transformed in') }) }) + + it('adds geo data', () => { + cy.request('/api/geo-test').then((response) => { + expect(response.body).to.have.nested.property('headers.x-geo-country') + expect(response.body).to.have.nested.property('headers.x-geo-region') + expect(response.body).to.have.nested.property('headers.x-geo-city') + expect(response.body).to.have.nested.property('headers.x-geo-longitude') + expect(response.body).to.have.nested.property('headers.x-geo-latitude') + expect(response.body).to.have.nested.property('headers.x-geo-timezone') + }) + }) }) diff --git a/demos/middleware/middleware.ts b/demos/middleware/middleware.ts index 8af64d3157..683783b291 100644 --- a/demos/middleware/middleware.ts +++ b/demos/middleware/middleware.ts @@ -29,6 +29,16 @@ export async function middleware(req: NextRequest) { return request.next() } + if (pathname.startsWith('/api/geo')) { + req.headers.set('x-geo-country', req.geo.country) + req.headers.set('x-geo-region', req.geo.region) + req.headers.set('x-geo-city', req.geo.city) + req.headers.set('x-geo-longitude', req.geo.longitude) + req.headers.set('x-geo-latitude', req.geo.latitude) + + return request.next() + } + if (pathname.startsWith('/headers')) { // Add a header to the rewritten request req.headers.set('x-hello', 'world') diff --git a/demos/middleware/pages/api/geo.js b/demos/middleware/pages/api/geo.js new file mode 100644 index 0000000000..84acde12b3 --- /dev/null +++ b/demos/middleware/pages/api/geo.js @@ -0,0 +1,3 @@ +export default function handler(req, res) { + res.status(200).json({ name: 'geo-test', headers: req.headers }) +} diff --git a/packages/runtime/src/templates/edge/runtime.ts b/packages/runtime/src/templates/edge/runtime.ts index a636320f21..2023307bfb 100644 --- a/packages/runtime/src/templates/edge/runtime.ts +++ b/packages/runtime/src/templates/edge/runtime.ts @@ -63,10 +63,12 @@ const handler = async (req: Request, context: Context) => { return } - const geo = { + const geo: RequestData['geo'] = { country: context.geo.country?.code, region: context.geo.subdivision?.code, city: context.geo.city, + latitude: context.geo.latitude?.toString(), + longitude: context.geo.longitude?.toString(), } const requestId = req.headers.get('x-nf-request-id') From ac259b4f7924a1b2706cb56c8b13f2860090a73f Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Tue, 15 Nov 2022 20:16:53 -0500 Subject: [PATCH 2/8] chore: removed setting a header for timezone as Next.js doesn't provide this --- cypress/integration/middleware/enhanced.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/integration/middleware/enhanced.spec.ts b/cypress/integration/middleware/enhanced.spec.ts index 4296d7843c..11467a44bd 100644 --- a/cypress/integration/middleware/enhanced.spec.ts +++ b/cypress/integration/middleware/enhanced.spec.ts @@ -34,7 +34,6 @@ describe('Enhanced middleware', () => { expect(response.body).to.have.nested.property('headers.x-geo-city') expect(response.body).to.have.nested.property('headers.x-geo-longitude') expect(response.body).to.have.nested.property('headers.x-geo-latitude') - expect(response.body).to.have.nested.property('headers.x-geo-timezone') }) }) }) From aa59d0342870de4c94b71b38e957e4b2f023614a Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Thu, 17 Nov 2022 17:04:50 -0500 Subject: [PATCH 3/8] chore: added timezone to geo data --- cypress/integration/middleware/enhanced.spec.ts | 1 + demos/middleware/middleware.ts | 1 + packages/next/src/middleware/request.ts | 15 ++++++++++++++- packages/runtime/src/templates/edge/next-dev.js | 5 ++++- packages/runtime/src/templates/edge/runtime.ts | 2 ++ 5 files changed, 22 insertions(+), 2 deletions(-) diff --git a/cypress/integration/middleware/enhanced.spec.ts b/cypress/integration/middleware/enhanced.spec.ts index 11467a44bd..4296d7843c 100644 --- a/cypress/integration/middleware/enhanced.spec.ts +++ b/cypress/integration/middleware/enhanced.spec.ts @@ -34,6 +34,7 @@ describe('Enhanced middleware', () => { expect(response.body).to.have.nested.property('headers.x-geo-city') expect(response.body).to.have.nested.property('headers.x-geo-longitude') expect(response.body).to.have.nested.property('headers.x-geo-latitude') + expect(response.body).to.have.nested.property('headers.x-geo-timezone') }) }) }) diff --git a/demos/middleware/middleware.ts b/demos/middleware/middleware.ts index 683783b291..a8472ccb40 100644 --- a/demos/middleware/middleware.ts +++ b/demos/middleware/middleware.ts @@ -35,6 +35,7 @@ export async function middleware(req: NextRequest) { req.headers.set('x-geo-city', req.geo.city) req.headers.set('x-geo-longitude', req.geo.longitude) req.headers.set('x-geo-latitude', req.geo.latitude) + req.headers.set('x-geo-timezone', req.geo.timezone) return request.next() } diff --git a/packages/next/src/middleware/request.ts b/packages/next/src/middleware/request.ts index f04554ad7d..077e2c82ee 100644 --- a/packages/next/src/middleware/request.ts +++ b/packages/next/src/middleware/request.ts @@ -1,9 +1,22 @@ import type { NextURL } from 'next/dist/server/web/next-url' import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' +import type { NextRequest as InternalNextRequest } from 'next/server' import { MiddlewareResponse } from './response' +export type NextRequest = InternalNextRequest & { + get geo(): + | { + city?: string + country?: string + region?: string + latitude?: string + longitude?: string + timezone?: string + } + | undefined +} + export interface NextOptions { /** * Include conditional request headers in the request to the origin. diff --git a/packages/runtime/src/templates/edge/next-dev.js b/packages/runtime/src/templates/edge/next-dev.js index 8575fcb9e4..094725f6f6 100644 --- a/packages/runtime/src/templates/edge/next-dev.js +++ b/packages/runtime/src/templates/edge/next-dev.js @@ -43,11 +43,14 @@ const handler = async (req, context) => { return } - // This is the format expected by Next.js + // This is the format expected by Next.js along with the timezone which we support. const geo = { country: context.geo.country?.code, region: context.geo.subdivision?.code, city: context.geo.city, + latitude: context.geo.latitude?.toString(), + longitude: context.geo.longitude?.toString(), + timezone: context.geo.timezone, } // A default request id is fine locally diff --git a/packages/runtime/src/templates/edge/runtime.ts b/packages/runtime/src/templates/edge/runtime.ts index 2023307bfb..59d7a4a9cd 100644 --- a/packages/runtime/src/templates/edge/runtime.ts +++ b/packages/runtime/src/templates/edge/runtime.ts @@ -20,6 +20,7 @@ export interface RequestData { region?: string latitude?: string longitude?: string + timezone?: string } headers: Record ip?: string @@ -69,6 +70,7 @@ const handler = async (req: Request, context: Context) => { city: context.geo.city, latitude: context.geo.latitude?.toString(), longitude: context.geo.longitude?.toString(), + timezone: context.geo.timezone, } const requestId = req.headers.get('x-nf-request-id') From 42381b7ead4f076b6bca0308fcc42e499c8a432f Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Thu, 17 Nov 2022 17:55:51 -0500 Subject: [PATCH 4/8] test: updated geo test for request --- packages/next/test/request.spec.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/next/test/request.spec.ts b/packages/next/test/request.spec.ts index 2fb7a64494..a421de9544 100644 --- a/packages/next/test/request.spec.ts +++ b/packages/next/test/request.spec.ts @@ -25,6 +25,9 @@ describe('MiddlewareRequest', () => { code: chance.province(), }, city: chance.city(), + latitude: chance.latitude(), + longitude: chance.longitude(), + timezone: chance.timezone(), }, ip, } @@ -33,6 +36,9 @@ describe('MiddlewareRequest', () => { country: context.geo.country?.code, region: context.geo.subdivision?.code, city: context.geo.city, + latitude: context.geo.latitude?.toString(), + longitude: context.geo.longitude?.toString(), + timezone: context.geo.timezone, } const req = new URL(url) From f3af4ad8532f1c2792b4983d548f1611a5a60adf Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Thu, 17 Nov 2022 18:05:21 -0500 Subject: [PATCH 5/8] chore: imported correct NextRequest type --- demos/middleware/middleware.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/demos/middleware/middleware.ts b/demos/middleware/middleware.ts index a8472ccb40..1816dd39bc 100644 --- a/demos/middleware/middleware.ts +++ b/demos/middleware/middleware.ts @@ -1,7 +1,5 @@ import { NextResponse } from 'next/server' -import type { NextRequest } from 'next/server' - -import { MiddlewareRequest } from '@netlify/next' +import { MiddlewareRequest, NextRequest } from '@netlify/next' export async function middleware(req: NextRequest) { let response From fcf020f349311e75fbcf4008f9fa57501b2c17c5 Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Thu, 17 Nov 2022 18:07:46 -0500 Subject: [PATCH 6/8] chore: removed unused import --- cypress/integration/middleware/enhanced.spec.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/integration/middleware/enhanced.spec.ts b/cypress/integration/middleware/enhanced.spec.ts index 4296d7843c..99111353df 100644 --- a/cypress/integration/middleware/enhanced.spec.ts +++ b/cypress/integration/middleware/enhanced.spec.ts @@ -1,4 +1,3 @@ -import { NextRequest } from 'next/server' describe('Enhanced middleware', () => { it('adds request headers', () => { cy.request('/api/hello').then((response) => { From b658c0c3c26075fd4dc0120465ed3d6fc47640a8 Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Thu, 17 Nov 2022 18:43:59 -0500 Subject: [PATCH 7/8] chore: updated api route for geo test --- cypress/integration/middleware/enhanced.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/integration/middleware/enhanced.spec.ts b/cypress/integration/middleware/enhanced.spec.ts index 99111353df..9fc8bfe06f 100644 --- a/cypress/integration/middleware/enhanced.spec.ts +++ b/cypress/integration/middleware/enhanced.spec.ts @@ -27,7 +27,7 @@ describe('Enhanced middleware', () => { }) it('adds geo data', () => { - cy.request('/api/geo-test').then((response) => { + cy.request('/api/geo').then((response) => { expect(response.body).to.have.nested.property('headers.x-geo-country') expect(response.body).to.have.nested.property('headers.x-geo-region') expect(response.body).to.have.nested.property('headers.x-geo-city') From 4d0801f860fe130b80dac92cd38843407f0423fc Mon Sep 17 00:00:00 2001 From: Nick Taylor Date: Fri, 18 Nov 2022 06:54:43 -0500 Subject: [PATCH 8/8] chore: cleaned up NextRequest type --- packages/next/src/middleware/request.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/next/src/middleware/request.ts b/packages/next/src/middleware/request.ts index 077e2c82ee..737ea90b37 100644 --- a/packages/next/src/middleware/request.ts +++ b/packages/next/src/middleware/request.ts @@ -5,16 +5,9 @@ import type { NextRequest as InternalNextRequest } from 'next/server' import { MiddlewareResponse } from './response' export type NextRequest = InternalNextRequest & { - get geo(): - | { - city?: string - country?: string - region?: string - latitude?: string - longitude?: string - timezone?: string - } - | undefined + get geo(): { + timezone?: string + } } export interface NextOptions {