/
ErrorDocument.pm6
88 lines (68 loc) · 2.01 KB
/
ErrorDocument.pm6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
use v6;
use Crust::Middleware;
use Crust::MIME;
use HTTP::Status;
unit class Crust::Middleware::ErrorDocument is Crust::Middleware;
has Hash $.errors;
has Bool $.sub-request;
method new(Callable $app, |opts) {
my %newopts = errors => {}, sub-request => False;
for opts -> $opt {
my $kv = $opt.key ~~ Pair ?? $opt.key !! $opt;
if $kv.key eq 'sub-request' {
%newopts<sub-request> = $kv.value;
} else {
%newopts<errors>{$kv.key.Str} = $kv.value;
}
}
callwith($app, |%newopts);
}
method !call(%env) {
my @ret = await $.app()(%env);
my %headers = %(@ret[1]);
my $path = $!errors{@ret[0].Str};
if !is-error(@ret[0]) || !$path.defined {
return @ret;
}
if $!sub-request {
for %headers -> $pair {
unless ($pair.key ~~ /^ p6w /) {
%headers{'p6wx.errordocument.' ~ $pair.key} = $pair.value;
}
}
%env<REQUEST_METHOD> = 'GET';
%env<REQUEST_URI> = $path;
%env<PATH_INFO> = $path;
%env<QUERY_STRING> = '';
%env<CONTENT_LENGTH>:delete;
my @sub_ret = await $.app()(%env);
@ret = @sub_ret if @sub_ret[0] == 200;
} else {
%headers<Content-Length>:delete;
%headers<Content-Encoding>:delete;
%headers<Transfer-Encoding>:delete;
%headers<Content-Type> = Crust::MIME.mime-type($path);
@ret[2] = open $path, :bin;
}
@ret[1] = [%headers];
return @ret;
}
method CALL-ME(%env) { start { self!call(%env) } }
=begin pod
=head1 NAME
Crust::Middleware::ErrorDocument - Set Error Document based on HTTP status code
=head1 SYNOPSIS
my &app = sub(%env) { ... };
my $code = Crust::Middleware::ErrorDocument.new(
&app,
500 => '/uri/error/500.html',
404 => '/uri/error/404.html',
}
# getting sub request
$code = Crust::Middleware::ErrorDocument.new(
&app,
500 => '/uri/error/500.html',
404 => '/uri/error/404.html',
:sub-request => True,
}
=end pod