Generated v3 spec generates validation errors on editor.swagger.io
HEM42 opened this issue · comments
Hi,
I noticed that the generated spec generates validation errors on editor.swagger.io, using your own example converted to OpenAPIv3, see code at the end
There is multiple problems, A few i would be able to submit a PR on :
Definitions belongs under {components}{schemas}, not responses.
Also swagger.io complains about the extra basePath and host in the spec
diff --git a/lib/Mojolicious/Plugin/OpenAPI.pm b/lib/Mojolicious/Plugin/OpenAPI.pm
index 8df0dce..96d885c 100644
--- a/lib/Mojolicious/Plugin/OpenAPI.pm
+++ b/lib/Mojolicious/Plugin/OpenAPI.pm
@@ -72,12 +72,12 @@ sub _add_default_response {
my $ref
= $self->validator->version ge '3'
- ? ($schema_data->{components}{responses}{$name} ||= $self->_default_schema)
+ ? ($schema_data->{components}{schemas}{$name} ||= $self->_default_schema)
: ($schema_data->{definitions}{$name} ||= $self->_default_schema);
my %schema
= $self->validator->version ge '3'
- ? ('$ref' => "#/components/responses/$name")
+ ? ('$ref' => "#/components/schemas/$name")
: ('$ref' => "#/definitions/$name");
tie %schema, 'JSON::Validator::Ref', $ref, $schema{'$ref'}, $schema{'$ref'};
diff --git a/lib/Mojolicious/Plugin/OpenAPI/SpecRenderer.pm b/lib/Mojolicious/Plugin/OpenAPI/SpecRenderer.pm
index 24db353..f2c868c 100644
--- a/lib/Mojolicious/Plugin/OpenAPI/SpecRenderer.pm
+++ b/lib/Mojolicious/Plugin/OpenAPI/SpecRenderer.pm
@@ -82,8 +82,12 @@ sub _render_spec {
my $format = $c->stash('format') || 'json';
my $spec = $self->{bundled} ||= $self->validator->bundle;
- local $spec->{basePath} = $c->url_for($spec->{basePath});
- local $spec->{host} = $c->req->url->to_abs->host_port;
+ if ( $self->validator->version ge '3' ) {
+ delete $spec->{basePath};
+ } else {
+ local $spec->{dbasePath} = $c->url_for($spec->{basePath});
+ local $spec->{host} = $c->req->url->to_abs->host_port;
+ }
return $c->render(json => $spec) unless $format eq 'html';
return $c->render(
But the last issue here, I was not able to fix, and I hope you can assist on this.
The default responses, even if the ref is added correctly at line 83 in lib/Mojolicious/Plugin/OpenAPI.pm
tie %schema, 'JSON::Validator::Ref', $ref, $schema{'$ref'}, $schema{'$ref'};
Its still rendered as following, under definitions:, which dont belong in v3 spec
"definitions": {
"__components_responses_DefaultResponse": {
"properties": {
"errors": {
"items": {
"properties": {
"message": {
"type": "string"
},
"path": {
"type": "string"
}
},
"required": [
"message"
],
"type": "object"
},
"type": "array"
}
},
"required": [
"errors"
],
"type": "object"
}
},
Following is the code used
use Mojolicious::Lite;
# Will be moved under "basePath", resulting in "POST /api/echo"
post "/echo" => sub {
my $c = shift->openapi->valid_input or return;
my $data = {body => $c->validation->param("body")};
$c->render(openapi => $data);
}, "echo";
# Load specification and start web server
plugin OpenAPI => {url => "data:///spec.json", schema => "v3"};
app->start;
__DATA__
@@ spec.json
{
"openapi": "3.0.0",
"info": {
"title": "Echo Service",
"version": "0.8"
},
"paths": {
"/echo": {
"post": {
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
},
"responses": {
"200": {
"description": "Echo response",
"content": {
"application/json": {
"schema": {
"type": "object"
}
}
}
}
},
"x-mojo-name": "echo"
}
}
},
"servers": [
{
"url": "/api"
}
]
}
Thanks for reporting in!
...A few i would be able to submit a PR on
Yes, please do submit a PR, with updated/new tests. (Please note that the PR should also be run through perltidy)
Definitions belongs under ./components/schemas, not ./responses.
Could you please provide a reference to the documentation? It seems very random that I would place it under "responses". Or would you happen to know if the spec has changed? If so, I should probably update the bundled spec in JSON::Validator
extra basePath and host in the spec
Aiai. Not cool. Please fix that in the PR as well.
The default responses, ..., Its still rendered as following, under definitions:, which dont belong in
v3 spec
Is "definitions" not allowed in the v3 spec? This is an issue with how JSON::Validator works, so it probably needs fixing in both modules.
I'm sorry I haven't paid much attention to the v3 spec. The reason is simply that I don't use it myself. Any contribution to make it work better is greatly appreciated!
Thanks for reporting in!
...A few i would be able to submit a PR on
Yes, please do submit a PR, with updated/new tests. (Please note that the PR should also be run through perltidy)
extra basePath and host in the spec
Aiai. Not cool. Please fix that in the PR as well.
Will work on that
Definitions belongs under ./components/schemas, not ./responses.
Could you please provide a reference to the documentation? It seems very random that I would place it under "responses". Or would you happen to know if the spec has changed? If so, I should probably update the bundled spec in JSON::Validator
You are right in this, I should have read the spec (I simply converted my v2 spec, and I didn't pay attention.
So reponses is actual the correct placement, so no real issue here, now that I look at it, it complains about the structure, which I will try to fix as well.
The default responses, ..., Its still rendered as following, under definitions:, which dont belong in v3 spec
Is "definitions" not allowed in the v3 spec? This is an issue with how JSON::Validator works, so it probably needs fixing in both modules.I'm sorry I haven't paid much attention to the v3 spec. The reason is simply that I don't use it myself. Any contribution to make it work better is greatly appreciated!
Not sure that is not allowed. But its not a part fixed fields in the spec : https://swagger.io/specification/#oasObject
Since the responses is actually build in Mojolicious::Plugin::OpenAPI, but not used, since JSON::Validator creates the "definitions".
Since you mentioned JSON::Validator, I looked at it, and found this passage in the doc for bundle()
Used to create a new schema, where there are no "$ref" pointing to
external resources. This means that all the "$ref" that are found, will be
moved into the "definitions" key, in the returning $schema.
I guess its here the problem lies, that JSON::Validator also creates the "definitions", even if the $ref is #/components/responses/DefaultResponse
Im uncertain on how to fix that, but will have a look there as well. If you have a good idea on where exactly I could look
it comes in as
\ {
$ref "#/components/responses/DefaultResponse"
} (tied to JSON::Validator::Ref)
but comes out as
\ {
$ref "#/definitions/__components_responses_DefaultResponse"
} (tied to JSON::Validator::Ref)
I guess one difference from v2 to v3 is that the it went from simple structured hash (definitions names as keys), to a more complex structure with components, type, and then the actual "definition" as keys
Definitions belongs under ./components/schemas, not ./responses.
Could you please provide a reference to the documentation? It seems very random that I would place it under "responses". Or would you happen to know if the spec has changed? If so, I should probably update the bundled spec in JSON::Validator
You are right in this, I should have read the spec (I simply converted my v2 spec, and I didn't pay attention.
So reponses is actual the correct placement, so no real issue here, now that I look at it, it complains about the structure, which I will try to fix as well.
Worth mentioning, my initial assumption was right on this (wrong placement). The type of object you create for the response, is in fact a Schema object, have a look at
https://swagger.io/specification/#componentsObject
There is a Response object defined, but has a different structure.
Doesn't look like the spec has changed for this
So for a final change to make the ref paths generated correctly for v3, which the latest J::V release makes possible by overriding generate_definitions_path() in JSON::Validator::OpenAPI::Mojolicious
Im not quite what the right approach could be, both works for all tests; first one takes version into account, so no changes for version 2:
https://gist.github.com/HEM42/2f4d9cfbc67d451d0c543bb95a0bacc0
Second approach, handles both v2 and v3 in a similar fashion:
https://gist.github.com/HEM42/986d0ce0bf81a879c4e1cf3120b2c3ff
If one of these approaches can be agreed upon, Ill happy make the PR for it :)
#152 was merged, this issue can now be closed