Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@vercel/edge

Package Overview
Dependencies
Maintainers
7
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vercel/edge - npm Package Compare versions

Comparing version 0.0.5 to 0.1.0

docs/interfaces/ModifiedRequest.md

42

dist/index.d.ts

@@ -0,1 +1,25 @@

interface ModifiedRequest {
/**
* If set, overwrites the incoming headers to the origin request.
*
* This is useful when you want to pass data between a Middleware and a
* Serverless or Edge Function.
*
* @example
* <caption>Add a `x-user-id` header and remove the `Authorization` header</caption>
*
* ```ts
* import { rewrite } from '@vercel/edge';
* export default async function middleware(request: Request): Promise<Response> {
* const newHeaders = new Headers(request.headers);
* newHeaders.set('x-user-id', 'user_123');
* newHeaders.delete('authorization');
* return rewrite(request.url, {
* request: { headers: newHeaders }
* })
* }
* ```
*/
headers?: Headers;
}
interface ExtraResponseInit extends Omit<ResponseInit, 'headers'> {

@@ -7,2 +31,6 @@ /**

headers?: HeadersInit;
/**
* Fields to rewrite for the upstream request.
*/
request?: ModifiedRequest;
}

@@ -106,6 +134,12 @@ /**

/**
* Region of the original client IP as calculated by Vercel Proxy.
* Country region of the original client IP calculated by Vercel Proxy.
*
* See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
*/
declare const REGION_HEADER_NAME = "x-vercel-ip-country-region";
/**
* The request ID for each request generated by Vercel Proxy.
*/
declare const REQUEST_ID_HEADER_NAME = "x-vercel-id";
/**
* We define a new type so this function can be reused with

@@ -129,2 +163,6 @@ * the global `Request`, `node-fetch` and other types.

region?: string;
/** The region part of the ISO 3166-2 code of the client IP.
* See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
*/
countryRegion?: string;
/** The latitude of the client. */

@@ -154,2 +192,2 @@ latitude?: string;

export { CITY_HEADER_NAME, COUNTRY_HEADER_NAME, ExtraResponseInit, Geo, IP_HEADER_NAME, LATITUDE_HEADER_NAME, LONGITUDE_HEADER_NAME, REGION_HEADER_NAME, geolocation, ipAddress, next, rewrite };
export { CITY_HEADER_NAME, COUNTRY_HEADER_NAME, ExtraResponseInit, Geo, IP_HEADER_NAME, LATITUDE_HEADER_NAME, LONGITUDE_HEADER_NAME, ModifiedRequest, REGION_HEADER_NAME, REQUEST_ID_HEADER_NAME, geolocation, ipAddress, next, rewrite };

@@ -29,2 +29,3 @@ "use strict";

REGION_HEADER_NAME: () => REGION_HEADER_NAME,
REQUEST_ID_HEADER_NAME: () => REQUEST_ID_HEADER_NAME,
geolocation: () => geolocation,

@@ -38,5 +39,20 @@ ipAddress: () => ipAddress,

