<<

NAME

ProductOpener::HTTP - utility functions around http (handling headers, cookies, redirect, etc.)

SYNOPSIS

ProductOpener::Web consists of functions used only in OpenFoodFacts website for different tasks.

DESCRIPTION

The module implements http utilities to use in different part of the code.

FIXME: a lot of functions in Display.pm should be moved here.

set_http_response_header($request_ref, $header_name, $header_value)

This function sets a header in the response.

Parameters

$request_ref - Reference to the request object.

$header_name - Name of the header.

$header_value - Value of the header.

write_http_response_headers($request_ref)

This function writes the headers in the response.

Parameters

$request_ref - Reference to the request object.

extension_and_query_parameters_to_redirect_url($request_ref)

This function returns the extension and query parameters that can be added to a redirect URL. e.g. if the URL is /ingredients.json?filter=strawberry we get a .json?filter=strawberry

Parameters

$request_ref - Reference to the request object.

Return value

A string with the extension and query parameters that can be added to a redirect URL.

redirect_to_url($request_ref, $status_code, $redirect_url)

This function instructs mod_perl to print redirect HTTP header (Location) and to terminate the request immediately. The mod_perl process is not terminated and will continue to serve future requests.

Arguments

Request object $request_ref

The request object may contain a cookie.

Status code $status_code

e.g. 302 for a temporary redirect

Redirect url $redirect_url

single_param ($param_name)

CGI.pm param() function returns a list when called in a list context (e.g. when param() is an argument of a function, or the value of a field in a hash). This causes issues for function signatures that expect a scalar, and that may get passed an empty list if the parameter is not set.

So instead of calling CGI.pm param() directly, we call single_param() to prefix it with scalar.

Arguments

CGI parameter name $param_name

Return value

A scalar value for the parameter, or undef if the parameter is not defined.

request_param ($request_ref, $param_name)

Return a request parameter. The parameter can be passed in the query string, as a POST multipart form data parameter, in a POST JSON body, or in cookies for some parameters like product attribute parameters

Arguments

Parameter name $param_name

Return value

A scalar value for the parameter, or undef if the parameter is not defined.

Note that we really want to return undef, and not use an empty return statement, as otherwise code like

        my $options_ref = {
                limit => request_param($request_ref, 'limit'),
                get_synonyms => request_param($request_ref, 'get_synonyms')
        };

will result in 'limit' being set to 'get_synonyms' value when the 'limit' parameter is not passed.

This goes against https://metacpan.org/pod/Perl::Critic::Policy::Subroutines::ProhibitExplicitReturnUndef but we are not using return undef to indicate an error, but to indicate that the parameter is not defined.

create_user_agent([$args])

Creates a standardized LWP::UserAgent

Parameters

Behavior

Creates a standardized HTTP client with correct user agent.

Return value

A new LWP::UserAgent instance

ip_is_not_public($ip_address)

Returns 1 if an IPv4 or IPv6 address is not globally routable: loopback, private, carrier grade NAT, link-local (including the 169.254.169.254 metadata service), unique local, site-local, multicast, documentation, benchmarking or reserved space. IPv4-mapped and IPv4-compatible IPv6 addresses are classified on the IPv4 address they carry.

Returns 0 for a globally routable address, and 1 for a value that is not an address at all: an address we cannot classify is not an address we want to fetch.

Arguments

$ip_address - string: an IPv4 or IPv6 address, in its usual textual form

Return value

1 if the address is not globally routable or cannot be parsed, 0 if it is

ip_address_matches_prefix($address_bytes, $family, $prefix, $prefix_length)

Returns 1 if the packed address ($address_bytes, in the given address family) starts with the given prefix, or 0 if it does not. Not exported, only used by ip_is_not_public().

resolve_host_addresses($host)

Returns an array ref with the addresses a host name resolves to, or an empty array ref if it does not resolve. An address written literally in the url is returned as it is, without asking for a DNS resolution.

Arguments

$host - string: a host name or an IP address

Return value

array ref with the IPv4 and IPv6 addresses the host resolves to (possibly empty)

url_is_fetchable($url, $allowed_hosts_ref)

Returns 1 if an url can be fetched from the server: its scheme is http or https, it has a host, and every address that host resolves to is globally routable. Otherwise returns 0.

The second argument defaults to the hosts that an operator listed in $server_options{allowed_image_download_hosts}: those are fetched without resolving them, for an operator who imports from a supplier serving images from a non globally routable address.

Note that the address is resolved again by the HTTP client: a host name whose DNS answer changes between our check and the request can still be reached (DNS rebinding). Pinning the address would mean connecting to it ourselves, which would break virtual hosting and the TLS certificate check.

Arguments

$url - string: the url that would be fetched

$allowed_hosts_ref - optional array ref: host names that are fetched without a check

Return value

1 if the url can be fetched, 0 otherwise

<<