NAME

Net::Inspect::L7::HTTP::Request::InspectChain - chained inspection and modification of HTTP request and response

SYNOPSIS

    my $http_request =
	Net::Inspect::L7::HTTP::Request::InspectChain->new(
	myHTTPRequest->new);
    $http_request->add_hooks(
	'-original-header-prefix' => 'X-Original-',
	'unchunk',
	'uncompress_ce'
    );
    my $http  = Net::Inspect::L7::HTTP->new($http_request);
    ...

    {
	package myHTTPRequest;
	use base 'Net::Inspect::L7::HTTP::Request::Simple';
	sub in {
	    my ($self,$dir,$data,$eof,$time) = @_;
	    ... save already uncompressed data into file ...
	}
    }

DESCRIPTION

With this class one can deeply analyze and modify a HTTP request, like unchunking and uncompressing the content and adding custom functions to modify request and response header and content.

It provides all hooks required from Net::Inspect::L7::HTTP and will require the same hooks for the attached upper flow, which will receive the modified header and content.

The following methods are provided for adding inspection and modification:

add_hooks([$pos],[%opt],@hooks,[$pos],[%opt],@hooks...)

adds the given inspection/modification hooks. A hook is either a string for predefined hooks or a hash ref with the name of the hookable place as key and a code ref or array-ref with code-ref and arguments implementing the hook as the value. The key 'name' can be used to give the hook a name, which later can be used in update_hook.

The hooks will be applied in the given order. With pos the position in the list can be defined, e.g. 0 will insert at the beginning, undef will add at the end. Adding at the end is the default. Note that the order of the hooks is really important!

Option keys in %opt start with '-'. All options will be added to the following hooks.

The following hookable places exist and require the given kind of hook code:

request_header => sub($self,\$hdr,$time,@hook_args)

This hook is called after reading the request header. The header as a string is given as a scalar-ref and can be modified. Using request_header method the header can be accessed as HTTP::Request object.

The hook should return 1 if the header was changed and 0 if not. If it returns undef the processing will stop and it will be expected, that the hook already called $self->fatal in this case to propagate the error.

request_body => sub($self,\$data,$eof,$time,@hook_args)

This hook is called whenever new data arrive for the request body. It should modify $data to remove all processed content and returns the processed content.

If content remains in $data it will be still in it when the hook is called again when new data arrive. This means especially, that nothing should remain in $data if $eof is true, because no more data will arrive. If this condition is not met the code will die().

response_header => sub($self,\$hdr,$time,@hook_args)

This is similar to request_header, except that is applied to the response header.

response_body => sub($self,\$data,$eof,$time,@hook_args)

This is similar to request_body, except that is applied to the response body. It will only be called on the content, not on the framing of chunked encoding.

chunked_header => sub($self,$dir,\$hdr,$time,@hook_args)

This will be called for each header of the framing in chunked encoding. One can modify $hdr. The hook should return undef on error, otherwise something defined.

chunked_trailer => sub($self,$dir,\$trailer,$time,@hook_args)

This will be called for the trailer of the framing in chunked encoding. One can modify $trailer. The hook should return undef on error, otherwise something defined.

The following predefined hooks exist:

unchunk

will hook into response_header. If it says, that the response is chunked it will remove the chunked info from Transfer-Encoding header and update hooks in chunk_header and chunk_trailer to remove the chunk framing.

If the chunking was found and removed it will set $self-{info}{chunked}>.

If option -original-header-prefix is given it will preserver the original header for alle changed headers with the given prefix.

uncompress_ce

will hook into response_header. If it says, that the response has a Content-Encoding of gzip or deflate or br (if supported) it will remove the info from the header and update hook in response_body to uncompress content.

If compression was found and removed it will set $self-{info}{ce_gzip}>, $self-{info}{ce_deflate}> or $self-{info}{ce_br}>.

If option -original-header-prefix is given it will preserver the original header for alle changed headers with the given prefix.

uncompress_te

same as uncompress_ce, but for Transfer-Encoding.

update_hook($name,\%hook)

will update the hook with with name $name with the given definition. Hookable places not given in %hook will be kept.

request_header([$hdr_string])

helper function which will return HTTP::Request object for the request header. Can also be used to set new header.

response_header([$hdr_string])

helper function which will return HTTP::Response object for the response header Can also be used to set new header.

LIMITS

Only gzip and deflate are supported for uncompression by default. If IO::Uncompress::Brotli is available also 'br' is supported.