From ac5ab3a4c9831479336104625569984a6593c3ab Mon Sep 17 00:00:00 2001 From: Ere Maijala Date: Thu, 20 Feb 2020 16:17:58 +0200 Subject: [PATCH] Bug 24700: Avoid validating REST API spec multiple times This patch changes the spec loading so that it is fully loaded and merged with any plugin routes before validation. The individual parts are separately validated only if the resulting complete spec is invalid. Note: the OpenAPI plugin validates the spec given to it, so normally no manual validation is necessary. Test plan: 1. prove -v t/db_dependent/Koha/REST/* 2. prove -v t/db_dependent/api/v1/* Sponsored-by: The National Library of Finland Signed-off-by: Martin Renvoize --- Koha/REST/Plugin/PluginRoutes.pm | 2 + Koha/REST/V1.pm | 82 ++++++++++++++++++++++---------- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/Koha/REST/Plugin/PluginRoutes.pm b/Koha/REST/Plugin/PluginRoutes.pm index 273d5df708..e993b563d0 100644 --- a/Koha/REST/Plugin/PluginRoutes.pm +++ b/Koha/REST/Plugin/PluginRoutes.pm @@ -70,6 +70,8 @@ sub register { sub inject_routes { my ( $spec, $plugin, $validator ) = @_; + return merge_spec( $spec, $plugin ) unless $validator; + return try { my $backup_spec = merge_spec( clone($spec), $plugin ); diff --git a/Koha/REST/V1.pm b/Koha/REST/V1.pm index b1f4657d4a..c0cc2fa8f5 100644 --- a/Koha/REST/V1.pm +++ b/Koha/REST/V1.pm @@ -21,6 +21,7 @@ use Mojo::Base 'Mojolicious'; use C4::Context; use JSON::Validator::OpenAPI::Mojolicious; +use Try::Tiny; =head1 NAME @@ -58,33 +59,66 @@ sub startup { } my $validator = JSON::Validator::OpenAPI::Mojolicious->new; - $validator->load_and_validate_schema( - $self->home->rel_file("api/v1/swagger/swagger.json"), - { - allow_invalid_ref => 1, - } - ); push @{$self->routes->namespaces}, 'Koha::Plugin'; - my $spec = $validator->schema->data; - $self->plugin( - 'Koha::REST::Plugin::PluginRoutes' => { - spec => $spec, - validator => $validator - } - ); - - $self->plugin( - OpenAPI => { - spec => $spec, - route => $self->routes->under('/api/v1')->to('Auth#under'), - allow_invalid_ref => - 1, # required by our spec because $ref directly under - # Paths-, Parameters-, Definitions- & Info-object - # is not allowed by the OpenAPI specification. - } - ); + # Try to load and merge all schemas first and validate the result just once. + my $spec; + try { + $spec = $validator->bundle( + { + replace => 1, + schema => $self->home->rel_file("api/v1/swagger/swagger.json") + } + ); + + $self->plugin( + 'Koha::REST::Plugin::PluginRoutes' => { + spec => $spec, + validator => undef + } + ); + + $self->plugin( + OpenAPI => { + spec => $spec, + route => $self->routes->under('/api/v1')->to('Auth#under'), + allow_invalid_ref => + 1, # required by our spec because $ref directly under + # Paths-, Parameters-, Definitions- & Info-object + # is not allowed by the OpenAPI specification. + } + ); + } + catch { + # Validation of the complete spec failed. Resort to validation one-by-one + # to catch bad ones. + $validator->load_and_validate_schema( + $self->home->rel_file("api/v1/swagger/swagger.json"), + { + allow_invalid_ref => 1, + } + ); + + $spec = $validator->schema->data; + $self->plugin( + 'Koha::REST::Plugin::PluginRoutes' => { + spec => $spec, + validator => $validator + } + ); + + $self->plugin( + OpenAPI => { + spec => $spec, + route => $self->routes->under('/api/v1')->to('Auth#under'), + allow_invalid_ref => + 1, # required by our spec because $ref directly under + # Paths-, Parameters-, Definitions- & Info-object + # is not allowed by the OpenAPI specification. + } + ); + }; $self->plugin( 'Koha::REST::Plugin::Pagination' ); $self->plugin( 'Koha::REST::Plugin::Query' ); -- 2.20.1