mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-05-28 18:26:54 +00:00
dev(api): add build options to test env (#59957)
This commit is contained in:
+6
-2
@@ -1,6 +1,6 @@
|
|||||||
import request from 'supertest';
|
import request from 'supertest';
|
||||||
|
|
||||||
import { build } from './src/app';
|
import { build, buildOptions } from './src/app';
|
||||||
import { createUserInput } from './src/utils/create-user';
|
import { createUserInput } from './src/utils/create-user';
|
||||||
import { examJson } from './__mocks__/exam';
|
import { examJson } from './__mocks__/exam';
|
||||||
import { CSRF_COOKIE, CSRF_HEADER } from './src/plugins/csrf';
|
import { CSRF_COOKIE, CSRF_HEADER } from './src/plugins/csrf';
|
||||||
@@ -158,7 +158,11 @@ const indexData: IndexData[] = [
|
|||||||
export function setupServer(): void {
|
export function setupServer(): void {
|
||||||
let fastify: FastifyTestInstance;
|
let fastify: FastifyTestInstance;
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
fastify = await build();
|
if (process.env.FCC_ENABLE_TEST_LOGGING !== 'true') {
|
||||||
|
// @ts-expect-error Disable logging by unsetting logger
|
||||||
|
buildOptions.logger = undefined;
|
||||||
|
}
|
||||||
|
fastify = await build(buildOptions);
|
||||||
await fastify.ready();
|
await fastify.ready();
|
||||||
|
|
||||||
// Prisma does not support TTL indexes in the schema yet, so, to avoid
|
// Prisma does not support TTL indexes in the schema yet, so, to avoid
|
||||||
|
|||||||
@@ -70,6 +70,7 @@
|
|||||||
"develop": "tsx watch --clear-screen=false src/server.ts",
|
"develop": "tsx watch --clear-screen=false src/server.ts",
|
||||||
"start": "FREECODECAMP_NODE_ENV=production node dist/server.js",
|
"start": "FREECODECAMP_NODE_ENV=production node dist/server.js",
|
||||||
"test": "jest --force-exit",
|
"test": "jest --force-exit",
|
||||||
|
"test-with-logging": "FCC_ENABLE_TEST_LOGGING=true pnpm run test",
|
||||||
"prisma": "dotenv -e ../.env prisma",
|
"prisma": "dotenv -e ../.env prisma",
|
||||||
"postinstall": "prisma generate",
|
"postinstall": "prisma generate",
|
||||||
"generate-exams": "tsx tools/exam-environment/generate/index.ts",
|
"generate-exams": "tsx tools/exam-environment/generate/index.ts",
|
||||||
|
|||||||
+67
-1
@@ -1,3 +1,5 @@
|
|||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import fastifyAccepts from '@fastify/accepts';
|
import fastifyAccepts from '@fastify/accepts';
|
||||||
import fastifySwagger from '@fastify/swagger';
|
import fastifySwagger from '@fastify/swagger';
|
||||||
import fastifySwaggerUI from '@fastify/swagger-ui';
|
import fastifySwaggerUI from '@fastify/swagger-ui';
|
||||||
@@ -9,6 +11,7 @@ import Fastify, {
|
|||||||
FastifyBaseLogger,
|
FastifyBaseLogger,
|
||||||
FastifyHttpOptions,
|
FastifyHttpOptions,
|
||||||
FastifyInstance,
|
FastifyInstance,
|
||||||
|
FastifyRequest,
|
||||||
RawReplyDefaultExpression,
|
RawReplyDefaultExpression,
|
||||||
RawRequestDefaultExpression,
|
RawRequestDefaultExpression,
|
||||||
RawServerDefault
|
RawServerDefault
|
||||||
@@ -42,7 +45,9 @@ import {
|
|||||||
FCC_ENABLE_EXAM_ENVIRONMENT,
|
FCC_ENABLE_EXAM_ENVIRONMENT,
|
||||||
FCC_ENABLE_SENTRY_ROUTES,
|
FCC_ENABLE_SENTRY_ROUTES,
|
||||||
GROWTHBOOK_FASTIFY_API_HOST,
|
GROWTHBOOK_FASTIFY_API_HOST,
|
||||||
GROWTHBOOK_FASTIFY_CLIENT_KEY
|
GROWTHBOOK_FASTIFY_CLIENT_KEY,
|
||||||
|
FREECODECAMP_NODE_ENV,
|
||||||
|
FCC_API_LOG_LEVEL
|
||||||
} from './utils/env';
|
} from './utils/env';
|
||||||
import { isObjectID } from './utils/validation';
|
import { isObjectID } from './utils/validation';
|
||||||
import {
|
import {
|
||||||
@@ -78,6 +83,67 @@ ajv.addFormat('objectid', {
|
|||||||
validate: (str: string) => isObjectID(str)
|
validate: (str: string) => isObjectID(str)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const requestSerializer = (req: FastifyRequest) => {
|
||||||
|
const method = req.method || 'METHOD not found';
|
||||||
|
const url = req.url || 'URL not found';
|
||||||
|
const headers = req.headers || 'HEADERS not found';
|
||||||
|
const xForwardedFor = Array.isArray(req.headers['x-forwarded-for'])
|
||||||
|
? req.headers['x-forwarded-for'][0]
|
||||||
|
: req.headers['x-forwarded-for'];
|
||||||
|
const ip =
|
||||||
|
xForwardedFor || req.headers['x-real-ip'] || req.ip || 'IP not found';
|
||||||
|
const query = isEmpty(req.query) ? 'QUERY not found' : req.query;
|
||||||
|
const hostname = req.hostname || 'HOSTNAME not found';
|
||||||
|
const remotePort = req.socket.remotePort || 'REMOTE_PORT not found';
|
||||||
|
|
||||||
|
return {
|
||||||
|
REQ_ID: req.id,
|
||||||
|
METHOD: method,
|
||||||
|
URL: url,
|
||||||
|
IP: ip,
|
||||||
|
HOSTNAME: hostname,
|
||||||
|
REMOTE_PORT: remotePort,
|
||||||
|
QUERY: query,
|
||||||
|
HEADERS: headers
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const envToLogger = {
|
||||||
|
development: {
|
||||||
|
transport: {
|
||||||
|
target: 'pino-pretty',
|
||||||
|
options: {
|
||||||
|
singleLine: true,
|
||||||
|
translateTime: 'HH:MM:ss Z',
|
||||||
|
ignore: 'pid,hostname'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
level: FCC_API_LOG_LEVEL || 'info',
|
||||||
|
serializers: {
|
||||||
|
req: (req: FastifyRequest) => {
|
||||||
|
return {
|
||||||
|
method: req.method,
|
||||||
|
url: req.url
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// No need to redact in development
|
||||||
|
},
|
||||||
|
production: {
|
||||||
|
level: FCC_API_LOG_LEVEL || 'info',
|
||||||
|
serializers: {
|
||||||
|
req: requestSerializer
|
||||||
|
},
|
||||||
|
redact: ['req.HEADERS.cookie']
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const buildOptions = {
|
||||||
|
logger: envToLogger[FREECODECAMP_NODE_ENV] ?? true,
|
||||||
|
genReqId: () => randomBytes(8).toString('hex'),
|
||||||
|
disableRequestLogging: true
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Top-level wrapper to instantiate the API server. This is where all middleware and
|
* Top-level wrapper to instantiate the API server. This is where all middleware and
|
||||||
* routes should be mounted.
|
* routes should be mounted.
|
||||||
|
|||||||
+3
-72
@@ -1,79 +1,10 @@
|
|||||||
import './instrument';
|
import './instrument';
|
||||||
|
|
||||||
import { randomBytes } from 'crypto';
|
import { build, buildOptions } from './app';
|
||||||
|
import { HOST, PORT } from './utils/env';
|
||||||
import { FastifyRequest } from 'fastify';
|
|
||||||
import { isEmpty } from 'lodash';
|
|
||||||
|
|
||||||
import { build } from './app';
|
|
||||||
import {
|
|
||||||
FREECODECAMP_NODE_ENV,
|
|
||||||
FCC_API_LOG_LEVEL,
|
|
||||||
HOST,
|
|
||||||
PORT
|
|
||||||
} from './utils/env';
|
|
||||||
|
|
||||||
const requestSerializer = (req: FastifyRequest) => {
|
|
||||||
const method = req.method || 'METHOD not found';
|
|
||||||
const url = req.url || 'URL not found';
|
|
||||||
const headers = req.headers || 'HEADERS not found';
|
|
||||||
const xForwardedFor = Array.isArray(req.headers['x-forwarded-for'])
|
|
||||||
? req.headers['x-forwarded-for'][0]
|
|
||||||
: req.headers['x-forwarded-for'];
|
|
||||||
const ip =
|
|
||||||
xForwardedFor || req.headers['x-real-ip'] || req.ip || 'IP not found';
|
|
||||||
const query = isEmpty(req.query) ? 'QUERY not found' : req.query;
|
|
||||||
const hostname = req.hostname || 'HOSTNAME not found';
|
|
||||||
const remotePort = req.socket.remotePort || 'REMOTE_PORT not found';
|
|
||||||
|
|
||||||
return {
|
|
||||||
REQ_ID: req.id,
|
|
||||||
METHOD: method,
|
|
||||||
URL: url,
|
|
||||||
IP: ip,
|
|
||||||
HOSTNAME: hostname,
|
|
||||||
REMOTE_PORT: remotePort,
|
|
||||||
QUERY: query,
|
|
||||||
HEADERS: headers
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const envToLogger = {
|
|
||||||
development: {
|
|
||||||
transport: {
|
|
||||||
target: 'pino-pretty',
|
|
||||||
options: {
|
|
||||||
singleLine: true,
|
|
||||||
translateTime: 'HH:MM:ss Z',
|
|
||||||
ignore: 'pid,hostname'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
level: FCC_API_LOG_LEVEL || 'info',
|
|
||||||
serializers: {
|
|
||||||
req: (req: FastifyRequest) => {
|
|
||||||
return {
|
|
||||||
method: req.method,
|
|
||||||
url: req.url
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// No need to redact in development
|
|
||||||
},
|
|
||||||
production: {
|
|
||||||
level: FCC_API_LOG_LEVEL || 'info',
|
|
||||||
serializers: {
|
|
||||||
req: requestSerializer
|
|
||||||
},
|
|
||||||
redact: ['req.HEADERS.cookie']
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const start = async () => {
|
const start = async () => {
|
||||||
const fastify = await build({
|
const fastify = await build(buildOptions);
|
||||||
logger: envToLogger[FREECODECAMP_NODE_ENV] ?? true,
|
|
||||||
genReqId: () => randomBytes(8).toString('hex'),
|
|
||||||
disableRequestLogging: true
|
|
||||||
});
|
|
||||||
try {
|
try {
|
||||||
const port = Number(PORT);
|
const port = Number(PORT);
|
||||||
fastify.log.info(`Starting server on port ${port}`);
|
fastify.log.info(`Starting server on port ${port}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user