<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><meta http-equiv=Content-Type content="text/html; charset=utf-8"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
{font-family:"Cambria Math";
panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:#954F72;
text-decoration:underline;}
.MsoChpDefault
{mso-style-type:export-only;}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style></head><body lang=EN-US link=blue vlink="#954F72"><div class=WordSection1><p class=MsoNormal>Hi all,</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Still (3 months later) struggling with this one. I’m still seeing the occasional crashes, and in addition – and this is new -- tests using Dancer::Test are failing consistency which may be yet another clue.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>I’ve narrowed the potential culprit to fancy route handling being done by my app. I’m posting here functioning and well-commented code (i.e. works most of the time except when it crashes as previously described) for any comments or thoughts. </p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>As an alternative way to fix the problem, I also welcome alternative ways to accomplish what we’re trying to accomplish (as described in comments):</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>use strict;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>use warnings;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>use Dancer;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>=item<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>Each "instance" of the app is accessed via a URL prefix representing each "client". Examples:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> Various paths within instance for client #1, called "mary":<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/mary<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/mary/foo<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/mary/foo/bar<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> Various paths within instance for client #2, called "susan":<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/susan<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/susan/foo<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> http://www.myapp.com/susan/foo/bar<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> The various paths are implemented as Dancer Routes:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> GET '/instance/...'<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> Examples:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> POST '/instance/bar/api/users'<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> GET '/instance/foo/bar'<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>We trick Dancer by substituting the instance URL with "/instance". All such trickery is contained within this <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>one file. Here's how it works:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>1. Dancer will attempt to match path to anything in ./public, and return file. However, since instance-specific<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>paths will be along the lines of http://www.myapp.com/mary/my.css, no match will occur, since all <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>instance-specific assets are under ./public/instance.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>2. Dancer attempts to match by route. Very first route is qr{.*} route (see below). However, before this route<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>runs, hook 'before' will be triggered...<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>3a. hook 'before' looks for instance URL prefixes (such as "/mary", "/susan" above). If match:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - change path to '/instance/..' <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - if path points to a ./public resource [/instance/(static|cached)], return to qr{.*} immediately<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - set vars->{'client'} to client id, such as "mary" or "susan" above<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - return to qr{.*} route<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>3b. If no match under 3a, return to qr{.*}<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>4. Back in qr{.*}:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - if route path is an instance-specific public asset [/instance/(static|cached)], send it manually using Dancer's send_file()<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - otherwise pass(), which leads to remaining default Dancer route handling:<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - if route path matches a remaining Dancer route, that route will be executed<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> - if no matches, Dancer creates 404/not_found error (unless final route is another catch-all for special handling of 404s)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>=cut<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>any qr{.*} => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> my $request_path = request->path_info;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # Manually send files in ./public/instance/(static|cached)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/(instance/(static|cached)(/.*|\z))} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> send_file( $1 );<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return; # per Dancer docs, route exits after send_file(). return is unnecessary; added for readability.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # causes Dancer to attempt to match to all remaining routes, with path as modified by hook<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> pass();<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>hook 'before' => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> my $request_path = request->path_info();<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # (already did all hook_before operations when first entered as /[instance_url], so skip now)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/instance(/|\z)} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /[instance_url]<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # If match,<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # 1. converts $request_path & request->path_info to /instance/...<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # 2. sets $instance<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # If no match, returns<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> my $instance;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/([^/]+)(/.*|\z)} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> my $url = $1;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> my $therest = $2;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $url =~ /^(mary|susan)$/ ) { # simplified; actual code uses a database<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> $instance = $url;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> $request_path = "/instance" . $therest;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> request->path_info( $request_path );<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( !defined($instance) ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance (converted from /[instance_url])<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # with $instance<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # hole for ./instance/(static|cached)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/instance/(static|cached)(/|\z)} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # set instance-specific var<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> var instance => $instance;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # Only allow access to specific /instance areas, and in some cases require authentication<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> #<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance - welcome<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/instance/?\z} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance/register - Register<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/instance/register(/|\z)} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return; <o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance/signedin - Signed-in area (requires authentication)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if ( $request_path =~ m{^/instance/signedin(/|\z)} ) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> if (!vars->{'not_signed_in'}) {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> request->path_info( "/instance/register");<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> }<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> # /instance/(everything else)<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> request->path_info('/instance/error/notfound');<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>#<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'># /instance routes<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>#<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>get '/instance' => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return "Welcome, ".vars->{'instance'};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>get '/instance/register' => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return "Please register, ".vars->{'instance'};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>get '/instance/signedin' => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return "This is the signed-in area, ".vars->{'instance'}.". You are authenticated";<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>get '/instance/error/not/found' => sub {<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'> return "OOPS! 404 Error";<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>};<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>dance;<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Test results:</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>use Dancer::Test;<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>…<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>response_status_is [GET => "/instance"], 200; # ok<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>response_status_is [GET => "/mary"], 200; # fails. Gets 404.<o:p></o:p></span></p><p class=MsoNormal><span style='font-size:9.0pt;font-family:"Courier New"'>response_status_is [GET => "/susan"], 200; # fails. Gets 404.<o:p></o:p></span></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Thoughts/ideas?</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Thank you!!</p><p class=MsoNormal>Hermann</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal><o:p> </o:p></p><div style='mso-element:para-border-div;border:none;border-top:solid #E1E1E1 1.0pt;padding:3.0pt 0in 0in 0in'><p class=MsoNormal style='border:none;padding:0in'><b>From: </b><a href="mailto:davidp@preshweb.co.uk">David Precious</a><br><b>Sent: </b>Tuesday, March 19, 2019 6:17 AM<br><b>To: </b><a href="mailto:dancer-users@dancer.pm">dancer-users@dancer.pm</a><br><b>Subject: </b>Re: [dancer-users] Dancer crashing</p></div><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>On Wed, 13 Mar 2019 09:58:54 -0700</p><p class=MsoNormal>Chad Wallace <cwallace@lodgingcompany.com> wrote:</p><p class=MsoNormal>> Here are lines 396 and 397 of HTTP/Server/Simple.pm (version 0.52):</p><p class=MsoNormal>> </p><p class=MsoNormal>> my $remote_sockaddr = getpeername( $self->stdio_handle );</p><p class=MsoNormal>> my $family = sockaddr_family($remote_sockaddr);</p><p class=MsoNormal>> </p><p class=MsoNormal>> So $remote_sockaddr is undef. It should avoid calling</p><p class=MsoNormal>> sockaddr_family() in that case.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>It looks like Chad is right - it would appear to be a problem with</p><p class=MsoNormal>HTTP::Server::Simple.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>That means (a) it should be reported there, (b) it should only affect</p><p class=MsoNormal>you while running Dancer standalone.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>You could, if you're keen, patch your local HTTP::Server::Simple with a</p><p class=MsoNormal>check that the call to getpeername( $self->stdio_handle ) did indeed</p><p class=MsoNormal>return something useful, before then passing that to sockaddr_family(),</p><p class=MsoNormal>and if not, emit as much potentially-useful debug info as you can, to</p><p class=MsoNormal>try to isolate the conditions under which this could happen.</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Some form of stress-testing might help, too - maybe it's a timing</p><p class=MsoNormal>issue, a race condition where another request arrives while a previous</p><p class=MsoNormal>one is in a certain state, where the client (or another/previous</p><p class=MsoNormal>client) drops its connection right whne the server isn't expecting it,</p><p class=MsoNormal>or similar?</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Cheers</p><p class=MsoNormal><o:p> </o:p></p><p class=MsoNormal>Dave P</p><p class=MsoNormal>_______________________________________________</p><p class=MsoNormal>dancer-users mailing list</p><p class=MsoNormal>dancer-users@dancer.pm</p><p class=MsoNormal>http://lists.preshweb.co.uk/mailman/listinfo/dancer-users</p><p class=MsoNormal><o:p> </o:p></p></div></body></html>