feat(proxy-server): allow setting proxy log level (#3989)

This commit is contained in:
Erez Rokah
2020-07-06 18:50:39 +03:00
committed by GitHub
parent 2da824bf71
commit 3e0d0886d9
10 changed files with 226 additions and 37 deletions

View File

@ -1,4 +1,6 @@
# optional, defaults to current directory
GIT_REPO_DIRECTORY=FULL_PATH_TO_LOCAL_GIT_REPO
# optional, defaults to 8081
PORT=CUSTOM_PORT
PORT=CUSTOM_PORT
# optional, defaults to false
LOG_LEVEL=info

View File

@ -28,7 +28,8 @@
"express": "^4.17.1",
"morgan": "^1.9.1",
"simple-git": "^2.0.0",
"what-the-diff": "^0.6.0"
"what-the-diff": "^0.6.0",
"winston": "^3.3.3"
},
"devDependencies": {
"@types/cors": "^2.8.6",

View File

@ -3,28 +3,35 @@ import express from 'express';
import { registerCommonMiddlewares } from './middlewares/common';
import { registerMiddleware as registerLocalGit } from './middlewares/localGit';
import { registerMiddleware as registerLocalFs } from './middlewares/localFs';
import { createLogger } from './logger';
const app = express();
const port = process.env.PORT || 8081;
const level = process.env.LOG_LEVEL || 'info';
(async () => {
registerCommonMiddlewares(app);
const logger = createLogger({ level });
const options = {
logger,
};
registerCommonMiddlewares(app, options);
try {
const mode = process.env.MODE || 'fs';
if (mode === 'fs') {
registerLocalFs(app);
registerLocalFs(app, options);
} else if (mode === 'git') {
registerLocalGit(app);
registerLocalGit(app, options);
} else {
throw new Error(`Unknown proxy mode '${mode}'`);
}
} catch (e) {
console.error(e.message);
logger.error(e.message);
process.exit(1);
}
return app.listen(port, () => {
console.log(`Netlify CMS Proxy Server listening on port ${port}`);
logger.info(`Netlify CMS Proxy Server listening on port ${port}`);
});
})();

View File

@ -0,0 +1,15 @@
import winston from 'winston';
const { combine, colorize, simple } = winston.format;
type LogOptions = {
level: string;
};
export const createLogger = ({ level }: LogOptions) => {
return winston.createLogger({
level,
format: combine(colorize(), simple()),
transports: [new winston.transports.Console()],
});
};

View File

@ -2,13 +2,26 @@ import express from 'express';
import { registerCommonMiddlewares } from './middlewares/common';
import { registerMiddleware as localGit } from './middlewares/localGit';
import { registerMiddleware as localFs } from './middlewares/localFs';
import { createLogger } from './logger';
export const registerLocalGit = async (app: express.Express) => {
registerCommonMiddlewares(app);
await localGit(app);
type Options = {
logLevel?: string;
};
export const registerLocalFs = async (app: express.Express) => {
registerCommonMiddlewares(app);
await localFs(app);
const createOptions = (options: Options) => {
return {
logger: createLogger({ level: options.logLevel || 'info' }),
};
};
export const registerLocalGit = async (app: express.Express, options: Options = {}) => {
const opts = createOptions(options);
registerCommonMiddlewares(app, opts);
await localGit(app, opts);
};
export const registerLocalFs = async (app: express.Express, options: Options = {}) => {
const opts = createOptions(options);
registerCommonMiddlewares(app, opts);
await localFs(app, opts);
};

View File

@ -1,9 +1,20 @@
import winston from 'winston';
import express from 'express';
import morgan from 'morgan';
import cors from 'cors';
export const registerCommonMiddlewares = (app: express.Express) => {
app.use(morgan('combined'));
export type Options = {
logger: winston.Logger;
};
export const registerCommonMiddlewares = (app: express.Express, options: Options) => {
const { logger } = options;
const stream = {
write: (message: string) => {
logger.info(String(message).trim());
},
};
app.use(morgan('combined', { stream }));
app.use(cors());
app.use(express.json({ limit: '50mb' }));
};

View File

@ -1,3 +1,4 @@
import winston from 'winston';
import express from 'express';
import path from 'path';
import { defaultSchema, joi } from '../joi';
@ -15,11 +16,12 @@ import {
import { listRepoFiles, deleteFile, writeFile, move } from '../utils/fs';
import { entriesFromFiles, readMediaFile } from '../utils/entries';
type Options = {
type FsOptions = {
repoPath: string;
logger: winston.Logger;
};
export const localFsMiddleware = ({ repoPath }: Options) => {
export const localFsMiddleware = ({ repoPath, logger }: FsOptions) => {
return async function(req: express.Request, res: express.Response) {
try {
const { body } = req;
@ -113,20 +115,25 @@ export const localFsMiddleware = ({ repoPath }: Options) => {
}
}
} catch (e) {
console.error(`Error handling ${JSON.stringify(req.body)}: ${e.message}`);
logger.error(`Error handling ${JSON.stringify(req.body)}: ${e.message}`);
res.status(500).json({ error: 'Unknown error' });
}
};
};
export const getSchema = ({ repoPath }: Options) => {
export const getSchema = ({ repoPath }: { repoPath: string }) => {
const schema = defaultSchema({ path: pathTraversal(repoPath) });
return schema;
};
export const registerMiddleware = async (app: express.Express) => {
type Options = {
logger: winston.Logger;
};
export const registerMiddleware = async (app: express.Express, options: Options) => {
const { logger } = options;
const repoPath = path.resolve(process.env.GIT_REPO_DIRECTORY || process.cwd());
app.post('/api/v1', joi(getSchema({ repoPath })));
app.post('/api/v1', localFsMiddleware({ repoPath }));
console.log(`Netlify CMS File System Proxy Server configured with ${repoPath}`);
app.post('/api/v1', localFsMiddleware({ repoPath, logger }));
logger.info(`Netlify CMS File System Proxy Server configured with ${repoPath}`);
};

View File

@ -1,3 +1,4 @@
import winston from 'winston';
import express from 'express';
import path from 'path';
import { promises as fs } from 'fs';
@ -65,8 +66,9 @@ const runOnBranch = async <T>(git: simpleGit.SimpleGit, branch: string, func: ()
const branchDescription = (branch: string) => `branch.${branch}.description`;
type Options = {
type GitOptions = {
repoPath: string;
logger: winston.Logger;
};
const commitEntry = async (
@ -142,7 +144,7 @@ const getDiffs = async (git: simpleGit.SimpleGit, source: string, dest: string)
return diffs;
};
export const validateRepo = async ({ repoPath }: Options) => {
export const validateRepo = async ({ repoPath }: { repoPath: string }) => {
const git = simpleGit(repoPath).silent(false);
const isRepo = await git.checkIsRepo();
if (!isRepo) {
@ -150,12 +152,12 @@ export const validateRepo = async ({ repoPath }: Options) => {
}
};
export const getSchema = ({ repoPath }: Options) => {
export const getSchema = ({ repoPath }: { repoPath: string }) => {
const schema = defaultSchema({ path: pathTraversal(repoPath) });
return schema;
};
export const localGitMiddleware = ({ repoPath }: Options) => {
export const localGitMiddleware = ({ repoPath, logger }: GitOptions) => {
const git = simpleGit(repoPath).silent(false);
return async function(req: express.Request, res: express.Response) {
@ -386,16 +388,21 @@ export const localGitMiddleware = ({ repoPath }: Options) => {
}
}
} catch (e) {
console.error(`Error handling ${JSON.stringify(req.body)}: ${e.message}`);
logger.error(`Error handling ${JSON.stringify(req.body)}: ${e.message}`);
res.status(500).json({ error: 'Unknown error' });
}
};
};
export const registerMiddleware = async (app: express.Express) => {
type Options = {
logger: winston.Logger;
};
export const registerMiddleware = async (app: express.Express, options: Options) => {
const { logger } = options;
const repoPath = path.resolve(process.env.GIT_REPO_DIRECTORY || process.cwd());
await validateRepo({ repoPath });
app.post('/api/v1', joi(getSchema({ repoPath })));
app.post('/api/v1', localGitMiddleware({ repoPath }));
console.log(`Netlify CMS Git Proxy Server configured with ${repoPath}`);
app.post('/api/v1', localGitMiddleware({ repoPath, logger }));
logger.info(`Netlify CMS Git Proxy Server configured with ${repoPath}`);
};