【问题标题】:How to debug server side script for file uploading from client (curl at this example)?如何调试服务器端脚本以从客户端上传文件(在本例中为 curl)?
【发布时间】:2016-10-03 08:52:16
【问题描述】:

我正在尝试从 CLI 编写 Perl Mojolicious 请求。我想将文件作为参数传递给这个请求。 以下是我迄今为止尝试过的事情,但无济于事。

以下示例对我来说很好。

curl (working):          curl -X POST "http://localhost:3000/uploadtest.pl/status?Token=6d949625-2f07-1e7a-d57a-de0fa949035d"
Mojolicious (working):  perl ./uploadtest.pl get -v -M POST /status?"Token=3780e99a-fc2c-54e5-2c31-417f945c1792"

下面是我被卡住的例子,因为下面的 perl 脚本将文件作为输入[文件上传]:

curl (working):          curl -X POST -F Input_File=@d:/xml/test.xml "http://localhost:3000/uploadtest.pl/upload?Input_Type=XML
Mojolicious (not working):  perl ./uploadtest.pl get -v -M POST /upload?"Input_Type=XML&Input_File=d:/xml/test.xml"

如果有人帮助我解决这个问题,那将是很大的帮助。


#uploadtest.pl

use Mojolicious::Lite;

# Upload form in DATA section
get '/' => 'form';


# Check status
post '/status' => sub {
  my $self = shift;
  my $Token = $self->param('Token');
  $self->render(text => "In process: $Token");
};

# Multipart upload handler
post '/upload' => sub {
  my $self = shift;

  # Process uploaded file
  my $Input_File = $self->param('Input_File');
  my $Input_Type = $self->param('Input_Type');
  my $size = $Input_File->size;
  my $name = $Input_File->filename;
  my $upload = $self->req->upload('Input_File');
  $upload->move_to("d:/xml/$name");  #move location
  $self->render(text => "Thanks for uploading $size byte file $name.");
};

app->start;
__DATA__

@@ form.html.ep
<!DOCTYPE html>
<html>
  <head><title>File Upload</title></head>
  <body>
  <form name="FileUpload" action="http://localhost:3000/uploadtest.pl/upload" enctype="multipart/form-data" method="post">
       Input Type:</td><td><input type="text" name="Input_Type" />
       Please specify a file:</td><td><input type="file" name="Input_File" size="40"></td></tr>
       <input type="submit" value="Submit"/>
   </form>
   <br><br><br><hr><br><br><br>
  <form name="Status" action="http://localhost:3000/uploadtest.pl/status" method="post">
      Token ID: <input type="text" name="Token" />
     <input type="submit" value="Check Status"/>
  </form>
  </body>
</html>

【问题讨论】:

  • 当我点击你的标题时,我认为这是关于在启动时将文件作为命令行参数传递给应用程序。澄清一下,您想使用以文件内容为主体的 curl 发送请求吗?或者可能不是。请edit您的问题并澄清。另外,您显示的代码是upload_test.pl 吗?
  • 我已经给出了 curl 以及我尝试过的 mojolicious 命令行示例。Curl 工作正常,但我不知道如何在 mojolicious 中使用命令作为文件内容作为参数。那么你能告诉我如何在 mojolicious 中将文件作为命令参数传递。

标签: perl mojolicious


【解决方案1】:

我想你不明白post '/upload'uploadtest.pl 是什么。

您的脚本是一个小型 HTTP 服务器,它接收请求并做出响应。 您可以永久运行您的服务器并使用例如curl 发出请求,或者对其发出一个请求并退出。

$ perl uploadtest.pl daemon
[Sat Jun 11 14:00:41 2016] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000

# in other shell
$ curl -X POST "http://localhost:3000/uploadtest.pl/status?Token=6d949625-2f07-1e7a-d57a-de0fa949035d"

或两者兼而有之:

$perl ./uploadtest.pl get -v -M POST /status?"Token=3780e99a-fc2c-54e5-2c31-417f945c1792"

这些 POST 向具有空内容

的永久(第一个示例)或一次性服务器(第二个)发出请求

如果您使用 -v 选项运行 curl:

