go-restful-openapi $refs must reference a valid location in the document - go

I'm using go-restful in combination with go-restful-openapi to generate my swagger doc automatically. However, on testing the tool with the swagger-editor, I get the following error:
$refs must reference a valid location in the document
struct
type Users struct {
# uuid imported from github.com/google/uuid#v1.2.0
RelatedUsers []uuid.UUID `json:"relatedIds" validate:"required"`
}
generated swagger snippet
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedIds": {
"type": "array",
"$ref": "#/definitions/uuid.UUID" #this line returns an error
}
}
}
}
Here's the swagger config:
swaggerConfig := restfulspec.Config{
WebServices: restfulContainer.RegisteredWebServices(),
APIPath: "/swagger.json",
PostBuildSwaggerObjectHandler: func(swo *spec.Swagger) {
swo.Info = &spec.Info{
InfoProps: spec.InfoProps{
Title: "User Service",
Description: "An example service for stackoverflow",
Version: "1.0.0",
},
}
},
}
NOTE: If I replace the lines above in the swagger editor as follows the error disappears, however, I couldn't figure out how to configure swagger to do so automatically
"Users": {
"required": [
"relatedIds"
],
"properties": {
"relatedUsers": {
type: array
items:
type: "string"
format: "uuid"
}
}
}
}

Just in case someone is running into this issue: go-restful-openapi cannot resolve imported custom types. To solve this issue add the type to the definitions
swo.Definitions["uuid.UUID"] = spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "uuid",
},
}

Related

OpenAPI definition does not include child objects in doc JSON

