NAME
Developer::Dashboard::Web::Server - PSGI server bridge for Developer Dashboard
SYNOPSIS
my $server = Developer::Dashboard::Web::Server->new(app => $app);
$server->run;
DESCRIPTION
This module reserves the local listen address, builds the Dancer2 PSGI app, and runs it under Starman through Plack::Runner.
METHODS
new, run, start_daemon, listening_url, serve_daemon, psgi_app, _build_runner, _default_headers, _ssl_certificate_directory, generate_self_signed_cert, get_ssl_cert_paths
Construct and run the local PSGI web server with optional SSL/HTTPS support.
When ssl = 1> is passed to new(), generates or refreshes self-signed certificates in ~/.developer-dashboard/certs/ with SAN coverage for localhost, 127.0.0.1, ::1, the concrete non-wildcard bind host, and any configured extra aliases/IPs, runs an internal HTTPS Starman backend, exposes a public frontend on the requested port, redirects plain HTTP requests on that public port to the equivalent https://... URL, and proxies real HTTPS traffic through to the internal backend. The listening_url() method returns https:// when SSL is enabled.
SSL SUPPORT
Pass ssl = 1> to the new() constructor to enable HTTPS:
my $server = Developer::Dashboard::Web::Server->new(
app => $app,
ssl => 1,
);
$server->run;
Self-signed certificates are generated automatically in ~/.developer-dashboard/certs/ and reused on subsequent runs when they already match the expected browser-safe localhost/loopback profile plus any configured SAN aliases or IP literals. Older legacy dashboard certs without the required SAN and server-auth extensions are regenerated automatically.
Both generate_self_signed_cert and get_ssl_cert_paths locate that directory through _ssl_certificate_directory, which asks Developer::Dashboard::PathRegistry for the home runtime layer. The registry resolves the home directory from HOME, then USERPROFILE, then HOMEDRIVE plus HOMEPATH, so HTTPS also starts on a Windows session, which does not export HOME at all. Only an environment that names no home directory by any of those variables is an error, and it is reported as a missing home directory rather than as a missing single variable.
HTTPS REDIRECT TRUST BOUNDARY
The public listener binds 0.0.0.0 by default, so the plain-HTTP redirect it serves on the SSL port is reachable from the network and its Location header must never be built from client-controlled input. Two values reach that header and both are validated:
The authority comes from the request
Hostheader only when that header parses as a valid host with an optional in-range port and names an authority this server can legitimately answer for: a loopback IP literal, or one of the names its own certificate covers (localhost,127.0.0.1,::1, the concrete non-wildcard bind host, and every entry inweb.ssl_subject_alt_names). Anything else is discarded and the redirect uses the server-derived listen authority instead. The accepted authority is rebuilt from the parsed parts, so no byte of the original header survives into the header value.The target is only reused when it is an origin-form path. A target is concatenated directly after the authority, so an authority-form target such as
@evil.com/would demote the real host to userinfo and hand the redirect to the attacker; a backslash or raw ASCII control byte is rejected for the same reason the login redirect sanitizer rejects them, because URL parsers fold or strip those bytes before parsing. Anything unsafe collapses to/.
Both the PSGI-level redirect used by psgi_app and the socket-level redirect served by the SSL front-proxy apply the same rules.
PURPOSE
This module wraps the dashboard PSGI app in a real listener. It reserves ports, builds the Plack/Starman runner, injects the default security headers, optionally generates and serves the HTTPS frontend, redirects plain HTTP to HTTPS on the same public port, and proxies TLS traffic to an internal backend when SSL is enabled.
WHY IT EXISTS
It exists because transport concerns such as port reservation, HTTPS redirect behavior, SAN-aware self-signed certificates, and SSL frontend proxying should stay out of the route backend. That keeps web transport policy separate from page logic.
WHEN TO USE
Use this file when changing listen host or port behavior, SSL certificate generation, HTTPS redirect logic, Plack runner options, or the low-level frontend/backend proxy path for secure serving.
HOW TO USE
Construct it with the backend app object and desired host, port, worker, and SSL settings, then call run, start_daemon, or serve_daemon. Keep route behavior in Developer::Dashboard::Web::App and keep the transport wiring here.
WHAT USES IT
It is used by dashboard serve, dashboard restart, app.psgi smoke paths, SSL/browser regression tests, and contributors verifying security headers and HTTPS behavior.
EXAMPLES
Example 1:
perl -Ilib -MDeveloper::Dashboard::Web::Server -e 1
Do a direct compile-and-load check against the module from a source checkout.
Example 2:
prove -lv t/03-web-app.t t/08-web-update-coverage.t t/web_app_static_files.t
Run the focused regression tests that most directly exercise this module's behavior.
Example 3:
HARNESS_PERL_SWITCHES=-MDevel::Cover prove -lr t
Recheck the module under the repository coverage gate rather than relying on a load-only probe.
Example 4:
prove -lr t
Put any module-level change back through the entire repository suite before release.