@datadome/module-nextjs
Version:
DataDome module for Next.js applications
91 lines (85 loc) • 3.37 kB
text/typescript
import { RequestCookies } from 'next/dist/compiled/@edge-runtime/cookies';
import { NextRequest } from 'next/server';
import { RequestData } from './middleware';
/**
* This function is used to attach the list of headers from the DataDome's protection API response to the incoming request.
* This function is mainly used to attach the DataDome's enriched headers.
* @see {@link https://docs.datadome.co/docs/logs-integration} for the available enriched headers.
* @param reqHeaders - The headers of the incoming request.
* @param dataDomeResHeaders - The headers of the DataDome's protection API response.
* @param listKey - The header key we want to retrieve.
* @returns A map of string.
*/
export function convertHeadersToMap(
reqHeaders: Headers,
dataDomeResHeaders: Headers,
listKey: string,
): Map<string, string> {
const map = new Map<string, string>();
const list = dataDomeResHeaders.get(listKey);
if (!list) {
return map;
}
for (const header of list.split(' ')) {
const value = dataDomeResHeaders.get(header);
// workaround for a bug in DataDome where the cookie domain gets set to
// the entire public suffix (.vercel.app), which UAs refuse to set cookies for
// e.g.: https://devcenter.heroku.com/articles/cookies-and-herokuapp-com
if (value) {
if (header.toLowerCase() === 'set-cookie' && /domain=\.vercel\.app/i.test(value)) {
map.set(header, value.replace(/domain=\.vercel\.app/i, `Domain=${reqHeaders.get('host')}`));
} else {
map.set(header, value);
}
}
}
return map;
}
/**
* This functions is used to return all the headers from the request in a string separated by commas.
* @param req - The incoming request.
* @returns A comma separated list of headers.
*/
export function getHeadersList(req: NextRequest): string {
return [...req.headers.keys()].join(',');
}
/**
* This function is used to return the length of the Authorization header.
* @param req - The incoming request.
* @returns The length of the Authorization header.
*/
export function getAuthorizationLength(req: NextRequest): number | undefined {
const authorization = req.headers.get('authorization');
return authorization?.length;
}
/**
* This function is used to create an URL-encoded string of the payload of the Protection API.
* @param obj - The truncated payload for the Protection API.
* @returns An URL-encoded string of the truncated payload.
*/
export function stringify(obj: RequestData) {
return obj
? (Object.keys(obj) as (keyof RequestData)[])
.reduce<string[]>((acc, key) => {
const value = obj[key];
if (!value) {
return acc;
}
acc.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
return acc;
}, [])
.join('&')
: '';
}
/**
* Returns the value of the `datadome` cookie.
* @param cookies - the cookies of the request.
* @returns The Client ID of the request.
*/
export function getCookieData(cookies: RequestCookies): string {
const datadomeCookie = cookies.get('datadome');
if (datadomeCookie !== undefined) {
return datadomeCookie.value;
}
return '';
}