使用express-graphql时GraphQL Mutation无法正常工作求助
排查express-graphql + swagger-to-graphql Mutation POST请求报错问题
我来帮你分析下这个问题,你遇到的uncaughtException: First argument must be a string or Buffer错误,大概率是POST请求的请求体没有被正确序列化为JSON字符串导致的,结合你的场景,咱们从这几个方向排查:
1. 先检查Swagger Schema的请求体定义是否正确
swagger-to-graphql完全依赖Swagger Schema生成GraphQL操作,首先要确认你的schema.json里addPet接口的请求体配置没问题:
- 找到
paths下/pet的post方法,确认requestBody(Swagger 3.0)或parameters(Swagger 2.0)是否正确标记了application/json类型,并且字段定义和你传入的Mutation参数匹配。 - 比如Swagger 3.0的正确配置应该类似这样:
"/pet": { "post": { "summary": "Add a new pet to the store", "requestBody": { "required": true, "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Pet" } } } } } } - 再检查
components/schemas/Pet的定义,确保id的类型是string(你传的是"111"字符串),name是必填字符串,photoUrls是字符串数组——如果类型不匹配,swagger-to-graphql可能无法正确转换请求体。
2. 升级依赖并调整代理地址配置
旧版本的swagger-to-graphql存在请求体序列化的bug,先升级依赖试试:
npm update swagger-to-graphql express-graphql
另外,你的GQLProxyBaseUrl末尾带了斜杠,可能导致接口地址拼接错误(比如变成http://localhost:3000/api/v2//pet),改成不带末尾斜杠的版本:
context: { GQLProxyBaseUrl: 'http://localhost:3000/api/v2', },
3. 自定义Fetch逻辑强制序列化请求体
如果升级后还是报错,那可以手动干预swagger-to-graphql的请求发送逻辑,强制把请求体序列化为JSON字符串。修改你的代码如下:
'use strict'; var graphqlHTTP = require('express-graphql'); var graphQLSchema = require('swagger-to-graphql'); var pathToSwaggerSchema = require('./schema.json'); const fetch = require('node-fetch'); // 需要先安装node-fetch:npm install node-fetch module.exports = function(server) { var router = server.loopback.Router(); router.get('/', server.loopback.status()); graphQLSchema(pathToSwaggerSchema, { // 自定义fetch逻辑,处理POST/PUT请求体 customFetch: async (url, options) => { if (['POST', 'PUT'].includes(options.method)) { // 把对象类型的body序列化为JSON字符串 options.body = JSON.stringify(options.body); // 确保Content-Type是application/json options.headers = { ...options.headers, 'Content-Type': 'application/json', }; } return fetch(url, options); } }).then(schema => { server.use('/graphql', graphqlHTTP((req) => { return { schema: schema, context: { GQLProxyBaseUrl: 'http://localhost:3000/api/v2', }, graphiql: true, }; })); }).catch(e => { throw e; }); server.use(router); };
这个方法强制将请求体转换成JSON字符串,解决了"First argument must be a string or Buffer"的核心问题。
4. 调试验证请求内容
如果还是有问题,可以在customFetch里加日志,打印实际发送的url和options,确认请求体的内容和类型:
customFetch: async (url, options) => { console.log('请求地址:', url); console.log('请求方法:', options.method); console.log('请求体类型:', typeof options.body); console.log('请求体内容:', options.body); // ...后续处理逻辑 }
通过日志可以直观看到请求体是否是字符串类型,以及内容是否符合后端接口的要求。
内容的提问来源于stack exchange,提问作者zulekha
相关产品推荐
相关产品推荐

