Perl::Dancer how to include a file path as a param

2019-07-25 18:24发布

问题:

I'm new to the Dancer framework and web apps in general. I have a Dancer project in which I have a route that accepts multiple parameters. So far, no sweat. However, if one of the parameters has a file path as its value then the route is not found.

I have tried encoding the parameter string as follows to eliminate the forward slashes:

$paramString =~ s/\//%2F/g;

and this does encode the slashes as expected (I print it out in the log to make sure).

However, after the parameter string is appended to the base URI for the route I'm interested in, the URI shows up in the browser in unencoded form, a 404 error is raised and the log says that the unencoded route can't be found.

I looked into the Request.pm module and found that in the init method a private method called _url_decode is called which removes the encoding. Is there a way to disable this when it is not desired?

I also tried using the uri_for method to create the URI. In this case, the encoded URI does show up in the browser, however, the route is still not found and the log indicates that the unencoded form (with the forward slashes) is being used to search for the route

Trying to match 'GET /exome_proj_config/project_type=exome&project_root=/usr/local/projects/users/pdagosto/projects&analysis_project_name=Test' against /^\/exome_proj_config\/([^\/]+)$/ (generated from '/exome_proj_config/:project_type:project_root:analysis_project_name') in /home/pdagosto/perl5/lib/perl5/Dancer/Route.pm l. 84 here

Since the regex used for the match is clearly looking for a string without any forward slashes following the one at the end of the base URI it's clear that the route will never be found.

Is there a way to have a URI parameter that contains a path or must some other approach be used?

回答1:

It is possible to have a URI with a file path or slashes in the parameter provided that the parameter is part of the query string rather than the path. (See http://en.wikipedia.org/wiki/Uniform_resource_locator.)

For example see this Dancer script:

use strict;
use warnings;
use Dancer;

get '/file/action/:action' => sub {
    my $filename = param('filename');
    my $action = param('action');
    return "Filename is $filename and action is $action";
};

dance;

If you put this string into the browser

http://localhost:3000/file/action/delete?filename=/folder/filename.txt

then you should expect to see this:

Filename is /folder/filename.txt and action is delete

In your question the URL you show uses the & character to separate parameters but it looks like you need a ? character first to separate the query string from the path. It is unclear from your question how you are creating your requests - but provided you can put the filename in the query string part of the URL then the approach above should work.