// src/middleware-helpers.ts
function handleMiddlewareField(init, headers) {
var _a;
if ((_a = init == null ? void 0 : init.request) == null ? void 0 : _a.headers) {
if (!(init.request.headers instanceof Headers)) {
throw new Error("request.headers must be an instance of Headers");
}
const keys = [];
for (const [key, value] of init.request.headers) {
headers.set("x-middleware-request-" + key, value);
keys.push(key);
}
headers.set("x-middleware-override-headers", keys.join(","));
}
}
function rewrite(destination, init) {
const headers = new Headers((init == null ? void 0 : init.headers) ?? {});
headers.set("x-middleware-rewrite", String(destination));
handleMiddlewareField(init, headers);
return new Response(null, {

@@ -50,2 +66,3 @@ ...init,

headers.set("x-middleware-next", "1");
handleMiddlewareField(init, headers);
return new Response(null, {

@@ -64,2 +81,3 @@ ...init,

var REGION_HEADER_NAME = "x-vercel-ip-country-region";
var REQUEST_ID_HEADER_NAME = "x-vercel-id";
function getHeader(request, key) {

@@ -71,2 +89,8 @@ return request.headers.get(key) ?? void 0;

}
function getRegionFromRequestId(requestId) {
if (!requestId) {
return "dev1";
}
return requestId.split(":")[0];
}
function geolocation(request) {

@@ -76,3 +100,4 @@ return {

country: getHeader(request, COUNTRY_HEADER_NAME),
region: getHeader(request, REGION_HEADER_NAME),
countryRegion: getHeader(request, REGION_HEADER_NAME),
region: getRegionFromRequestId(getHeader(request, REQUEST_ID_HEADER_NAME)),
latitude: getHeader(request, LATITUDE_HEADER_NAME),

@@ -90,2 +115,3 @@ longitude: getHeader(request, LONGITUDE_HEADER_NAME)

REGION_HEADER_NAME,
REQUEST_ID_HEADER_NAME,
geolocation,

@@ -92,0 +118,0 @@ ipAddress,

@@ -14,2 +14,3 @@ # Interface: ExtraResponseInit

- [headers](ExtraResponseInit.md#headers)
- [request](ExtraResponseInit.md#request)
- [status](ExtraResponseInit.md#status)

@@ -29,6 +30,18 @@ - [statusText](ExtraResponseInit.md#statustext)

[src/middleware-helpers.ts:6](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L6)
[src/middleware-helpers.ts:31](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L31)
---
### request
• `Optional` **request**: [`ModifiedRequest`](ModifiedRequest.md)
Fields to rewrite for the upstream request.
#### Defined in
[src/middleware-helpers.ts:35](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L35)
---
### status

@@ -35,0 +48,0 @@

24

docs/interfaces/Geo.md

@@ -11,2 +11,3 @@ # Interface: Geo

- [country](Geo.md#country)
- [countryRegion](Geo.md#countryregion)
- [latitude](Geo.md#latitude)

@@ -26,3 +27,3 @@ - [longitude](Geo.md#longitude)

[src/edge-headers.ts:41](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L41)
[src/edge-headers.ts:47](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L47)

@@ -39,6 +40,19 @@ ---

[src/edge-headers.ts:44](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L44)
[src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
---
### countryRegion
• `Optional` **countryRegion**: `string`
The region part of the ISO 3166-2 code of the client IP.
See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
#### Defined in
[src/edge-headers.ts:58](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L58)
---
### latitude

@@ -52,3 +66,3 @@

[src/edge-headers.ts:50](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L50)
[src/edge-headers.ts:61](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L61)

@@ -65,3 +79,3 @@ ---

[src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)
[src/edge-headers.ts:64](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L64)

@@ -78,2 +92,2 @@ ---

[src/edge-headers.ts:47](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L47)
[src/edge-headers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L53)

@@ -9,2 +9,3 @@ # @vercel/edge

- [Geo](interfaces/Geo.md)
- [ModifiedRequest](interfaces/ModifiedRequest.md)

@@ -19,2 +20,3 @@ ### Variables

- [REGION_HEADER_NAME](README.md#region_header_name)
- [REQUEST_ID_HEADER_NAME](README.md#request_id_header_name)

@@ -94,8 +96,22 @@ ### Functions

Region of the original client IP as calculated by Vercel Proxy.
Country region of the original client IP calculated by Vercel Proxy.
See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
#### Defined in
[src/edge-headers.ts:24](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L24)
[src/edge-headers.ts:26](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L26)
---
### REQUEST_ID_HEADER_NAME
• `Const` **REQUEST_ID_HEADER_NAME**: `"x-vercel-id"`
The request ID for each request generated by Vercel Proxy.
#### Defined in
[src/edge-headers.ts:30](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L30)
## Functions

@@ -129,3 +145,3 @@

[src/edge-headers.ts:80](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L80)
[src/edge-headers.ts:106](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L106)

@@ -156,3 +172,3 @@ ---

[src/edge-headers.ts:66](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L66)
[src/edge-headers.ts:77](https://github.com/vercel/vercel/blob/main/packages/edge/src/edge-headers.ts#L77)

@@ -205,3 +221,3 @@ ---

[src/middleware-helpers.ts:94](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L94)
[src/middleware-helpers.ts:145](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L145)

@@ -268,2 +284,2 @@ ---

[src/middleware-helpers.ts:53](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L53)
[src/middleware-helpers.ts:101](https://github.com/vercel/vercel/blob/main/packages/edge/src/middleware-helpers.ts#L101)
{
"name": "@vercel/edge",
"version": "0.0.5",
"version": "0.1.0",
"license": "MIT",

@@ -15,3 +15,3 @@ "main": "dist/index.js",

"devDependencies": {
"@edge-runtime/jest-environment": "1.1.0-beta.36",
"@edge-runtime/jest-environment": "2.0.0",
"@types/jest": "27.4.1",

@@ -35,3 +35,3 @@ "ts-node": "8.9.1",

},
"gitHead": "dd94dcab3255839c7c9addbba35026dc88cf0e95"
"gitHead": "a630e1989613052f64411fd7e5468de58c5999ba"
}

@@ -22,5 +22,11 @@ /**

/**
* Region of the original client IP as calculated by Vercel Proxy.
* Country region of the original client IP calculated by Vercel Proxy.
*
* See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
*/
export const REGION_HEADER_NAME = 'x-vercel-ip-country-region';
/**
* The request ID for each request generated by Vercel Proxy.
*/
export const REQUEST_ID_HEADER_NAME = 'x-vercel-id';

@@ -50,2 +56,7 @@ /**

/** The region part of the ISO 3166-2 code of the client IP.
* See [docs](https://vercel.com/docs/concepts/edge-network/headers#x-vercel-ip-country-region).
*/
countryRegion?: string;
/** The latitude of the client. */

@@ -73,2 +84,17 @@ latitude?: string;

/**
* Extracts the Vercel Edge Network region name from the request ID.
*
* @param requestId The request ID (`x-vercel-id`).
* @returns The first region received the client request.
*/
function getRegionFromRequestId(requestId?: string): string | undefined {
if (!requestId) {
return 'dev1';
}
// The request ID is in the format of `region::id` or `region1:region2:...::id`.
return requestId.split(':')[0];
}
/**
* Returns the location information for the incoming request.

@@ -87,3 +113,4 @@ *

country: getHeader(request, COUNTRY_HEADER_NAME),
region: getHeader(request, REGION_HEADER_NAME),
countryRegion: getHeader(request, REGION_HEADER_NAME),
region: getRegionFromRequestId(getHeader(request, REQUEST_ID_HEADER_NAME)),
latitude: getHeader(request, LATITUDE_HEADER_NAME),

@@ -90,0 +117,0 @@ longitude: getHeader(request, LONGITUDE_HEADER_NAME),

@@ -0,1 +1,26 @@

export interface ModifiedRequest {
/**
* If set, overwrites the incoming headers to the origin request.
*
* This is useful when you want to pass data between a Middleware and a
* Serverless or Edge Function.
*
* @example
* <caption>Add a `x-user-id` header and remove the `Authorization` header</caption>
*
* ```ts
* import { rewrite } from '@vercel/edge';
* export default async function middleware(request: Request): Promise<Response> {
* const newHeaders = new Headers(request.headers);
* newHeaders.set('x-user-id', 'user_123');
* newHeaders.delete('authorization');
* return rewrite(request.url, {
* request: { headers: newHeaders }
* })
* }
* ```
*/
headers?: Headers;
}
export interface ExtraResponseInit extends Omit<ResponseInit, 'headers'> {

@@ -7,4 +32,27 @@ /**

headers?: HeadersInit;
/**
* Fields to rewrite for the upstream request.
*/
request?: ModifiedRequest;
}
function handleMiddlewareField(
init: ExtraResponseInit | undefined,
headers: Headers
) {
if (init?.request?.headers) {
if (!(init.request.headers instanceof Headers)) {
throw new Error('request.headers must be an instance of Headers');
}
const keys = [];
for (const [key, value] of init.request.headers) {
headers.set('x-middleware-request-' + key, value);
keys.push(key);
}
headers.set('x-middleware-override-headers', keys.join(','));
}
}
/**

@@ -60,2 +108,5 @@ * Returns a response that rewrites the request to a different URL.

headers.set('x-middleware-rewrite', String(destination));
handleMiddlewareField(init, headers);
return new Response(null, {

@@ -99,2 +150,5 @@ ...init,

headers.set('x-middleware-next', '1');
handleMiddlewareField(init, headers);
return new Response(null, {

@@ -101,0 +155,0 @@ ...init,

@@ -15,2 +15,3 @@ /**

REGION_HEADER_NAME,
REQUEST_ID_HEADER_NAME,
} from '../src';

@@ -28,5 +29,12 @@

describe('`geolocation`', () => {
test('returns an empty object if headers are not found', () => {
test('returns an object with lots of undefined if headers are not found', () => {
const req = new Request('https://example.vercel.sh');
expect(geolocation(req)).toEqual({});
expect(geolocation(req)).toEqual({
city: undefined,
country: undefined,
countryRegion: undefined,
latitude: undefined,
longitude: undefined,
region: 'dev1',
});
});

@@ -41,3 +49,4 @@

[LONGITUDE_HEADER_NAME]: '34.855499',
[REGION_HEADER_NAME]: 'fra1',
[REGION_HEADER_NAME]: 'TA', // https://en.wikipedia.org/wiki/ISO_3166-2:IL
[REQUEST_ID_HEADER_NAME]: 'fra1::kpwjx-123455678-c0ffee',
},

@@ -51,4 +60,46 @@ });

region: 'fra1',
countryRegion: 'TA',
});
});
test('reads values from headers (with a request ID containing two edge regions)', () => {
const req = new Request('https://example.vercel.sh', {
headers: {
[CITY_HEADER_NAME]: 'Tokyo',
[COUNTRY_HEADER_NAME]: 'Japan',
[LATITUDE_HEADER_NAME]: '37.1233',
[LONGITUDE_HEADER_NAME]: '30.733399',
[REGION_HEADER_NAME]: '13',
[REQUEST_ID_HEADER_NAME]: 'hnd1:iad1::kpwjx-123455678-c0ffee',
},
});
expect(geolocation(req)).toEqual<Geo>({
city: 'Tokyo',
country: 'Japan',
latitude: '37.1233',
longitude: '30.733399',
region: 'hnd1',
countryRegion: '13',
});
});
test('reads values from headers (without a request ID)', () => {
const req = new Request('https://example.vercel.sh', {
headers: {
[CITY_HEADER_NAME]: 'Tokyo',
[COUNTRY_HEADER_NAME]: 'Japan',
[LATITUDE_HEADER_NAME]: '37.1233',
[LONGITUDE_HEADER_NAME]: '30.733399',
[REGION_HEADER_NAME]: '13',
},
});
expect(geolocation(req)).toEqual<Geo>({
city: 'Tokyo',
country: 'Japan',
latitude: '37.1233',
longitude: '30.733399',
region: 'dev1',
countryRegion: '13',
});
});
});

@@ -25,2 +25,28 @@ /**

});
test('receives new request headers', () => {
const headers = new Headers();
headers.set('x-from-middleware1', 'hello1');
headers.set('x-from-middleware2', 'hello2');
const resp = rewrite(new URL('https://example.vercel.sh/'), {
headers: {
'x-custom-header': 'custom-value',
},
request: { headers },
});
expect({
status: resp.status,
headers: Object.fromEntries(resp.headers),
}).toMatchObject({
status: 200,
headers: {
'x-middleware-rewrite': 'https://example.vercel.sh/',
'x-custom-header': 'custom-value',
'x-middleware-override-headers':
'x-from-middleware1,x-from-middleware2',
'x-middleware-request-x-from-middleware2': 'hello2',
'x-middleware-request-x-from-middleware1': 'hello1',
},
});
});
});

@@ -46,2 +72,28 @@

});
test('receives new request headers', () => {
const headers = new Headers();
headers.set('x-from-middleware1', 'hello1');
headers.set('x-from-middleware2', 'hello2');
const resp = next({
headers: {
'x-custom-header': 'custom-value',
},
request: { headers },
});
expect({
status: resp.status,
headers: Object.fromEntries(resp.headers),
}).toMatchObject({
status: 200,
headers: {
'x-middleware-next': '1',
'x-custom-header': 'custom-value',
'x-middleware-override-headers':
'x-from-middleware1,x-from-middleware2',
'x-middleware-request-x-from-middleware2': 'hello2',
'x-middleware-request-x-from-middleware1': 'hello1',
},
});
});
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc