From a0cfac92f8e1666fc1acaf4277ce0699e273b65e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Gigandet?= Date: Thu, 11 May 2023 15:03:59 +0200 Subject: [PATCH] fix: make CORS work on dev server and API v3 (#8392) --- lib/ProductOpener/API.pm | 7 +++++-- lib/ProductOpener/APITest.pm | 3 ++- lib/ProductOpener/HTTP.pm | 6 +++--- stop_words.txt | 6 ++++++ tests/integration/api_v3_product_write.t | 11 +++++++++++ tests/integration/cors.t | 14 +++++++++++++- tests/unit/http.t | 2 +- 7 files changed, 41 insertions(+), 8 deletions(-) diff --git a/lib/ProductOpener/API.pm b/lib/ProductOpener/API.pm index 31a7d7de7f39d..5b73fc1bf13ce 100644 --- a/lib/ProductOpener/API.pm +++ b/lib/ProductOpener/API.pm @@ -374,10 +374,13 @@ sub process_api_request ($request_ref) { # Product read or write if ($request_ref->{api_action} eq "product") { - if ($request_ref->{api_method} eq "PATCH") { + if ($request_ref->{api_method} eq "OPTIONS") { + # Just return CORS headers + } + elsif ($request_ref->{api_method} eq "PATCH") { write_product_api($request_ref); } - elsif ($request_ref->{api_method} =~ /^(GET|HEAD|OPTIONS)$/) { + elsif ($request_ref->{api_method} =~ /^(GET|HEAD)$/) { read_product_api($request_ref); } else { diff --git a/lib/ProductOpener/APITest.pm b/lib/ProductOpener/APITest.pm index 294062df8a46c..39c27878da25a 100644 --- a/lib/ProductOpener/APITest.pm +++ b/lib/ProductOpener/APITest.pm @@ -460,7 +460,8 @@ sub execute_api_tests ($file, $tests_ref, $ua = undef) { $response = $test_ua->delete( $url, Content => encode_utf8($test_ref->{body}), - "Content-Type" => "application/json; charset=utf-8" % $headers_in, + "Content-Type" => "application/json; charset=utf-8", + %$headers_in, ); } elsif ($method eq 'PATCH') { diff --git a/lib/ProductOpener/HTTP.pm b/lib/ProductOpener/HTTP.pm index 74a6884941995..9066f9d76621d 100644 --- a/lib/ProductOpener/HTTP.pm +++ b/lib/ProductOpener/HTTP.pm @@ -30,7 +30,7 @@ C consists of functions used only in OpenFoodFacts website f The module implements http utilities to use in different part of the code. -FIXME: a lot of fuctions in Display.pm should be moved here. +FIXME: a lot of functions in Display.pm should be moved here. =cut @@ -61,7 +61,7 @@ use ProductOpener::Config qw/:all/; =head2 get_cors_headers($allow_credentials = 0, $sub_domain_only = 0) -We handle CORS headers from perl code, NGINX should not interfere. +We handle CORS headers from Perl code, NGINX should not interfere. So this is the central place for it. Some parts needs to be more strict than others (eg. auth). @@ -129,7 +129,7 @@ sub get_cors_headers ($allow_credentials = 0, $sub_domain_only = 0) { # be generous on methods and headers, it does not hurt $headers_ref->{"Access-Control-Allow-Methods"} = "HEAD, GET, PATCH, POST, PUT, OPTIONS"; $headers_ref->{"Access-Control-Allow-Headers"} - = "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match"; + = "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match,Authorization"; $headers_ref->{"Access-Control-Expose-Headers"} = "Content-Length,Content-Range"; return $headers_ref; diff --git a/stop_words.txt b/stop_words.txt index 6ca2613c9fe19..f6d991ceb7aad 100644 --- a/stop_words.txt +++ b/stop_words.txt @@ -18,6 +18,7 @@ APIProductWrite appid aromatisées arôme +auth autocomplete backend backticks @@ -44,6 +45,7 @@ CodeOnline colza Config contenant +CORS couvercle Crowdin csv @@ -66,6 +68,7 @@ EXIF Fabriqué filehandle FILEHANDLE +FIXME flavour flavouring flavourings @@ -130,6 +133,7 @@ NaN naturel nd NGO +NGINX nodejs nutri Nutri @@ -146,6 +150,7 @@ packagings param Pâtes pectine +Perl png PNG PNNS @@ -189,6 +194,7 @@ tagtype taxonomize taxonomized tesseract +tld TODO TSV ua diff --git a/tests/integration/api_v3_product_write.t b/tests/integration/api_v3_product_write.t index c1a6b7a3ec3fa..d580a40282fde 100644 --- a/tests/integration/api_v3_product_write.t +++ b/tests/integration/api_v3_product_write.t @@ -593,6 +593,17 @@ my $tests_ref = [ path => '/api/v3/product/test', body => '{"product": { "ingredients_text_en": "milk 80%, sugar, cocoa powder"}}', }, + { + test_case => 'options-code-test', + method => 'OPTIONS', + path => '/api/v3/product/test', + body => '{"product": { "ingredients_text_en": "milk 80%, sugar, cocoa powder"}}', + headers => { + "Access-Control-Allow-Origin" => "*", + "Access-Control-Allow-Methods" => "HEAD, GET, PATCH, POST, PUT, OPTIONS", + }, + expected_type => "html", + }, { test_case => 'patch-unrecognized-field', method => 'PATCH', diff --git a/tests/integration/cors.t b/tests/integration/cors.t index 332b36f545c66..e28e719708546 100644 --- a/tests/integration/cors.t +++ b/tests/integration/cors.t @@ -60,11 +60,23 @@ my $tests_ref = [ }, expected_type => "html", }, + # Note: in API v3, we return a 200 status code for OPTIONS, even if the product does not exist { test_case => 'options-api-v3', method => 'OPTIONS', path => '/api/v3/product/0000002', - expected_status_code => 404, + expected_status_code => 200, + headers => { + "Access-Control-Allow-Origin" => "*", + "Access-Control-Allow-Methods" => "HEAD, GET, PATCH, POST, PUT, OPTIONS", + }, + expected_type => "html", + }, + { + test_case => 'options-api-v3-test-product', + method => 'OPTIONS', + path => '/api/v3/product/test', + expected_status_code => 200, headers => { "Access-Control-Allow-Origin" => "*", "Access-Control-Allow-Methods" => "HEAD, GET, PATCH, POST, PUT, OPTIONS", diff --git a/tests/unit/http.t b/tests/unit/http.t index 2ef8a9b54ecfd..2bcfbce3bd7e9 100644 --- a/tests/unit/http.t +++ b/tests/unit/http.t @@ -34,7 +34,7 @@ sub fake_headers_in ($fake_arg) { my $expected_base_ref = { "Access-Control-Allow-Methods" => "HEAD, GET, PATCH, POST, PUT, OPTIONS", "Access-Control-Allow-Headers" => - "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match", + "DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,If-None-Match,Authorization", "Access-Control-Expose-Headers" => "Content-Length,Content-Range", };