6 plan(skip_all => "IPC::Run not available")
19 # Black-box (ish) test for relative linking between CGI and static content
23 sub parse_cgi_content {
26 if ($content =~ qr{<base href="([^"]+)" */>}) {
29 if ($content =~ qr{href="([^"]+/style.css)"}) {
30 $bits{stylehref} = $1;
32 if ($content =~ qr{class="parentlinks">\s+<a href="([^"]+)">this is the name of my wiki</a>/}s) {
35 if ($content =~ qr{<a[^>]+href="([^"]+)\?do=prefs"}) {
41 ok(! system("make -s ikiwiki.out"));
42 ok(! system("rm -rf t/tmp"));
43 ok(! system("mkdir t/tmp"));
49 writefile($name, "t/tmp/in", $content);
50 ok(utime(333333333, 333333333, "t/tmp/in/$name"));
53 write_old_file("a.mdwn", "A");
54 write_old_file("a/b.mdwn", "B");
55 write_old_file("a/b/c.mdwn",
59 write_old_file("a/d.mdwn", "D");
60 write_old_file("a/d/e.mdwn", "E");
62 sub write_setup_file {
64 my $urlline = defined $args{url} ? "url: $args{url}" : "";
65 my $w3mmodeline = defined $args{w3mmode} ? "w3mmode: $args{w3mmode}" : "";
66 my $reverseproxyline = defined $args{reverse_proxy} ? "reverse_proxy: $args{reverse_proxy}" : "";
68 writefile("test.setup", "t/tmp", <<EOF
69 # IkiWiki::Setup::Yaml - YAML formatted setup file
70 wikiname: this is the name of my wiki
73 templatedir: templates
77 cgi_wrapper: t/tmp/ikiwiki.cgi
80 # make it easier to test previewing
85 ENV: { 'PERL5LIB': 'blib/lib:blib/arch' }
90 sub thoroughly_rebuild {
91 ok(unlink("t/tmp/ikiwiki.cgi") || $!{ENOENT});
92 ok(! system("./ikiwiki.out --setup t/tmp/test.setup --rebuild --wrappers"));
95 sub check_cgi_mode_bits {
96 my (undef, undef, $mode, undef, undef,
97 undef, undef, undef, undef, undef,
98 undef, undef, undef) = stat("t/tmp/ikiwiki.cgi");
99 is($mode & 07777, 0754);
102 sub check_generated_content {
103 my $cgiurl_regex = shift;
104 ok(-e "t/tmp/out/a/b/c/index.html");
105 my $content = readfile("t/tmp/out/a/b/c/index.html");
106 # no <base> on static HTML
107 unlike($content, qr{<base\W});
108 like($content, $cgiurl_regex);
109 # cross-links between static pages are relative
110 like($content, qr{<li>A: <a href="../../">a</a></li>});
111 like($content, qr{<li>B: <a href="../">b</a></li>});
112 like($content, qr{<li>E: <a href="../../d/e/">e</a></li>});
118 my $is_preview = delete $args{is_preview};
119 my $is_https = delete $args{is_https};
121 SCRIPT_NAME => '/cgi-bin/ikiwiki.cgi',
122 HTTP_HOST => 'example.com',
124 if (defined $is_preview) {
125 $defaults{REQUEST_METHOD} = 'POST';
126 $in = 'do=edit&page=a/b/c&Preview';
127 $defaults{CONTENT_LENGTH} = length $in;
129 $defaults{REQUEST_METHOD} = 'GET';
130 $defaults{QUERY_STRING} = 'do=prefs';
132 if (defined $is_https) {
133 $defaults{SERVER_PORT} = '443';
134 $defaults{HTTPS} = 'on';
136 $defaults{SERVER_PORT} = '80';
142 run(["./t/tmp/ikiwiki.cgi"], \$in, \$out, init => sub {
144 $ENV{$_} = $envvars{$_}
151 #######################################################################
152 # site 1: a perfectly ordinary ikiwiki
156 url => "http://example.com/wiki/",
157 cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
159 thoroughly_rebuild();
160 check_cgi_mode_bits();
161 # url and cgiurl are on the same host so the cgiurl is host-relative
162 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
163 %bits = parse_cgi_content(run_cgi());
164 is($bits{basehref}, "http://example.com/wiki/");
165 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
166 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
167 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
169 # when accessed via HTTPS, links are secure
170 %bits = parse_cgi_content(run_cgi(is_https => 1));
171 is($bits{basehref}, "https://example.com/wiki/");
172 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
173 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
174 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
176 # when accessed via a different hostname, links stay on that host
177 %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
178 is($bits{basehref}, "http://staging.example.net/wiki/");
179 like($bits{stylehref}, qr{^(?:(?:http:)?//staging.example.net)?/wiki/style.css$});
180 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
181 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
184 %bits = parse_cgi_content(run_cgi(is_preview => 1));
185 is($bits{basehref}, "http://example.com/wiki/a/b/c/");
186 like($bits{stylehref}, qr{^(?:(?:http:)?//example.com)?/wiki/style.css$});
187 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
188 like($bits{cgihref}, qr{^(?:(?:http:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
190 # in html5, the <base> is allowed to be relative, and we take full
194 url => "http://example.com/wiki/",
195 cgiurl => "http://example.com/cgi-bin/ikiwiki.cgi",
197 thoroughly_rebuild();
198 check_cgi_mode_bits();
199 # url and cgiurl are on the same host so the cgiurl is host-relative
200 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
202 %bits = parse_cgi_content(run_cgi());
203 is($bits{basehref}, "/wiki/");
204 is($bits{stylehref}, "/wiki/style.css");
205 is($bits{tophref}, "/wiki/");
206 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
208 # when accessed via HTTPS, links are secure - this is easy because under
209 # html5 they're independent of the URL at which the CGI was accessed
210 %bits = parse_cgi_content(run_cgi(is_https => 1));
211 is($bits{basehref}, "/wiki/");
212 is($bits{stylehref}, "/wiki/style.css");
213 is($bits{tophref}, "/wiki/");
214 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
216 # when accessed via a different hostname, links stay on that host -
217 # this is really easy in html5 because we can use relative URLs
218 %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'staging.example.net'));
219 is($bits{basehref}, "/wiki/");
220 is($bits{stylehref}, "/wiki/style.css");
221 is($bits{tophref}, "/wiki/");
222 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
225 %bits = parse_cgi_content(run_cgi(is_preview => 1));
226 is($bits{basehref}, "/wiki/a/b/c/");
227 is($bits{stylehref}, "/wiki/style.css");
228 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
229 is($bits{cgihref}, "/cgi-bin/ikiwiki.cgi");
231 #######################################################################
232 # site 2: static content and CGI are on different servers
236 url => "http://static.example.com/",
237 cgiurl => "http://cgi.example.com/ikiwiki.cgi",
239 thoroughly_rebuild();
240 check_cgi_mode_bits();
241 # url and cgiurl are not on the same host so the cgiurl has to be
242 # protocol-relative or absolute
243 check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
245 %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
246 like($bits{basehref}, qr{^http://static.example.com/$});
247 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com)?/style.css$});
248 like($bits{tophref}, qr{^(?:http:)?//static.example.com/$});
249 like($bits{cgihref}, qr{^(?:(?:http:)?//cgi.example.com)?/ikiwiki.cgi$});
251 # when accessed via HTTPS, links are secure
252 %bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
253 like($bits{basehref}, qr{^https://static.example.com/$});
254 like($bits{stylehref}, qr{^(?:(?:https:)?//static.example.com)?/style.css$});
255 like($bits{tophref}, qr{^(?:https:)?//static.example.com/$});
256 like($bits{cgihref}, qr{^(?:(?:https:)?//cgi.example.com)?/ikiwiki.cgi$});
258 # when accessed via a different hostname, links to the CGI (only) should
260 %bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
261 like($bits{basehref}, qr{^http://static.example.com/a/b/c/$});
262 like($bits{stylehref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/style.css$});
263 like($bits{tophref}, qr{^(?:(?:http:)?//static.example.com|\.\./\.\./\.\.)/$});
264 like($bits{cgihref}, qr{^(?:(?:http:)?//(?:staging\.example\.net|cgi\.example\.com))?/ikiwiki.cgi$});
266 local $TODO = "use self-referential CGI URL?";
267 like($bits{cgihref}, qr{^(?:(?:http:)?//staging.example.net)?/ikiwiki.cgi$});
272 url => "http://static.example.com/",
273 cgiurl => "http://cgi.example.com/ikiwiki.cgi",
275 thoroughly_rebuild();
276 check_cgi_mode_bits();
277 # url and cgiurl are not on the same host so the cgiurl has to be
278 # protocol-relative or absolute
279 check_generated_content(qr{<a[^>]+href="(?:http:)?//cgi.example.com/ikiwiki.cgi\?do=prefs"});
281 %bits = parse_cgi_content(run_cgi(SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
282 is($bits{basehref}, "//static.example.com/");
283 is($bits{stylehref}, "//static.example.com/style.css");
284 is($bits{tophref}, "//static.example.com/");
285 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
287 # when accessed via HTTPS, links are secure - in fact they're exactly the
288 # same as when accessed via HTTP
289 %bits = parse_cgi_content(run_cgi(is_https => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'cgi.example.com'));
290 is($bits{basehref}, "//static.example.com/");
291 is($bits{stylehref}, "//static.example.com/style.css");
292 is($bits{tophref}, "//static.example.com/");
293 is($bits{cgihref}, "//cgi.example.com/ikiwiki.cgi");
295 # when accessed via a different hostname, links to the CGI (only) should
297 %bits = parse_cgi_content(run_cgi(is_preview => 1, SCRIPT_NAME => '/ikiwiki.cgi', HTTP_HOST => 'staging.example.net'));
298 is($bits{basehref}, "//static.example.com/a/b/c/");
299 is($bits{stylehref}, "//static.example.com/style.css");
300 is($bits{tophref}, "../../../");
301 like($bits{cgihref}, qr{//(?:staging\.example\.net|cgi\.example\.com)/ikiwiki\.cgi});
303 local $TODO = "use self-referential CGI URL maybe?";
304 is($bits{cgihref}, "//staging.example.net/ikiwiki.cgi");
307 #######################################################################
308 # site 3: we specifically want everything to be secure
312 url => "https://example.com/wiki/",
313 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
315 thoroughly_rebuild();
316 check_cgi_mode_bits();
317 # url and cgiurl are on the same host so the cgiurl is host-relative
318 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
320 # when accessed via HTTPS, links are secure
321 %bits = parse_cgi_content(run_cgi(is_https => 1));
322 is($bits{basehref}, "https://example.com/wiki/");
323 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
324 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
325 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
327 # when not accessed via HTTPS, links should still be secure
328 # (but if this happens, that's a sign of web server misconfiguration)
329 %bits = parse_cgi_content(run_cgi());
330 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
332 local $TODO = "treat https in configured url, cgiurl as required?";
333 is($bits{basehref}, "https://example.com/wiki/");
334 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
336 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
338 # when accessed via a different hostname, links stay on that host
339 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
340 is($bits{basehref}, "https://staging.example.net/wiki/");
341 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
342 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
343 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
346 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
347 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
348 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
349 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
350 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
352 # not testing html5: 0 here because that ends up identical to site 1
354 #######################################################################
355 # site 4 (NetBSD wiki): CGI is secure, static content doesn't have to be
359 url => "http://example.com/wiki/",
360 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
362 thoroughly_rebuild();
363 check_cgi_mode_bits();
364 # url and cgiurl are on the same host but different schemes
365 check_generated_content(qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
367 # when accessed via HTTPS, links are secure (to avoid mixed-content)
368 %bits = parse_cgi_content(run_cgi(is_https => 1));
369 is($bits{basehref}, "https://example.com/wiki/");
370 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
371 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
372 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
374 # when not accessed via HTTPS, ???
375 %bits = parse_cgi_content(run_cgi());
376 like($bits{basehref}, qr{^https?://example.com/wiki/$});
377 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
378 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
379 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
381 # when accessed via a different hostname, links stay on that host
382 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
383 # because the static and dynamic stuff is on the same server, we assume that
384 # both are also on the staging server
385 like($bits{basehref}, qr{^https://staging.example.net/wiki/$});
386 like($bits{stylehref}, qr{^(?:(?:https:)?//staging.example.net)?/wiki/style.css$});
387 like($bits{tophref}, qr{^(?:(?:(?:https:)?//staging.example.net)?/wiki|\.)/$});
388 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:staging\.example\.net|example\.com))?/cgi-bin/ikiwiki.cgi$});
390 local $TODO = "this should really point back to itself but currently points to example.com";
391 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
395 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
396 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
397 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
398 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
399 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
403 url => "http://example.com/wiki/",
404 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
406 thoroughly_rebuild();
407 check_cgi_mode_bits();
408 # url and cgiurl are on the same host but different schemes
409 check_generated_content(qr{<a[^>]+href="https://example.com/cgi-bin/ikiwiki.cgi\?do=prefs"});
411 # when accessed via HTTPS, links are secure (to avoid mixed-content)
412 %bits = parse_cgi_content(run_cgi(is_https => 1));
413 is($bits{basehref}, "/wiki/");
414 is($bits{stylehref}, "/wiki/style.css");
415 is($bits{tophref}, "/wiki/");
416 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
418 # when not accessed via HTTPS, ???
419 %bits = parse_cgi_content(run_cgi());
420 like($bits{basehref}, qr{^(?:https?://example.com)?/wiki/$});
421 like($bits{stylehref}, qr{^(?:(?:https?:)?//example.com)?/wiki/style.css$});
422 like($bits{tophref}, qr{^(?:(?:https?://example.com)?/wiki|\.)/$});
423 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
425 # when accessed via a different hostname, links stay on that host
426 %bits = parse_cgi_content(run_cgi(is_https => 1, HTTP_HOST => 'staging.example.net'));
427 # because the static and dynamic stuff is on the same server, we assume that
428 # both are also on the staging server
429 is($bits{basehref}, "/wiki/");
430 is($bits{stylehref}, "/wiki/style.css");
431 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
432 like($bits{cgihref}, qr{^(?:(?:https:)?//(?:example\.com|staging\.example\.net))?/cgi-bin/ikiwiki.cgi$});
434 local $TODO = "this should really point back to itself but currently points to example.com";
435 like($bits{cgihref}, qr{^(?:(?:https:)?//staging.example.net)?/cgi-bin/ikiwiki.cgi$});
439 %bits = parse_cgi_content(run_cgi(is_preview => 1, is_https => 1));
440 is($bits{basehref}, "/wiki/a/b/c/");
441 is($bits{stylehref}, "/wiki/style.css");
442 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
443 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
445 # Deliberately not testing https static content with http cgiurl,
446 # because that makes remarkably little sense.
448 #######################################################################
449 # site 5: w3mmode, as documented in [[w3mmode]]
454 cgiurl => "ikiwiki.cgi",
457 thoroughly_rebuild();
458 check_cgi_mode_bits();
459 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
460 check_generated_content(qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
462 %bits = parse_cgi_content(run_cgi(PATH_INFO => '/ikiwiki.cgi', SCRIPT_NAME => '/cgi-bin/ikiwiki-w3m.cgi'));
463 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
464 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
465 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
466 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
471 cgiurl => "ikiwiki.cgi",
474 thoroughly_rebuild();
475 check_cgi_mode_bits();
476 # FIXME: does /$LIB/ikiwiki-w3m.cgi work under w3m?
477 check_generated_content(qr{<a[^>]+href="(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi\?do=prefs"});
479 %bits = parse_cgi_content(run_cgi(PATH_INFO => '/ikiwiki.cgi', SCRIPT_NAME => '/cgi-bin/ikiwiki-w3m.cgi'));
480 like($bits{tophref}, qr{^(?:\Q$pwd\E/t/tmp/out|\.)/$});
481 like($bits{cgihref}, qr{^(?:file://)?/\$LIB/ikiwiki-w3m.cgi/ikiwiki.cgi$});
482 like($bits{basehref}, qr{^(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out/$});
483 like($bits{stylehref}, qr{^(?:(?:(?:file:)?//)?\Q$pwd\E/t/tmp/out|\.)/style.css$});
485 #######################################################################
486 # site 6: we're behind a reverse-proxy
490 url => "https://example.com/wiki/",
491 cgiurl => "https://example.com/cgi-bin/ikiwiki.cgi",
494 thoroughly_rebuild();
495 check_cgi_mode_bits();
496 # url and cgiurl are on the same host so the cgiurl is host-relative
497 check_generated_content(qr{<a[^>]+href="/cgi-bin/ikiwiki.cgi\?do=prefs"});
499 # because we are behind a reverse-proxy we must assume that
500 # we're being accessed by the configured cgiurl
501 %bits = parse_cgi_content(run_cgi(HTTP_HOST => 'localhost'));
502 like($bits{tophref}, qr{^(?:/wiki|\.)/$});
503 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
504 is($bits{basehref}, "https://example.com/wiki/");
505 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
508 %bits = parse_cgi_content(run_cgi(is_preview => 1, HTTP_HOST => 'localhost'));
509 like($bits{tophref}, qr{^(?:/wiki|\.\./\.\./\.\.)/$});
510 like($bits{cgihref}, qr{^(?:(?:https:)?//example.com)?/cgi-bin/ikiwiki.cgi$});
511 is($bits{basehref}, "https://example.com/wiki/a/b/c/");
512 like($bits{stylehref}, qr{^(?:(?:https:)?//example.com)?/wiki/style.css$});
514 # not testing html5: 1 because it would be the same as site 1 -
515 # the reverse_proxy config option is unnecessary under html5