I'm looking at creating an api using OpenAPI V3 in Perl with Mojolicious. Both OpenAPI and Mojolicious are new to me.
Mojolicious::Plugin::OpenAPI looks to be under active development with the the latest version 3.31 being released less than a day ago as of writing this.
I have a test demo i am working on and have overcome allot of problems but i am completely stuck on this error as it makes no sense saying properties in my open api spec are not allowed despite being within the openapi spec.
**EDIT - Here is a bare minimum example which works using OpenAPI V2 but if i convert the yaml file into V3 spec the error occurs. Both yaml files pass checks on https://editor.swagger.io/
App2_0.pm
package App2_0;
use Mojo::Base "Mojolicious";
sub startup {
my $self = shift;
$self->plugin("OpenAPI" => {url => $self->home->rel_file("api.yaml")});
}
1;
Echo.pm
package App2_0::Controller::Echo;
use Mojo::Base "Mojolicious::Controller";
sub index {
# Render back the same data you received
$self->render(openapi => $self->req->json);
}
1;
basic.t
use Mojo::Base -strict;
use Test::More;
use Test::Mojo;
my $t = Test::Mojo->new('App2_0');
$t->post_ok('/api/echo', '{"i":"work"}')->status_is(200)->json_is({i=>"work"});
done_testing();
api.yaml
swagger: '2.0'
info:
version: '1.0'
title: An API
basePath: "/api"
paths:
"/echo":
post:
x-mojo-to: "echo#index"
operationId: echo
parameters:
- in: body
name: body
schema:
type: object
responses:
200:
description: Echo response
schema:
type: object
api.yaml (same as above but in V3)
openapi: 3.0.2
info:
version: '1.0'
title: An API
servers:
- url: "/api"
paths:
"/echo":
post:
x-mojo-to: "echo#index"
operationId: echo
requestBody:
content:
application/json:
schema:
type: object
responses:
'200':
description: ech response
content:
application/json:
schema:
type: object
Running test with V2 yaml works
prove -l t
t/basic.t .. ok
All tests successful.
Result: PASS
The same test but using the V3 yaml fails
prove -l t
Invalid JSON specification HASH(0x4415710):
- /: Properties not allowed: openapi, servers. at /usr/local/share/perl5/JSON/Validator.pm line 159.
...
t/basic.t .. Dubious, test returned 255 (wstat 65280, 0xff00)
No subtests run
Test Summary Report
-------------------
t/basic.t (Wstat: 65280 Tests: 0 Failed: 0)
Non-zero exit status: 255
Parse errors: No plan found in TAP output
Result: FAIL
**END EDIT the rest is just my OP example which is now redundant
Invalid JSON specification HASH(0x3801f58): - /: Properties not allowed: components, openapi,
servers. at /usr/local/share/perl5/JSON/Validator.pm line 159.
This is my test demo openapi spec
myapi_y2.yaml
openapi: 3.0.2
info:
version: '1.0'
title: An API
servers:
- url: "/api"
paths:
"/pets":
get:
operationId: get_pets
x-mojo-name: get_pets
x-mojo-to: pet#list
summary: Finds pets in the system
parameters:
- in: query
name: age
schema:
type: integer
requestBody:
content:
application/json:
schema:
type: object
responses:
'200':
description: Pet response
content:
application/json:
schema:
type: object
properties:
pets:
type: array
items:
type: object
components:
schemas:
Pet:
type: object
required:
- id
- name
- age
properties:
id:
type: integer
format: int64
name:
type: string
age:
type: integer
format: int64
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
I have exhausted google and cannot find any info on why this is happening. Has anyone seen this or know why it happens?
Test demo code my_app2
#!/usr/bin/env perl
use strict;
use warnings;
use FindBin;
BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
use Mojolicious::Commands;
# Start command line interface for application
Mojolicious::Commands->start_app('MyApp2');
MyApp2.pm
package MyApp2;
use Mojo::Base "Mojolicious";
sub startup {
my $app = shift;
$app->plugin("OpenAPI" => {url => $app->home->rel_file("myapi_y2.yaml"), schema => 'v3'});
}
1;
Pet.pm
package MyApp2::Controller::Pet;
use Mojo::Base "Mojolicious::Controller";
sub list {
my $c = shift->openapi->valid_input or return;
my $age = $c->param("age");
my $body = $c->req->json;
# $output will be validated by the OpenAPI spec before rendered
my $output = {pets => [{name => "kit-e-cat"}]};
$c->render(openapi => $output);
}
1;
Thanks