这是我的问题:我正在尝试计算收到的参数数量,以便将它们写入访问日志中。 我使用从express、graphql 启动的apollo 服务器作为我的API 入口点,并且使用摩根库来写入访问日志。
我尝试使用 apollo 插件从 graphql 请求中检索信息。我可以从插件中找出我有多少个参数,但我无法将此信息传递给请求上下文,以便摩根库可以检索要写入的参数数量。
我制作了一个 .js 文件,总结了我想要使用 console.log 进行调试的操作
const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const { json } = require('body-parser');
const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
morgan.token('countID', (req) => {
console.log('req.countID', req.countID);
if (req.countID) return req.countID;
return '-';
});
const logger = morgan('[:date[clf]] ":method :url HTTP/:http-version" :status ":countID"', { stream: process.stdout });
const typeDefs = `#graphql
type Query {
hello(id: [ID!]!): String
}
`;
const resolvers = {
Query: {
hello: (parent, args, context, info) => {
const { id } = args;
return `id: ${id.length}`;
},
},
};
const countIDPlugin = {
requestDidStart() {
return {
executionDidStart() {
return {
willResolveField({ info, contextValue: resolverContext }) {
const args = info?.fieldNodes[0]?.arguments.filter((e) => e.name.value === 'id');
const countID = args[0]?.value?.values?.length
if (!countID) {
return;
}
console.log('plugin:', countID)
resolverContext.countID = countID;
console.log('resolverContext.countID: ', countID)
},
};
},
};
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: true,
csrfPrevention: false,
plugins: [
countIDPlugin,
],
context: ({ req }) => ({ req }),
});
(async () => {
const app = express();
app.use(logger);
app.use(cors({
origin: '*',
allowedHeaders: ['Content-Type', 'x-api-key'],
method: ['GET', 'POST'],
}));
await server.start();
app.use('/graphql', cors(), json(), expressMiddleware(server, {}));
app.listen(3000, async () => {
console.log('Server up')
});
})();
有了这个js文件,当我启动服务器和执行graphql请求时,就会有我的日志:
Server up
plugin: 3
resolverContext.countID: 3
req.countID undefined
[11/Mar/2024:19:47:00 +0000] "POST /graphql HTTP/1.1" 200 "-"
我不知道通过 apollo 插件来做我想做的事情是否是正确的解决方案,我仍然对其他建议持开放态度。
提前致谢
您可以通过以下方式向中间件添加上下文表达来做到这一点:
app.use('/graphql', cors(), json(), expressMiddleware(server, {
context: async ({ req }) => req,
}));
在您的 willResolveField 函数中,您可以执行以下操作
contextValue.res.req.countID = countID;
这是完整和简化的代码
const cors = require('cors');
const express = require('express');
const morgan = require('morgan');
const { json } = require('body-parser');
const { ApolloServer } = require('@apollo/server');
const { expressMiddleware } = require('@apollo/server/express4');
morgan.token('countID', (req) => (req?.countID || '-'));
const logger = morgan('[:date[clf]] ":method :url HTTP/:http-version" :status ":countID"', { stream: process.stdout });
const typeDefs = `#graphql
type Query {
hello(id: [ID!]!): String
}
`;
const resolvers = {
Query: {
hello: (parent, args, context, info) => (`id: ${context.countID}`),
},
};
const countIDPlugin = {
requestDidStart() {
return {
executionDidStart() {
return {
willResolveField({ args, contextValue }) {
const countID = args?.id?.length;
if (!countID) { return; }
contextValue.res.req.countID = countID;
contextValue.countID = countID;
},
};
},
};
},
};
const server = new ApolloServer({
typeDefs,
resolvers,
introspection: true,
csrfPrevention: false,
plugins: [
countIDPlugin,
],
context: ({ req }) => ({ req }),
});
(async () => {
const app = express();
app.use(logger);
app.use(cors({
origin: '*',
allowedHeaders: ['Content-Type', 'x-api-key'],
method: ['GET', 'POST'],
}));
await server.start();
app.use('/graphql', cors(), json(), expressMiddleware(server, {
context: async ({ req }) => req,
}));
app.listen(3000, async () => {
console.log('Server up')
});
})();