mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 21:07:46 +00:00
[@vercel/edge] add header helpers (#8036)
* [@vercel/edge] add header helpers * rename getIp => ipAddress, getGeo => geolocation, as suggested by @kikobeats
This commit is contained in:
82
packages/edge/src/edge-headers.ts
Normal file
82
packages/edge/src/edge-headers.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* City of the original client IP calculated by Vercel Proxy.
|
||||
*/
|
||||
export const CITY_HEADER_NAME = 'x-vercel-ip-city';
|
||||
/**
|
||||
* Country of the original client IP calculated by Vercel Proxy.
|
||||
*/
|
||||
export const COUNTRY_HEADER_NAME = 'x-vercel-ip-country';
|
||||
/**
|
||||
* Ip from Vercel Proxy. Do not confuse it with the client Ip.
|
||||
*/
|
||||
export const IP_HEADER_NAME = 'x-real-ip';
|
||||
/**
|
||||
* Latitude of the original client IP calculated by Vercel Proxy.
|
||||
*/
|
||||
export const LATITUDE_HEADER_NAME = 'x-vercel-ip-latitude';
|
||||
/**
|
||||
* Longitude of the original client IP calculated by Vercel Proxy.
|
||||
*/
|
||||
export const LONGITUDE_HEADER_NAME = 'x-vercel-ip-longitude';
|
||||
/**
|
||||
* Region of the original client IP calculated by Vercel Proxy.
|
||||
*/
|
||||
export const REGION_HEADER_NAME = 'x-vercel-ip-country-region';
|
||||
|
||||
/**
|
||||
* We define a new type so this function can be reused with
|
||||
* the global `Request`, `node-fetch` and other types.
|
||||
*/
|
||||
interface Request {
|
||||
headers: {
|
||||
get(name: string): string | null;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The location information of a given request
|
||||
*/
|
||||
export interface Geo {
|
||||
/** The city that the request originated from */
|
||||
city?: string;
|
||||
/** The country that the request originated from */
|
||||
country?: string;
|
||||
/** The Vercel Edge Network region that received the request */
|
||||
region?: string;
|
||||
/** The latitude of the client */
|
||||
latitude?: string;
|
||||
/** The longitude of the client */
|
||||
longitude?: string;
|
||||
}
|
||||
|
||||
function getHeader(request: Request, key: string): string | undefined {
|
||||
return request.headers.get(key) ?? undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the IP address of the request from the headers.
|
||||
*
|
||||
* @see {@link IP_HEADER_NAME}
|
||||
*/
|
||||
export function ipAddress(request: Request): string | undefined {
|
||||
return getHeader(request, IP_HEADER_NAME);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location information from for the incoming request
|
||||
*
|
||||
* @see {@link CITY_HEADER_NAME}
|
||||
* @see {@link COUNTRY_HEADER_NAME}
|
||||
* @see {@link REGION_HEADER_NAME}
|
||||
* @see {@link LATITUDE_HEADER_NAME}
|
||||
* @see {@link LONGITUDE_HEADER_NAME}
|
||||
*/
|
||||
export function geolocation(request: Request): Geo {
|
||||
return {
|
||||
city: getHeader(request, CITY_HEADER_NAME),
|
||||
country: getHeader(request, COUNTRY_HEADER_NAME),
|
||||
region: getHeader(request, REGION_HEADER_NAME),
|
||||
latitude: getHeader(request, LATITUDE_HEADER_NAME),
|
||||
longitude: getHeader(request, LONGITUDE_HEADER_NAME),
|
||||
};
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
export type { ExtraResponseInit } from './middleware-helpers';
|
||||
export { next, rewrite } from './middleware-helpers';
|
||||
export * from './middleware-helpers';
|
||||
|
||||
export type { Geo } from './edge-headers';
|
||||
export * from './edge-headers';
|
||||
|
||||
50
packages/edge/test/edge-headers.test.ts
vendored
Normal file
50
packages/edge/test/edge-headers.test.ts
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* @jest-environment @edge-runtime/jest-environment
|
||||
*/
|
||||
|
||||
import {
|
||||
CITY_HEADER_NAME,
|
||||
COUNTRY_HEADER_NAME,
|
||||
Geo,
|
||||
geolocation,
|
||||
ipAddress,
|
||||
IP_HEADER_NAME,
|
||||
LATITUDE_HEADER_NAME,
|
||||
LONGITUDE_HEADER_NAME,
|
||||
REGION_HEADER_NAME,
|
||||
} from '../src';
|
||||
|
||||
test('`ipAddress` returns the value from the header', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[IP_HEADER_NAME]: '127.0.0.1',
|
||||
},
|
||||
});
|
||||
expect(ipAddress(req)).toBe('127.0.0.1');
|
||||
});
|
||||
|
||||
describe('`geolocation`', () => {
|
||||
test('returns an empty object if headers are not found', () => {
|
||||
const req = new Request('https://example.vercel.sh');
|
||||
expect(geolocation(req)).toEqual({});
|
||||
});
|
||||
|
||||
test('reads values from headers', () => {
|
||||
const req = new Request('https://example.vercel.sh', {
|
||||
headers: {
|
||||
[CITY_HEADER_NAME]: 'Tel Aviv',
|
||||
[COUNTRY_HEADER_NAME]: 'Israel',
|
||||
[LATITUDE_HEADER_NAME]: '32.109333',
|
||||
[LONGITUDE_HEADER_NAME]: '34.855499',
|
||||
[REGION_HEADER_NAME]: 'fra1',
|
||||
},
|
||||
});
|
||||
expect(geolocation(req)).toEqual<Geo>({
|
||||
city: 'Tel Aviv',
|
||||
country: 'Israel',
|
||||
latitude: '32.109333',
|
||||
longitude: '34.855499',
|
||||
region: 'fra1',
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user