From 6d69eebf74953a55c815f40757669effb58e1344 Mon Sep 17 00:00:00 2001 From: Irina Peshinskaya Date: Thu, 12 Apr 2018 09:12:28 +0200 Subject: [PATCH] TT#35538 Prepare API to faxes changes * Consider POST body not utf8 encoded, so encode "json" parameter * Allow empty body for multipart/form-data controlled by configuration as faxes took text from "json" part too. * Allow empty return from create, meaning asynchronous operations, like fax creation * Allow to skip hal validation through form. Can be used for collections without PUT and PATCH. Change-Id: If0d0e7cdc6abe53d76ad0b18568e93743040e90f --- lib/NGCP/Panel/Role/API.pm | 30 ++++++++++++++++++----------- lib/NGCP/Panel/Role/Entities.pm | 5 ++++- lib/NGCP/Panel/Role/EntitiesItem.pm | 4 ++++ 3 files changed, 27 insertions(+), 12 deletions(-) diff --git a/lib/NGCP/Panel/Role/API.pm b/lib/NGCP/Panel/Role/API.pm index 9516e67ff9..2d8b954dd6 100644 --- a/lib/NGCP/Panel/Role/API.pm +++ b/lib/NGCP/Panel/Role/API.pm @@ -17,6 +17,8 @@ use DateTime::Format::HTTP qw(); use DateTime::Format::RFC3339 qw(); use Types::Standard qw(InstanceOf); use Regexp::Common qw(delimited); # $RE{delimited} +use Encode qw( encode_utf8 ); + use HTTP::Headers::Util qw(split_header_words); use Data::Compare; use Data::HAL qw(); @@ -55,7 +57,7 @@ sub get_valid_data{ my ($json_raw,$json_decoded); if ($c->req->headers->content_type eq 'multipart/form-data') { return unless $self->require_uploads($c); - $json_raw = $c->req->param('json'); + $json_raw = encode_utf8($c->req->param('json')); } elsif ($c->req->headers->content_type eq 'application/json' && 'GET' ne $method) { return unless $self->require_body($c); @@ -77,7 +79,11 @@ sub get_valid_data{ $json_raw //= $data; return unless $self->require_wellformed_json($c, $resource_media_type, $json_raw); - $json_decoded = JSON::from_json($json_raw, { utf8 => 1 }); + if ($c->req->headers->content_type eq 'multipart/form-data') { + $json_decoded = JSON::from_json($json_raw, { utf8 => 0 }); + } else { + $json_decoded = JSON::from_json($json_raw, { utf8 => 1 }); + } if ($method eq 'PATCH') { my $ops = $params{ops} // [qw/replace copy/]; return unless $self->require_valid_patch($c, $json_decoded, $ops); @@ -370,8 +376,8 @@ sub require_body { } sub require_uploads { my ($self, $c) = @_; - return 1 if $c->req->upload; - $self->error($c, HTTP_BAD_REQUEST, "Thismultipart/form-data request is missing upload part."); + return 1 if $c->req->upload || $self->get_config('backward_allow_empty_upload'); + $self->error($c, HTTP_BAD_REQUEST, "This multipart/form-data request is missing upload part."); return; } @@ -1080,13 +1086,15 @@ sub hal_from_item { ], relation => 'ngcp:'.$self->resource_name, ); - if($form){ - $self->validate_form( - c => $c, - resource => $resource, - form => $form, - run => 0, - ); + if (!$self->get_config('dont_validate_hal')) { + if($form){ + $self->validate_form( + c => $c, + resource => $resource, + form => $form, + run => 0, + ); + } } $resource->{id} = $self->get_item_id($c, $item); $resource = $self->post_process_hal_resource($c, $item, $resource, $form); diff --git a/lib/NGCP/Panel/Role/Entities.pm b/lib/NGCP/Panel/Role/Entities.pm index 0034166747..b311c17f69 100644 --- a/lib/NGCP/Panel/Role/Entities.pm +++ b/lib/NGCP/Panel/Role/Entities.pm @@ -71,8 +71,11 @@ sub set_config { #Uploads => [qw/front_image mac_image/],#uploads filenames # or #Uploads => {'greetingfile' => ['audio/x-wav', 'application/octet-stream']}, + #'backward_allow_empty_upload' => [0}1], #default 0. For backward compatibility, when we allowed faxes data input as json field, but not as file #own_transaction_control->{PUT|POST|PATCH|DELETE|ALL} = 0|1 - don't start transaction guard in parent classes, implementation need to control it #ReturnContentType => 'binary'#mostly for GET. value different from 'application/json' says that method is going to return binary data using get_item_binary_data + #'dont_validate_hal' => [0|1], #default 0. Apply or not hal resource validation through form. Validation can be avoided if no PUT or PATCH method supposed for "information" collections + #'no_item_created' => [0|1], #default 0. For rare case when we create something asyronously #} my $obj_name = $self; @@ -268,7 +271,7 @@ sub post { last unless $self->check_resource($c, undef, undef, $resource, $form, $process_extras); $item = $self->create_item($c, $resource, $form, $process_extras); - last unless $item; + last unless $item || $self->get_config('no_item_created'); } else { try { #$processed_ok(array), $processed_failed(array), $info, $error diff --git a/lib/NGCP/Panel/Role/EntitiesItem.pm b/lib/NGCP/Panel/Role/EntitiesItem.pm index 51c6ece033..57927222d5 100644 --- a/lib/NGCP/Panel/Role/EntitiesItem.pm +++ b/lib/NGCP/Panel/Role/EntitiesItem.pm @@ -74,8 +74,12 @@ sub set_config { #Uploads => [qw/front_image mac_image/],#uploads filenames # or #Uploads => {'greetingfile' => ['audio/x-wav', 'application/octet-stream']}, + #'backward_allow_empty_upload' => [0}1], #default 0. For backward compatibility, when we allowed faxes data input as json field, but not as file + #own_transaction_control->{PUT|POST|PATCH|DELETE|ALL} = 0|1 - don't start transaction guard in parent classes, implementation need to control it #ReturnContentType => 'binary'#mostly for GET. value different from 'application/json' says that method is going to return binary data using get_item_binary_data + #'dont_validate_hal' => [0|1], #default 0. Apply or not hal resource validation through form. Validation can be avoided if no PUT or PATCH method supposed for "information" collections + #'no_item_created' => [0|1], #default 0. For rare case when we create something asynchronously #} my $obj_name = $self;