@@ -, +, @@ swagger.min.json --- Koha/REST/V1.pm | 48 +++++++++++++++++ t/api/v1/minifier.t | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 195 insertions(+) create mode 100644 t/api/v1/minifier.t --- a/Koha/REST/V1.pm +++ a/Koha/REST/V1.pm @@ -18,8 +18,11 @@ package Koha::REST::V1; use Modern::Perl; use Mojo::Base 'Mojolicious'; +use File::Find::Rule; + use C4::Auth qw( check_cookie_auth get_session ); use C4::Context; +use Koha::Logger; use Koha::Patrons; sub startup { @@ -43,6 +46,8 @@ sub startup { # Force charset=utf8 in Content-Type header for JSON responses $self->types->type(json => 'application/json; charset=utf8'); + $self->minifySwagger(); + my $secret_passphrase = C4::Context->config('api_secret_passphrase'); if ($secret_passphrase) { $self->secrets([$secret_passphrase]); @@ -54,4 +59,47 @@ sub startup { }); } +sub minifySwagger { + my ($self, $swaggerPath) = @_; + + $swaggerPath = C4::Context->config("intranetdir").'/api/v1/' unless $swaggerPath; + my $pathToMinifier = $swaggerPath.'minifySwagger.pl'; + my $pathToSwaggerJson = $swaggerPath.'swagger.json'; + my $pathToSwaggerMinJson = $swaggerPath.'swagger.min.json'; + + if (_isMinificationRequired($swaggerPath, $pathToSwaggerJson, + $pathToSwaggerMinJson)) { + if (-e $pathToSwaggerMinJson && not -w $pathToSwaggerMinJson + || not -e $pathToSwaggerMinJson && not -w $swaggerPath) { + my $user = $ENV{LOGNAME} || $ENV{USER} || getpwuid($<); + my $logger = Koha::Logger->get({ interface => 'intranet' }); + $logger->warn("User $user cannot write to $pathToSwaggerMinJson. ". + "Please give $user write-permission to $pathToSwaggerMinJson ". + "or run $pathToMinifier manually."); + return; + } + my $output = `perl $pathToMinifier -s $pathToSwaggerJson -d $pathToSwaggerMinJson`; + if ($output) { + die $output; + } + } +} + +sub _isMinificationRequired { + my ($swaggerPath, $pathToSwaggerJson, $pathToSwaggerMinJson) = @_; + + return 1 unless -e $pathToSwaggerJson; # swagger.json exists? + return 1 unless -e $pathToSwaggerMinJson; # swagger.min.json exists? + my $latestModification = -C $pathToSwaggerJson; + + # Recursively go through specification files and find the last modified + my $lastModifiedFile; + my @files = File::Find::Rule->file()->name("*.json")->in($swaggerPath); + foreach my $file (@files){ + next if $file eq $pathToSwaggerMinJson; + $latestModification = -C $file if -C $file < $latestModification; + } + return 1 if $latestModification < -C $pathToSwaggerMinJson; # compare modification time +} + 1; --- a/t/api/v1/minifier.t +++ a/t/api/v1/minifier.t @@ -0,0 +1,147 @@ +#!/usr/bin/env perl + +# Copyright (C) 2016 KohaSuomi +# +# This file is part of Koha. +# +# Koha is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# Koha is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with Koha; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; + +use File::Copy qw/copy/; +use File::Temp; +use File::Path qw/make_path rmtree/; + +use Test::More tests => 13; + +use C4::Context; +use Koha::REST::V1; + +my $oldSwagger_title = "Swagger Sample App"; +my $newSwagger_title = "Koha REST API"; + +# Construct an example swagger.json +my $swaggerJsonTest = +qq ({ + "swagger": "2.0", + "info": { + "title": "$oldSwagger_title", + "version": "1" + }, + "paths": {}, + "definitions": {}, + "parameters": {} +}); + +my $swaggerJsonTestModified = +qq ({ + "swagger": "2.0", + "info": { + "title": "$newSwagger_title", + "version": "1" + }, + "paths": {}, + "definitions": { + "\$ref": "definitions.json" + }, + "parameters": {} +}); +my $swaggerJsonTestDefinitions = +qq ({ + "test": { + "type": "object", + "properties": { + "id": { + "type": "integer", + "description": "test integer" + } + } + } +}); + +# Path containing actual swagger specification files +my $real_swaggerPath = C4::Context->config("intranetdir").'/api/v1/'; + +# Create a tmp directory where we can modify swagger.json +my $swaggerPath = File::Temp->newdir()."/"; +make_path($swaggerPath); + +# Copy minifySwagger.pl to this location +copy($real_swaggerPath.'minifySwagger.pl', $swaggerPath); + +my $pathToMinifier = $swaggerPath.'minifySwagger.pl'; +my $pathToSwaggerJson = $swaggerPath.'swagger.json'; +my $pathToSwaggerDefinitionsJson = $swaggerPath.'definitions.json'; +my $pathToSwaggerMinJson = $swaggerPath.'swagger.min.json'; + +is(-e $pathToSwaggerJson, undef, "swagger.json does not yet exist"); +is(-e $pathToSwaggerMinJson, undef, "swagger.min.json does not yet exist"); +is(-e $pathToSwaggerDefinitionsJson, undef, "definitions.json does not yet exist"); +ok(-w $swaggerPath, "$swaggerPath is writeable"); + +my $exists = -e $pathToSwaggerJson; +# Create swagger.json test file +open my $fh, '>', $pathToSwaggerJson; +print $fh $swaggerJsonTest; +close $fh; + +ok(-e $pathToSwaggerJson, "swagger.json created!"); + +Koha::REST::V1::minifySwagger(undef, $swaggerPath); +ok(-e $pathToSwaggerMinJson, "swagger.min.json created!"); +my $lastmodified = -C $pathToSwaggerMinJson; + +# Read swagger.min.json +require Swagger2; +my $swaggerMin = Swagger2->new($pathToSwaggerMinJson); +$swaggerMin = $swaggerMin->expand; +my $oldSwaggerTitle = $swaggerMin->{'api_spec'}->{'data'}->{'info'}->{'title'}; +is($oldSwaggerTitle, $oldSwagger_title, "old title found"); + +# Modify swagger.json +sleep(1); # make sure modification time differs from swagger.min.json +open $fh, '>', $pathToSwaggerJson; +print $fh $swaggerJsonTestModified; +close $fh; + +# Add definitions.json +sleep(1); # make sure modification time differs from swagger.min.json +open $fh, '>', $pathToSwaggerDefinitionsJson; +print $fh $swaggerJsonTestDefinitions; +close $fh; + +ok(-e $pathToSwaggerDefinitionsJson, "definitions.json created!"); + +Koha::REST::V1::minifySwagger(undef, $swaggerPath); + +ok($lastmodified > -C $pathToSwaggerMinJson, + "swagger.min.json modified after editing swagger.json"); +$lastmodified = -C $pathToSwaggerMinJson; + +# Re-read swagger.min.json +$swaggerMin = Swagger2->new($pathToSwaggerMinJson); +$swaggerMin = $swaggerMin->expand; +my $newSwaggerTitle = $swaggerMin->{'api_spec'}->{'data'}->{'info'}->{'title'}; +is($newSwaggerTitle, $newSwagger_title, "new title found"); # was minified +is($swaggerMin->{'api_spec'}->{'data'}->{'definitions'} + ->{'test'}->{'properties'}->{'id'}->{'description'}, + "test integer", "test integer found!"); + +Koha::REST::V1::minifySwagger(undef, $swaggerPath); +ok($lastmodified == -C $pathToSwaggerMinJson, + "swagger.min.json not modified because no modifications to swagger.json"); + +# Cleanup +rmtree($swaggerPath) if $swaggerPath ne $real_swaggerPath; +is(-e $swaggerPath, undef, "tmp files deleted"); --