-
Notifications
You must be signed in to change notification settings - Fork 3
/
service.p6
127 lines (110 loc) · 3.85 KB
/
service.p6
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
use Cro::HTTP::Log::File;
use Cro::HTTP::Router;
use Cro::HTTP::Server;
use Cro::HTTP::Session::InMemory;
use Routes;
$*ERR.out-buffer = $*OUT.out-buffer = False;
class CSPolicy does Cro::Transform {
method consumes() { Cro::HTTP::Response }
method produces() { Cro::HTTP::Response }
method transformer(Supply $pipeline --> Supply) {
supply {
whenever $pipeline -> $response {
$response.append-header:
'Content-Security-Policy',
"frame-ancestors 'none'";
$response.append-header:
'Content-Security-Policy-Report-Only',
"default-src 'none';"
~ "font-src 'self';"
~ "img-src 'self' data:;"
~ "object-src 'none';"
~ "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.gstatic.com https://code.jquery.com https://cdnjs.cloudflare.com;"
~ "style-src 'self' 'unsafe-inline' https://www.gstatic.com;"
~ "report-uri /csp-violation/;";
emit $response;
}
}
}
}
class StrictTransportSecurity does Cro::Transform {
has Duration:D $.max-age is required;
method consumes() { Cro::HTTP::Response }
method produces() { Cro::HTTP::Response }
method transformer(Supply $pipeline --> Supply) {
supply {
whenever $pipeline -> $response {
$response.append-header:
'Strict-Transport-Security',
"max-age=$!max-age; includeSubDomains; preload";
emit $response;
}
}
}
}
class XHeaders does Cro::Transform {
method consumes() { Cro::HTTP::Response }
method produces() { Cro::HTTP::Response }
method transformer(Supply $pipeline --> Supply) {
supply {
whenever $pipeline -> $response {
$response.append-header:
'X-Frame-Options',
'DENY';
$response.append-header:
'X-XSS-Protection',
'1; mode=block';
$response.append-header:
'X-Content-Type-Options',
'nosniff';
emit $response;
}
}
}
}
# Redirect HTTP to HTTPS.
my $http = Cro::HTTP::Server.new(
:1080port,
:host<0.0.0.0>,
application => route {
get -> *@path, :%headers is header {
my $url = "https://%headers<Host>" ~ (request.path // '');
$url ~= '?' ~ request.query if request.query;
redirect :permanent, $url;
}
},
);
my $https = Cro::HTTP::Server.new(
:1443port,
:host<0.0.0.0>,
# FIXME POST /login doesnt't work with h2.
http => <1.1>,
before => [
Cro::HTTP::Session::InMemory[UserSession].new;
],
tls => %(
private-key-file => %*ENV<MYJUDO_TLS_KEY> ||
%?RESOURCES<fake-tls/server-key.pem> || "resources/fake-tls/server-key.pem",
certificate-file => %*ENV<MYJUDO_TLS_CERT> ||
%?RESOURCES<fake-tls/server-crt.pem> || "resources/fake-tls/server-crt.pem",
),
application => routes(),
after => [
Cro::HTTP::Log::File.new(logs => $*OUT, errors => $*ERR),
# set max age to be one year and one day, 366 days
StrictTransportSecurity.new(max-age => Duration.new(366 * 24 * 60 * 60)),
XHeaders.new(),
CSPolicy.new(),
]
);
$http.start;
$https.start;
say 'Listening…';
react {
whenever signal(SIGINT) {
say 'Stopping…';
$http.stop;
$https.stop;
done;
}
}