view release on metacpan or search on metacpan
0.0.40 2023-07-09T17:55:20Z
- Perl 5.38.0 is released
- Perl 5.36.1 is released
0.0.39 2022-11-20T18:56:48Z
- update dependency modules
0.0.38 2022-11-13T05:40:29Z
- fix Untagged opnames warnings, closes https://github.com/shogo82148/p5-aws-lambda/issues/97
- Off load perlstrip to AWS Lambda.
- add fallback to content-type
0.0.37 2022-10-08T13:28:41Z
- arm64 compatible layers are now available on 12 additional regions
- Africa (Cape Town) af-south-1
- Asia Pacific (Seoul) ap-northeast-2
- Asia Pacific (Jakarta) ap-southeast-3
- Asia Pacific (Hong Kong) ap-east-1
- Asia Pacific (Osaka) ap-northeast-3
- Canada (Central) ca-central-1
- Europe (Paris) eu-west-3
author/publish-perl-runtime-archives.pl view on Meta::CPAN
for my $zip(glob "$FindBin::Bin/../.perl-layer/dist/perl-*-$suffix-$arch.zip") {
chomp(my $sha256 = `openssl dgst -sha256 -r "$zip" | cut -d" " -f1`);
my $name = basename($zip, '.zip');
next unless $name =~ /^perl-([0-9]+)-([0-9]+)-/;
my $perl_version = "$1.$2";
head_or_put("$name/$sha256.zip", $zip);
my $metadata = encode_json({
url => "https://shogo82148-lambda-perl-runtime-us-east-1.s3.amazonaws.com/$name/$sha256.zip",
});
run_command("echo '$metadata' | aws --region 'us-east-1' s3 cp --content-type application/json - s3://shogo82148-lambda-perl-runtime-us-east-1/$name.json");
}
}
if ($force) {
say STDERR "FORCE TO DEPLOY";
} else {
say STDERR "DRY RUN";
}
publish("runtime-al2023", "x86_64");
lib/AWS/Lambda/PSGI.pm view on Meta::CPAN
if (reftype($body) eq 'ARRAY') {
$content = join '', grep defined, @$body;
} else {
local $/ = \4096;
while (defined(my $buf = $body->getline)) {
$content .= $buf;
}
$body->close;
}
my $type = $singleValueHeaders->{'content-type'} // 'application/octet-stream';
my $isBase64Encoded = $type !~ m(^text/.*|application/(:?json|javascript|xml))i;
if ($isBase64Encoded) {
$content = encode_base64 $content, '';
} else {
$content = try {
# is valid utf-8 string? try to decode as utf-8.
decode_utf8($content, Encode::FB_CROAK | Encode::LEAVE_SRC);
} catch {
# it looks not utf-8 encoding. fallback to base64 encoding.
$isBase64Encoded = 1;
lib/AWS/Lambda/ResponseWriter.pm view on Meta::CPAN
my $host_port = ($port == $DefaultPort{$scheme} ? $host : "$host:$port");
my $request = {
method => "POST",
scheme => $scheme,
host => $host,
port => $port,
host_port => $host_port,
uri => $path_query,
headers => {
"host" => $host_port,
"content-type" => $content_type,
"transfer-encoding" => "chunked",
"trailer" => "Lambda-Runtime-Function-Error-Type, Lambda-Runtime-Function-Error-Body",
"lambda-runtime-function-response-mode" => "streaming",
},
header_case => {
"host" => "Host",
"content-type" => "Content-Type",
"transfer-encoding" => "Transfer-Encoding",
"trailer" => "Trailer",
"lambda-runtime-function-response-mode" => "Lambda-Runtime-Function-Response-Mode",
},
};
my $peer = $host;
# We remove the cached handle so it is not reused in the case of redirect.
# reuse for the same scheme, host and port
my $handle = delete $http->{handle};
t/20_psgi.t view on Meta::CPAN
is $req->query_string, 'query=hoge&query=fuga', 'query string';
is $req->header('Header-Name'), 'Value1, Value2', 'header';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "API Gateway POST Request" => sub {
my $input = slurp_json("testdata/apigateway-post-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
is $req->content_type, 'application/json', 'content-type';
my $content;
warning_is { $content = slurp_fh($req->input) } undef, 'no warning';
is $content, '{"hello":"ããã«ã¡ã¯ä¸ç"}', 'content';
is $req->request_uri, '/', 'request uri';
is $req->path_info, '/', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "API Gateway Base64 encoded POST Request" => sub {
my $input = slurp_json("testdata/apigateway-base64-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
# You have to add 'application/octet-stream' to binary media types.
# https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-payload-encodings-configure-with-console.html
is $req->content_type, 'application/octet-stream', 'content-type';
my $content;
warning_is { $content = slurp_fh($req->input) } undef, 'no warning';
is $content, '{"hello":"world"}', 'content';
is $req->request_uri, '/', 'request uri';
is $req->path_info, '/', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "API Gateway v2 GET Request" => sub {
t/20_psgi.t view on Meta::CPAN
is $req->query_string, 'query=hoge&query=fuga', 'query string';
is $req->header('Header-Name'), 'Value1, Value2', 'header';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "ALB POST Request" => sub {
my $input = slurp_json("testdata/alb-post-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
is $req->content_type, 'application/json', 'content-type';
is slurp_fh($req->input), '{"hello":"ããã«ã¡ã¯ä¸ç"}', 'content';
is $req->request_uri, '/', 'request uri';
is $req->path_info, '/', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "ALB POST Base64 Request" => sub {
my $input = slurp_json("testdata/alb-base64-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
is $req->content_type, 'application/octet-stream', 'content-type';
is slurp_fh($req->input), '{"hello":"world"}', 'content';
is $req->request_uri, '/foo/bar', 'request uri';
is $req->path_info, '/foo/bar', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "Function URLs GET Request" => sub {
my $input = slurp_json("testdata/function-urls-get-request.json");
my $output = $app->format_input($input);
t/20_psgi.t view on Meta::CPAN
is $req->query_string, 'parameter1=value1¶meter1=value2¶meter2=value', 'query string';
is $req->header('header1'), 'value1,value2', 'header';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "Function URLs POST Request" => sub {
my $input = slurp_json("testdata/function-urls-post-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
is $req->content_type, 'application/json', 'content-type';
is slurp_fh($req->input), '{"hello":"world"}', 'content';
is $req->request_uri, '/my/path', 'request uri';
is $req->path_info, '/my/path', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "Function URLs POST Base64 Request" => sub {
my $input = slurp_json("testdata/function-urls-post-base64-request.json");
my $output = $app->format_input($input);
my $req = Plack::Request->new($output);
is $req->method, 'POST', 'method';
is $req->content_type, 'application/octet-stream', 'content-type';
is slurp_fh($req->input), '{"hello":"world"}', 'content';
is $req->request_uri, '/my/path', 'request uri';
is $req->path_info, '/my/path', 'path info';
is $req->query_string, '', 'query string';
ok !$req->env->{'psgi.streaming'}, 'psgi.streaming';
};
subtest "plain text response" => sub {
my $response = [
200,
t/20_psgi.t view on Meta::CPAN
[
"Hello",
"World",
encode_utf8("ããã«ã¡ã¯ä¸ç"),
]
];
my $res = $app->format_output($response);
cmp_deeply $res, {
isBase64Encoded => bool 0,
headers => {
'content-type' => 'text/plain',
'header-name' => 'value2',
},
multiValueHeaders => {
'content-type' => ['text/plain'],
'header-name' => ['value1', 'value2'],
},
statusCode => 200,
body => "HelloWorldããã«ã¡ã¯ä¸ç",
};
diag encode_json $res;
};
subtest "binary response" => sub {
my $response = [
t/20_psgi.t view on Meta::CPAN
'Content-Type' => 'application/octet-stream',
],
[
'{"hello":"world"}',
]
];
my $res = $app->format_output($response);
cmp_deeply $res, {
isBase64Encoded => bool 1,
headers => {
'content-type' => 'application/octet-stream',
},
multiValueHeaders => {
'content-type' => ['application/octet-stream'],
},
statusCode => 200,
body => "eyJoZWxsbyI6IndvcmxkIn0=",
};
diag encode_json $res;
};
subtest "IO::Handle-like response" => sub {
open my $f, "<", \"HelloWorld";
my $response = [
200,
[
'Content-Type' => 'text/plain',
],
$f,
];
my $res = $app->format_output($response);
cmp_deeply $res, {
isBase64Encoded => bool 0,
headers => {
'content-type' => 'text/plain',
},
multiValueHeaders => {
'content-type' => ['text/plain'],
},
statusCode => 200,
body => "HelloWorld",
};
diag encode_json $res;
};
subtest "EUC-JP encoded response" => sub {
my $response = [
200,
t/20_psgi.t view on Meta::CPAN
'Content-Type' => 'text/plain',
],
[
"\xC8\xFE\xC6\xFD",
]
];
my $res = $app->format_output($response);
cmp_deeply $res, {
isBase64Encoded => bool 1,
headers => {
'content-type' => 'text/plain',
},
multiValueHeaders => {
'content-type' => ['text/plain'],
},
statusCode => 200,
body => "yP7G/Q==",
};
diag encode_json $res;
};
subtest "query string enconding" => sub {
my $input = slurp_json("testdata/apigateway-get-request.json");
$input->{queryStringParameters} = {
t/21_psgi_response_streaming.t view on Meta::CPAN
open my $fh, ">", \$buf or die "failed to open: $!";
return $fh;
};
$res->($responder);
is $content_type, "application/vnd.awslambda.http-integration-response", "content type";
my ($prelude, $body) = split /\x00\x00\x00\x00\x00\x00\x00\x00/, $buf;
cmp_deeply decode_json($prelude), {
statusCode => 200,
headers => {
"content-type" => "text/plain",
},
cookies => [],
}, "prelude";
is $body, "hello", "body";
};
subtest "IO::Handle-like object" => sub {
my $content_type = undef;
open my $fh, "<", \"hello" or die "failed to open: $!";
my $buf = "";
t/21_psgi_response_streaming.t view on Meta::CPAN
open my $fh, ">", \$buf or die "failed to open: $!";
return $fh;
};
$res->($responder);
is $content_type, "application/vnd.awslambda.http-integration-response", "content type";
my ($prelude, $body) = split /\x00\x00\x00\x00\x00\x00\x00\x00/, $buf;
cmp_deeply decode_json($prelude), {
statusCode => 200,
headers => {
"content-type" => "text/plain",
},
cookies => [],
}, "prelude";
is $body, "hello", "body";
};
subtest "streaming response" => sub {
my $content_type = undef;
my $buf = "";
my $res = $app->_handle_response_stream(sub {
t/21_psgi_response_streaming.t view on Meta::CPAN
open my $fh, ">", \$buf or die "failed to open: $!";
return $fh;
};
$res->($responder);
is $content_type, "application/vnd.awslambda.http-integration-response", "content type";
my ($prelude, $body) = split /\x00\x00\x00\x00\x00\x00\x00\x00/, $buf;
cmp_deeply decode_json($prelude), {
statusCode => 200,
headers => {
"content-type" => "text/plain",
},
cookies => [],
}, "prelude";
is $body, "hello", "body";
};
done_testing;
t/testdata/alb-base64-request.json view on Meta::CPAN
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lambda-target/a8d0882e91e66540"
}
},
"httpMethod": "POST",
"path": "/foo/bar",
"queryStringParameters": {},
"headers": {
"accept": "*/*",
"content-length": "17",
"content-type": "application/octet-stream",
"host": "lambda-test-1234567890.ap-northeast-1.elb.amazonaws.com",
"user-agent": "curl/7.54.0",
"x-amzn-trace-id": "Root=1-5c0f091f-56087f0297986bc017de21bc",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "80",
"x-forwarded-proto": "http"
},
"body": "eyJoZWxsbyI6IndvcmxkIn0=",
"isBase64Encoded": true
}
t/testdata/alb-post-request.json view on Meta::CPAN
"elb": {
"targetGroupArn": "arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:targetgroup/lambda-target/a8d0882e91e66540"
}
},
"httpMethod": "POST",
"path": "/",
"queryStringParameters": {},
"headers": {
"accept": "*/*",
"content-length": "17",
"content-type": "application/json",
"host": "lambda-test-1234567890.ap-northeast-1.elb.amazonaws.com",
"user-agent": "curl/7.54.0",
"x-amzn-trace-id": "Root=1-5c0f08ec-8a00ddf3c79b53a01fa905ba",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"body": "{\"hello\":\"ããã«ã¡ã¯ä¸ç\"}",
"isBase64Encoded": false
}
t/testdata/apigateway-base64-request.json view on Meta::CPAN
{
"resource": "/",
"path": "/",
"httpMethod": "POST",
"headers": {
"accept": "*/*",
"content-type": "application/octet-stream",
"Host": "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
"User-Agent": "curl/7.54.0",
"X-Amzn-Trace-Id": "Root=1-5c0f0502-7611e42628aee5c8cce21a72",
"X-Forwarded-For": "192.0.2.1",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"accept": [
"*/*"
],
"content-type": [
"application/octet-stream"
],
"Host": [
"xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
],
"User-Agent": [
"curl/7.54.0"
],
"X-Amzn-Trace-Id": [
"Root=1-5c0f0502-7611e42628aee5c8cce21a72"
t/testdata/apigateway-post-request.json view on Meta::CPAN
{
"resource": "/",
"path": "/",
"httpMethod": "POST",
"headers": {
"accept": "*/*",
"content-type": "application/json",
"Host": "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
"User-Agent": "curl/7.54.0",
"X-Amzn-Trace-Id": "Root=1-5c0f033a-32eff4c8b894f0d4f8fa213c",
"X-Forwarded-For": "192.0.2.1",
"X-Forwarded-Port": "443",
"X-Forwarded-Proto": "https"
},
"multiValueHeaders": {
"accept": [
"*/*"
],
"content-type": [
"application/json"
],
"Host": [
"xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
],
"User-Agent": [
"curl/7.54.0"
],
"X-Amzn-Trace-Id": [
"Root=1-5c0f033a-32eff4c8b894f0d4f8fa213c"
t/testdata/apigateway-v2-base64-request.json view on Meta::CPAN
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "",
"headers": {
"accept": "*/*",
"content-length": "17",
"content-type": "application/octet-stream",
"host": "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
"user-agent": "curl/7.64.1",
"x-amzn-trace-id": "Root=1-5e8a9b8c-5fd89a5053994a40c1343990",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "xxxxxxxxxx",
t/testdata/apigateway-v2-post-request.json view on Meta::CPAN
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "",
"headers": {
"accept": "*/*",
"content-length": "17",
"content-type": "application/json",
"host": "xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com",
"user-agent": "curl/7.64.1",
"x-amzn-trace-id": "Root=1-5e8a9af6-43dfdbb5896d7684515eb0ba",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"requestContext": {
"accountId": "123456789012",
"apiId": "xxxxxxxxxx",
t/testdata/function-urls-post-base64-request.json view on Meta::CPAN
{
"body": "eyJoZWxsbyI6IndvcmxkIn0=",
"headers": {
"accept": "*/*",
"content-type": "application/octet-stream",
"host": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws",
"user-agent": "curl/7.79.1",
"x-amzn-trace-id": "Root=1-62577702-3f59d86f1830be3f76a10c1e",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"isBase64Encoded": true,
"rawPath": "/my/path",
"rawQueryString": "",
t/testdata/function-urls-post-request.json view on Meta::CPAN
{
"body": "{\"hello\":\"world\"}",
"headers": {
"accept": "*/*",
"content-type": "application/json",
"host": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.lambda-url.ap-northeast-1.on.aws",
"user-agent": "curl/7.79.1",
"x-amzn-trace-id": "Root=1-62577683-4e8059702ee4af274153a8a9",
"x-forwarded-for": "192.0.2.1",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"isBase64Encoded": false,
"rawPath": "/my/path",
"rawQueryString": "",