2

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

jeffez
  • 185
  • 1
  • 12
  • Can you show the code for your test demo? – brian d foy Apr 01 '20 at 03:28
  • I have now added all my demo code to my post. Thanks – jeffez Apr 01 '20 at 04:47
  • Looks like the script at `/usr/local/share/perl5/JSON/Validator.pm` does not support OpenAPI 3.0. Maybe it only supports OpenAPI 2.0? – Helen Apr 01 '20 at 06:29
  • yes, the v3 support in in active development as mentioned in there doc. From the error message it looks like some issue with 'components', 'openapi' and 'servers' tag in your yaml. Are you using the current version of the plugin? I can see a test case https://metacpan.org/source/JHTHORSEN/Mojolicious-Plugin-OpenAPI-3.31/t/v3-defaults.t where they are testing V3 and its working. You can check it for reference – rai-gaurav Apr 01 '20 at 19:29
  • The test case in the link you provided passed testing when i run `prove -l t` i did notice it's using `Mojolicious::Lite` unlike my demo though. I am not sure if that matters or not. That said i was considering using the Lite version as it looks allot simpler to use but this is for a large production api so i am still researching if it's suited. – jeffez Apr 01 '20 at 22:44
  • This is what i have installed and they are all currently up to date `Mojolicious::Plugin::OpenAPI` `OpenAPI::Client` `YAML::XS` – jeffez Apr 01 '20 at 22:48
  • One clue is that if i deliberately put in a made up non supported property `nonsense` in my yaml, the error message won't complain about 'components', 'openapi' and 'servers' and instead just lists the bad one i put in. `Properties not allowed: nonsense.` – jeffez Apr 01 '20 at 22:58
  • I have just pasted the yaml on https://editor.swagger.io/. You can check it also for the validity of your yaml. Got an error 'Semantic error - at paths./pets.get.requestBody GET operations cannot have a requestBody'. Removing it makes the yaml valid. I wonder whether this is the actual problem. – rai-gaurav Apr 02 '20 at 04:39
  • Interesting. You are are right, it's not even possible for a get request to have a body. Sadly correcting this didn't fix the problem and i am still seeing the same error. – jeffez Apr 03 '20 at 06:42
  • 1
    I have edited my post putting in a minimal demo example, which works with V2 but switching to V3 yaml causes the error. – jeffez Apr 21 '20 at 00:19
  • Should i just delete the first demo from my OP? The newer demo i have is really easy to replicate the problem but i think it's just lost in now a very lengthy OP. – jeffez Apr 22 '20 at 05:11

0 Answers0