$ curl -v -X POST "http://localhost:3000/status?Token=6d949625-2f07-1e7a-d57a-de0fa949035d"
* Hostname was NOT found in DNS cache
*   Trying 127.0.0.1...
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST /status?Token=6d949625-2f07-1e7a-d57a-de0fa949035d HTTP/1.1
> User-Agent: curl/7.35.0
> Host: localhost:3000
> Accept: */*
> 
< HTTP/1.1 200 OK
* Server Mojolicious (Perl) is not blacklisted
< Server: Mojolicious (Perl)
< Date: Sat, 11 Jun 2016 11:42:24 GMT
< Content-Length: 48
< Content-Type: text/html;charset=UTF-8
< 
* Connection #0 to host localhost left intact
In process: 6d949625-2f07-1e7a-d57a-de0fa949035d

您甚至可以在查询服务器时使用tcpdump

$ sudo tcpdump -x -X -i lo port 3000
14:41:51.665032 IP localhost.49063 > localhost.3000: Flags [P.], seq 1:129, ack 1, win 342, options [nop,nop,TS val 1097613 ecr 1097613], length 128
    0x0000:  4500 00b4 38c4 4000 4006 037e 7f00 0001  E...8.@.@..~....
    0x0010:  7f00 0001 bfa7 0bb8 3b17 8750 a281 4839  ........;..P..H9
    0x0020:  8018 0156 fea8 0000 0101 080a 0010 bf8d  ...V............
    0x0030:  0010 bf8d 504f 5354 202f 7374 6174 7573  ....POST./status
    0x0040:  3f54 6f6b 656e 3d36 6439 3439 3632 352d  ?Token=6d949625-
    0x0050:  3266 3037 2d31 6537 612d 6435 3761 2d64  2f07-1e7a-d57a-d
    0x0060:  6530 6661 3934 3930 3335 6420 4854 5450  e0fa949035d.HTTP
    0x0070:  2f31 2e31 0d0a 5573 6572 2d41 6765 6e74  /1.1..User-Agent
    0x0080:  3a20 6375 726c 2f37 2e33 352e 300d 0a48  :.curl/7.35.0..H
    0x0090:  6f73 743a 206c 6f63 616c 686f 7374 3a33  ost:.localhost:3
    0x00a0:  3030 300d 0a41 6363 6570 743a 202a 2f2a  000..Accept:.*/*
    0x00b0:  0d0a 0d0a                                ....

当你想上传文件到你的服务器时,你使用-F Input_File=@d:/xml/test.xml curl 选项。您还希望您可以执行相同的 onetime 请求,但下一个命令:

$perl ./uploadtest.pl get -v -M POST /upload?"Input_Type=XML&Input_File=d:/xml/test.xml"

不支持此类选项。

$perl ./uploadtest.pl help get
Usage: APPLICATION get [OPTIONS] URL [SELECTOR|JSON-POINTER] [COMMANDS]

  ./myapp.pl get /
  ./myapp.pl get -H 'Accept: text/html' /hello.html 'head > title' text
  ./myapp.pl get //sri:secr3t@/secrets.json /1/content
  mojo get mojolicious.org
  mojo get -v -r google.com
  mojo get -v -H 'Host: mojolicious.org' -H 'Accept: */*' mojolicious.org
  mojo get -M POST -H 'Content-Type: text/trololo' -c 'trololo' perl.org
  mojo get mojolicious.org 'head > title' text
  mojo get mojolicious.org .footer all
  mojo get mojolicious.org a attr href
  mojo get mojolicious.org '*' attr id
  mojo get mojolicious.org 'h1, h2, h3' 3 text
  mojo get https://api.metacpan.org/v0/author/SRI /name

Options:
  -C, --charset <charset>     Charset of HTML/XML content, defaults to
                              auto-detection
  -c, --content <content>     Content to send with request
  -H, --header <name:value>   Additional HTTP header
  -h, --help                  Show this summary of available options
      --home <path>           Path to home directory of your application,
                              defaults to the value of MOJO_HOME or
                              auto-detection
  -M, --method <method>       HTTP method to use, defaults to "GET"
  -m, --mode <name>           Operating mode for your application, defaults to
                              the value of MOJO_MODE/PLACK_ENV or
                              "development"
  -r, --redirect              Follow up to 10 redirects
  -v, --verbose               Print request and response headers to STDERR

从帮助中可以看到,可以发送短信:

  ./uploadtest.pl get -M POST -H 'Content-Type: text/trololo' -c 'trololo' perl.org

要将文件上传到您的uploadtest.pl 服务器,您可以编写自己的上传器。为此,您应该使用Mojo::UserAgent 模块。 Example

use Mojo::UserAgent;

# Upload file via POST and "multipart/form-data"
my $ua = Mojo::UserAgent->new;
$ua->post("http://localhost:3000" => form => {Input_Type => "XML", Input_File => {file => "d:/xml/test.xml"}});

但这是same

perl -Mojo -E 'p("http://localhost:3000" => form => {Input_Type => "XML", Input_File => {file => "d:/xml/test.xml"}})'

UPD

要调试用于文件上传的服务器端脚本,您应该

perl -d uploadtest.pl daemon

Loading DB routines from perl5db.pl version 1.49_04
Editor support available.

Enter h or 'h h' for help, or 'man perldebug' for more help.