I am in the process of taking a look into polymorphism for OpenAPI. More specifically I am in trying out the example with the Pet, Cat and Dog found here using this portion of yaml:
components:
schemas:
Pet:
type: object
discriminator:
propertyName: petType
properties:
name:
type: string
petType:
type: string
required:
- name
- petType
Cat: ## "Cat" will be used as the discriminator value
description: A representation of a cat
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
huntingSkill:
type: string
description: The measured skill for hunting
enum:
- clueless
- lazy
- adventurous
- aggressive
required:
- huntingSkill
Dog: ## "Dog" will be used as the discriminator value
description: A representation of a dog
allOf:
- $ref: '#/components/schemas/Pet'
- type: object
properties:
packSize:
type: integer
format: int32
description: the size of the pack the dog is from
default: 0
minimum: 0
required:
- packSize
Using this I am able to create the DTOs using the OpenAPI spring generator correctly and with a proper structure. Now all seem fine up to this step but when I serve the SwaggerUI using the Spring's dependencies the generated subclasses are not served as part of the schema. For instance, when I fetch the JSON definition of this I get the following:
{
"openapi": "3.0.1",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [{
"url": "http://localhost:8080",
"description": "Generated server url"
}],
"tags": [{
"name": "Test",
"description": "the Test API"
}],
"paths": {
"/test": {
"get": {
"tags": ["Test"],
"operationId": "testGet",
"responses": {
"200": {
"description": "A list of search results",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Pet": {
"required": ["name", "petType"],
"type": "object",
"properties": {
"name": {
"type": "string"
},
"petType": {
"type": "string"
}
},
"discriminator": {
"propertyName": "petType"
}
}
}
}
}
As we can see there is no Cat or Dog definition. This in turn makes consumers of this JSON definition to incorrectly generate their code.
My question is thus, what needs to be done in order to get this working properly. For reference I am using OpenAPI 3.0.1, SpringBoot 3.0 and the following swagger and springdoc dependencies:
implementation 'org.openapitools:jackson-databind-nullable:0.2.4'
implementation 'io.swagger.core.v3:swagger-annotations:2.2.7'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.0'

Using AJV in Postman seems to ignore nesting/children

I'm trying to validate JSON response messages according to schema.
But as soon as an attribute has the type "array" or "object", AJV seems to ignore them and does not see the nested attribute within that object or array.
I started trying to break up the schema into multiple smaller ones so all objects/arrays are covered, but this is a tedious task and I'm hoping I'm just using AJV incorrectly.
Example schema (simplified):
{
"type": "object",
"required": [
"MainThing"
],
"properties": {
"MainThing": {
"type": "string",
"description": "Some kind of string.",
"example": "This is some kind of string."
},
"NestedThing": {
"type": "object",
"required": [
"NestedAttribute"
],
"properties": {
"NestedAttribute": {
"type": "String",
"description": "A nested string.",
"example": "This is a nested string"
}
}
}
}
}
If I change the NestedAttribute to an Integer instead of a String, the schema validation in Postman will tell me the response is valid against the schema. While it's not, because the response will contain a NestedAttribute which is a String value.
The following response would be deemed valid, while it's not:
{
"MainThing": "The main thing",
"NestedThing": {
"NestedAttribute": 12345
}
}
My Postman testcode:
var Ajv = require('ajv'),
ajv = new Ajv({logger: console}),
schema = JSON.parse(pm.variables.get("THIS_IS_MY_AWESOME_SCHEMA"));
pm.test('My schema is valid', function() {
var data = pm.response.json();
pm.expect(ajv.validate(schema, data)).to.be.true;
});
If anyone can point me in the right direction, that would be greatly appreciated!

Swagger is not working with JSONAPI - Golang

Swagger is not creating example with expected format: How to use swagger with json-api golang
Input struct:
type example struct {
ID string `jsonapi:"primary,examples"`
value string `jsonapi:"attr,value"`
}
Expected format:
{
"data":[
{
"type": "examples",
"id": "01FDG693F2MS0ZCEW925MZ7BAA",
"attributes": {
"value": "xxx.xxx.xxx.xxx",
}
}
],
}

How to properly set and query siteMetadata in Gatsbyjs?

The issue I am running into is that when I set a key-value pair in the gatsby-config.js file I am not able to see the data inside GraphiQL. I am following the documentation and using keys that are used in the example code. See here for the documentation: https://www.gatsbyjs.org/docs/gatsby-config/#sitemetadata
Here is my gatsby-config.js file:
module.exports = {
siteMetadata: {
title: `My Photography Site`,
description: `Just the best`,
},
plugins: [
`gatsby-plugin-emotion`,
`gatsby-transformer-remark`,
{
resolve: `gatsby-source-filesystem`,
options: {
name: `src`,
path: `${__dirname}/src/`,
},
},
{
resolve: `gatsby-plugin-typography`,
options: {
pathToConfigModule: `src/utils/typography`,
},
},
],
}
Here is my GraphiQL query (after restarting the development server to reload the gatsby-config.js file):
query SiteQuery {
site {
siteMetadata {
title
description
}
}
}
Expected results from the GraphiQL:
{
"data": {
"site": {
"siteMetadata": {
"title": "My Photography Site",
"description": "Just the best"
}
}
}
}
Here is the actual result of the GraphiQL:
{
"errors": [
{
"message": "Cannot query field \"description\" on type \"SiteSiteMetadata\".",
"locations": [
{
"line": 5,
"column": 7
}
],
"stack": [
"GraphQLError: Cannot query field \"description\" on type \"SiteSiteMetadata\".",
" at Object.Field (/mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/graphql/validation/rules/FieldsOnCorrectType.js:64:31)",
" at Object.enter (/mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/graphql/language/visitor.js:334:29)",
" at Object.enter (/mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/graphql/language/visitor.js:385:25)",
" at visit (/mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/graphql/language/visitor.js:252:26)",
" at validate (/mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/graphql/validation/validate.js:63:22)",
" at /mnt/c/Users/Spencer/dev/gatsbyjs/hello-world/node_modules/express-graphql/dist/index.js:154:52",
" at processTicksAndRejections (internal/process/task_queues.js:89:5)"
]
}
]
}
What is odd is that I was able to successfully create a custom key-value pair before and it worked fine. I had a key of tagLine and a value of Panda Site. The normal title key worked as well.
Here are the software versions I am using:
gatsby: 2.5.12
node: v12.1.0
npm: 6.9.0
I am running using Windows Subsystem for Linux (WSL). Let me know if you would like any other config files, including package.json.

Confusion creating swagger.json file from proto file

I've created a proto file with all the necessary messages and rpc functions for a REST webservice I intend to generate. Using the protoc-gen-swagger plugin I've managed to compile that proto file into a swagger.json file and all seems well, except for two things, which I can't seem to work out.
All the definitions in the swagger.json file has the name of my proto file's package prefixed onto them. Is there a way to get rid of this?
All of the fields of my messages are "optional". They're not specified explicitly as such but they're not specified to be "required" which, by definition, makes them optional. Proto3 no longer supports required/optional/repeating but even if I use Proto2 and add those keywords, it doesn't seem to affect the swagger.json ouput. How do I specifiy in my proto file that a field is required such that protoc-gen-swagger will add the required section to the json output?
Here is a sample of a very basic proto file:
webservice.proto
syntax = "proto3";
package mypackage;
import "google/api/annotations.proto";
service MyAPIWebService {
rpc MyFunc (MyMessage) returns (MyResponse) {
option (google.api.http) = {
post: "/message"
body: "*"
};
}
}
message MyMessage {
string MyString = 1;
int64 MyInt = 2;
}
message MyResponse {
string MyString = 1;
}
This is then compiled into a swagger.json file with the following command:
protoc -I. -I"%GOPATH%/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis" --swagger_out=logtostderr=true:. webservice.proto
which yields the following output:
webservice.swagger.json
{
"swagger": "2.0",
"info": {
"title": "webservice.proto",
"version": "version not set"
},
"schemes": [
"http",
"https"
],
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"paths": {
"/message": {
"post": {
"operationId": "MyFunc",
"responses": {
"200": {
"description": "",
"schema": {
"$ref": "#/definitions/mypackageMyResponse"
}
}
},
"parameters": [
{
"name": "body",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/mypackageMyMessage"
}
}
],
"tags": [
"MyAPIWebService"
]
}
}
},
"definitions": {
"mypackageMyMessage": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
},
"MyInt": {
"type": "string",
"format": "int64"
}
}
},
"mypackageMyResponse": {
"type": "object",
"properties": {
"MyString": {
"type": "string"
}
}
}
}
}
Notice how MyMessage and MyResponse in the proto file translates to mypackageMyMessage and mypackageMyResponse in the json file.
If I wanted, for instance, MyMessage:MyString to be required, I'd have to add a section to the "mypackageMyMessage" section in "definitions" that looks like this:
"required":[
"MyString"
]
I would definitely prefer if there was a way I could specify that in the proto file already so that I don't have to manually edit the json file every time I compile it.
Posting here for anyone else who comes across this question looking for the same information.
UPDATE
This is where the code defines how definitions are created.
https://github.com/grpc-ecosystem/grpc-gateway/blob/master/protoc-gen-swagger/genswagger/template.go#L859
This is how you can denote fields as required -- add a custom option to your message definition:
message MyMessage {
option (grpc.gateway.protoc_gen_swagger.options.openapiv2_schema) = {
json_schema: {
title: "MyMessage"
description: "Does something neat"
required: ["MyString"]
}
};
string MyString = 1;
int64 MyInt = 2;
}
Your prefix mypackage is a part of namespacing in .proto file. It is coming from line: package mypackage; delete this line and regenerate json

Resources