GCP API Gateway配置文件上传接口报参数映射错误如何解决
我正在尝试为GCP API Gateway创建如下api config(已隐去真实后端URL):
swagger: '2.0' info: title: upload description: upload version: 1.0.0 schemes: - https produces: - application/json security: - api_key: [ ] paths: /upload: post: summary: uploads a file. consumes: - multipart/form-data operationId: uploadFile parameters: - in: formData name: file description: The file to upload. required: true type: file responses: '200': description: upload successful x-google-backend: address: https://XXXXX.XXXXX path_translation: APPEND_PATH_TO_ADDRESS securityDefinitions: api_key: type: "apiKey" name: "key" in: "query"
执行如下gcloud命令(已将真实变量替换为占位符):
gcloud api-gateway api-configs create uploadconfig --api=[API] --openapi-spec=openapi.yaml --project=[MYPROJECT] --backend-auth-service-account=[ACCOUNT]
执行后返回如下error message:
ERROR: (gcloud.api-gateway.api-configs.create) INVALID_ARGUMENT: Cannot convert to service config.
'location: "unknown location"
kind: ERROR
message: "http: repeated message field 'google.protobuf.Struct.fields' referred to by message 'UploadFileRequest' cannot be mapped as an HTTP parameter."
location: "unknown location"
kind: ERROR
message: "http: cyclic message field 'google.protobuf.Struct.FieldsEntry.value' referred to by message 'UploadFileRequest' in method 'method 1.xxxxxxx.UploadFile' cannot be mapped as an HTTP parameter."'
我已使用其他API配置和后端验证过该gcloud命令可正常运行,且上述配置可通过Swagger编辑器校验,但gcloud始终无法接受该配置,请问如何在GCP API Gateway中正确定义文件上传接口?
报错核心原因是GCP API Gateway默认会对请求参数做转码映射,当你在OpenAPI 2.0中声明type: file的formData参数时,配置转换器会自动生成携带google.protobuf.Struct类型的请求消息结构,而Struct本身是带循环引用的重复字段结构,不支持直接映射为HTTP参数,最终触发转码失败。
按以下两点修改配置即可解决:
- 调整接口参数定义,移除原来formData类型的file参数声明,改为body类型的二进制流参数
- 在
x-google-backend配置段添加disable_request_transcoding: true,关闭网关的自动请求转码逻辑,让网关直接透传原始multipart请求流到后端,不做结构化解析
修改后的/upload接口配置片段如下:
paths: /upload: post: summary: uploads a file. consumes: - multipart/form-data operationId: uploadFile parameters: - in: body name: file description: The file to upload. required: true schema: type: string format: binary responses: '200': description: upload successful x-google-backend: address: https://XXXXX.XXXXX path_translation: APPEND_PATH_TO_ADDRESS disable_request_transcoding: true
其余全局配置(安全定义、协议配置等)不需要改动,修改后的配置既可以通过Swagger编辑器校验,也可以正常被gcloud命令解析创建API配置。
注意:如果接口需要同时上传其他普通表单字段,不需要在parameters中额外声明,关闭转码后整个multipart/form-data请求会原样发送到后端,由后端服务自行解析表单内容即可。
内容的提问来源于stack exchange,提问作者Dennis Cieplik