main::(tx.pl:6):    get '/' => 'form';
  DB<1>

这将带你进入perl debugger (Tutorial)

  DB<1> l 1-30
1   #uploadtest.pl
2   
3:  use Mojolicious::Lite;
4   
5   # Upload form in DATA section
6==>    get '/' => 'form';
7   
8   
9   # Check status
10  post '/status' => sub {
11:   my $self = shift;
12:   my $Token = $self->param('Token');
13:   $self->render(text => "In process: $Token");
14: };
15  
16  # Multipart upload handler
17  post '/upload' => sub {
18:   my $self = shift;
19  
20    # Process uploaded file
21:   my $Input_File = $self->param('Input_File');
22:   my $Input_Type = $self->param('Input_Type');
23:   my $size = $Input_File->size;
24:   my $name = $Input_File->filename;
25:   my $upload = $self->req->upload('Input_File');
26:   $upload->move_to("d:/xml/$name");  #move location
27:   $self->render(text => "Thanks for uploading $size byte file $name.");
28: };
29  
30: app->start;
  DB<2> b 11
  DB<3> b 18
  DB<4> l 1-30
1   #uploadtest.pl
2   
3:  use Mojolicious::Lite;
4   
5   # Upload form in DATA section
6==>    get '/' => 'form';
7   
8   
9   # Check status
10  post '/status' => sub {
11:b      my $self = shift;
12:   my $Token = $self->param('Token');
13:   $self->render(text => "In process: $Token");
14: };
15  
16  # Multipart upload handler
17  post '/upload' => sub {
18:b      my $self = shift;
19  
20    # Process uploaded file
21:   my $Input_File = $self->param('Input_File');
22:   my $Input_Type = $self->param('Input_Type');
23:   my $size = $Input_File->size;
24:   my $name = $Input_File->filename;
25:   my $upload = $self->req->upload('Input_File');
26:   $upload->move_to("d:/xml/$name");  #move location
27:   $self->render(text => "Thanks for uploading $size byte file $name.");
28: };
29  
30: app->start;
  DB<5> c
[Tue Jun 14 16:43:06 2016] [info] Listening at "http://*:3000"
Server available at http://127.0.0.1:3000
[Tue Jun 14 16:43:10 2016] [debug] POST "/status"
[Tue Jun 14 16:43:10 2016] [debug] Routing to a callback
main::CODE(0x23f7be0)(tx.pl:11):      my $self = shift;
  DB<5> n
main::CODE(0x23f7be0)(tx.pl:12):      my $Token = $self->param('Token');
  DB<5> n
main::CODE(0x23f7be0)(tx.pl:13):      $self->render(text => "In process: $Token");
  DB<5> x $Token
0  '6d949625-2f07-1e7a-d57a-de0fa949035d'
  DB<6> 

这里我列出了1到30行的源代码l 1-30,设置了两个断点b 11b 18,再次列出源代码l 1-30,看看断点是否生效(注意b在附近行),从当前点运行脚本(注意行附近的 ==> 符号)直到下一个断点,使用n 命令完成两个步骤并查看 $Token 的值em> 带有x $Token 命令的变量。

注意,c 脚本等待交互之后。我用curl 来做到这一点

http://localhost:3000/status?Token=6d949625-2f07-1e7a-d57a-de0fa949035d

注意:您应该像以前一样请求“/status”和“/upload”“/updater.pl/status”。您的服务器脚本如何命名与外部单词无关。只有两件事:

  1. 你的脚本在哪里监听:localhost:3000
  2. 可以服务的请求:“/upload”和“/status”

【讨论】:

  • 是的,你是对的,mojolicious get 不支持文件作为参数。我想调试以文件为参数的代码。 curl 不支持这个,所以我使用了 mojolicious。但它没有相同的功能。是否有任何替代方法可以调试我的网络服务,该服务将文件作为参数?
  • 我不懂你。您想调试允许文件上传或使用 Mojo::UserAgent 进行文件上传的服务器端脚本?如果第二个我给了the answer(这与-F Input_File=@d:/xml/test.xml相同)
  • 是的,我想调试允许文件上传的服务器端脚本。
  • @NeyazAhmad 嗯...看来我的回答没用 =)
【解决方案2】:

恐怕 Mojolicious get 命令不支持从文件生成请求。

perl -Mojo -E 'p("http://localhost:3000" => form => {Input_Type => "XML", Input_File => {file => "d:/xml/test.xml"}})'

您必须使用 ojo 单线。

【讨论】:

  • 嗨塞巴斯蒂安,我想你误解了我的问题。我唯一想要的是将文件作为参数提供给 Mojolicious 从 CLI 获取。您建议的语法对代码调试没有用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-03
相关资源
最近更新 更多