What could be causing the error "http: body field path 'foo' must be a non-repeated message" when deploying the configuration to GCP API Gateway with the following api-spec.yaml?
I've read documentation swagger 2.0 and I think there's no issue here. I check through swagger editor to check if there is any error but no error regarding error mentioned above.
swagger: '2.0'
info:
title: API Gateway
version: 1.0.0
description: API Gateway
schemes:
- https
produces:
- application/json
securityDefinitions:
firebase:
scopes: {}
authorizationUrl: ''
flow: implicit
type: oauth2
x-google-issuer: 'https://securetoken.google.com/project-id'
x-google-jwks_uri: 'https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com'
paths:
'/v1/events/{id}/tickets':
get:
produces:
- application/json
parameters:
- in: path
name: id
required: true
type: string
responses:
'200':
description: ''
schema:
items:
properties:
description:
type: string
donationPurpose:
type: string
endDate:
format: date-time
type: string
endTime:
type: string
eventId:
type: string
freeTicketType:
enum:
- donation
- infaq
- none
type: string
id:
type: string
name:
type: string
price:
type: number
startDate:
format: date-time
type: string
startTime:
type: string
totalAvailableTickets:
type: number
totalTickets:
type: number
type:
enum:
- free
- paid
type: string
required:
- id
- eventId
- name
- description
- type
- freeTicketType
- donationPurpose
- totalAvailableTickets
- totalTickets
- price
- startDate
- endDate
- startTime
- endTime
type: object
type: array
security:
- firebase: []
tags:
- events
operationId: EventController_getTicketsByEvent
summary: Get event tickets
x-google-backend:
address: 'https://backend-et.a.run.app/v1/events/{id}/tickets'
post:
consumes:
- application/json
parameters:
- in: path
name: id
required: true
type: string
- in: body
name: tikets
required: true
schema:
items:
type: string
type: array
responses:
'200':
description: ''
security:
- firebase: []
tags:
- events
operationId: EventController_createTicket
summary: Create event tickets
x-google-backend:
address: 'https://backend-et.a.run.app/v1/events/{id}/tickets'
put:
consumes:
- application/json
produces:
- application/json
parameters:
- in: path
name: id
required: true
type: string
- in: body
name: updateTickets
required: true
schema:
items:
type: string
type: array
responses:
'200':
description: ''
'404':
description: ''
schema:
properties:
error:
properties:
data:
type: object
details:
type: object
errorCode:
type: number
errorName:
type: string
localizedMessage:
type: string
message:
type: string
path:
type: string
requestId:
type: string
status:
type: string
timestamp:
type: string
required:
- status
- errorCode
- message
- errorName
- details
- path
- requestId
- timestamp
- data
type: object
required:
- error
type: object
security:
- firebase: []
tags:
- events
operationId: EventController_updateTicket
summary: Update event tickets
x-google-backend:
address: 'https://backend-et.a.run.app/v1/events/{id}/tickets'
Explanation why it is happening? What should my yaml looks like?
I solved it but forgot what caused the error. I remember that the message error is useless, caused by different reasons. However, I still have my own script to generate spec from openapi3 to swagger2 with no issues.
const fs = require("fs");
const path = require("path");
const yaml = require("js-yaml");
const minimist = require("minimist");
const TEMP_DIR = path.join(__dirname, "../../tmp");
// Create the temp directory if it doesn't exist.
if (!fs.existsSync(TEMP_DIR)) {
fs.mkdirSync(TEMP_DIR);
}
const TEMP_SWAGGER_FILE = path.join(TEMP_DIR, "swagger.yaml");
// Use args --source <path to swagger spec> --backend <backend address> --output <path to output file>
// read args source, backend, output using minimist
const args = minimist(process.argv.slice(2), {
string: ["source", "backend", "output"],
alias: { s: "source", b: "backend", o: "output" },
default: {
source: path.join(__dirname, "../../swagger.yaml"),
backend: "https://your-backend-here",
output: path.join(__dirname, "../../api.yaml"),
},
});
// Get the Swagger spec location from args or use the default. const swaggerSpecPath = args['source'];
// Convert the openapi spec to swagger spec 2.0 format using api-spec-converter
const apiSpecConverter = require("api-spec-converter");
apiSpecConverter
.convert({ from: "openapi_3", to: "swagger_2", source: swaggerSpecPath })
.then(function (result) {
result.fillMissing();
return result.validate().then(function (r) {
if (r.errors) return console.error(JSON.stringify(r.errors, null, 2));
if (r.warnings) return console.error(JSON.stringify(r.warnings, null, 2));
// Write the swagger spec to the temp directory.
fs.writeFileSync(TEMP_SWAGGER_FILE, result.stringify({ syntax: "yaml" }));
});
})
.then(() => {
// Get x-google-backend address from args or use the default. const backendAddress = args['backend'];
// Load the Swagger spec from the file system.
const swaggerSpec = yaml.load(fs.readFileSync(TEMP_SWAGGER_FILE, "utf8"));
// Extract the paths from the Swagger spec.
const paths = swaggerSpec.paths;
// Generate the API spec.
const apiSpec = {
swagger: "2.0",
info: {
title: "API Gateway",
version: "1.0.0",
description: "API Gateway",
},
schemes: ["https"],
produces: ["application/json"],
securityDefinitions: {
bearer: {
authorizationUrl: "",
flow: "implicit",
type: "oauth2",
"x-google-issuer": "https://securetoken.google.com/qalboo-staging",
"x-google-jwks_uri":
"https://www.googleapis.com/service_accounts/v1/metadata/x509/securetoken@system.gserviceaccount.com",
},
},
paths: {},
definitions: swaggerSpec.definitions,
tags: swaggerSpec.tags,
};
// Iterate over the paths.
for (const path in paths) {
// Get the path definition.
const pathDef = paths[path];
// Iterate over the methods.
for (const method in pathDef) {
// Get the method definition.
const methodDef = pathDef[method];
methodDef["x-google-backend"] = {
address: `${backendAddress}${path}`,
};
// // check if the method has a security definition
// if (!methodDef.security || methodDef.security.length === 0) {
// // Add the security definition to the method definition.
// methodDef.security = [
// {
// bearer: [],
// },
// ];
// }
pathDef[method] = methodDef;
}
// Add the API spec path to the API spec.
apiSpec.paths[path] = pathDef;
}
// Write the API spec to the file system.
console.info(`Writing API spec to ${args["output"]}`);
fs.writeFileSync(args["output"], yaml.dump(apiSpec));
});