为什么curl POST 请求会使我的Catalyst::Controller::REST 控制器崩溃?
我正在使用 Catalyst 构建 RESTful Web 服务,因此我以通常的方式创建一个 Catalyst 控制器
script/myapp_create.pl controller MyApp::Controller
,然后启动 Catalyst 测试服务器
script/zoo_server.pl -rd
到目前为止一切顺利 - 我现在可以访问 http://localhost:3000 /user
并看到消息“Matched MyApp::Controller::User in User”。
然后,我将 lib/MyApp/Controller/User.pm 中的第一行 BEGIN 替换为以下行
BEGIN { extends 'Catalyst::Controller::REST' }
在执行其他操作之前,我想检查我执行 POST 请求并观察响应的能力。因此,在另一个终端窗口中,我键入
curl http://localhost:3000/user --verbose --data "<test><m>whatever</m></test>" -H "Content-Type: text/xml"
At 此时,由于我尚未实现任何 POST 方法,因此我希望看到“405 Method Not allowed”响应。相反,我从curl 中看到的是这样的:
* About to connect() to localhost port 3000 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST /user HTTP/1.1
> User-Agent: curl/7.19.6 (i386-apple-darwin10.0.0) libcurl/7.19.6 zlib/1.2.5
> Host: localhost:3000
> Accept: */*
> Content-Type: text/xml
> Content-Length: 28
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
* Closing connection #0
这似乎使catalyst 的测试服务器崩溃。服务器不记录任何内容,但将来尝试联系服务器,例如对“localhost:3000/user”执行另一个 GET 请求,会导致curl 出现“无法连接到主机”错误。
我注意到,只有当我使用 Catalyst::Controller::REST 时才会发生这种情况。如果我只是制作一个常规控制器,发布到它不会导致任何崩溃。所以我假设它发生在反序列化操作上,该操作将委托给 XML::Simple (根据 Catalyst::Controller::REST 的默认值)。有什么想法吗?
顺便说一句,我最终想做的是创建一个类似 sub thing :Local :ActionClass('REST') ...
的方法,以及相应的 sub thing_POST
。我的理解是,在 thing_POST
之前,对包含 XML 的 /user/thing 的 POST 请求应该自动反序列化并将其放入 $c->request->data
中叫。上述测试是对此的初步测试 - 旨在检查如果没有定义 POST 方法会发生什么。 (无论如何,如果我创建 sub thing
和 sub thing_POST
,然后使用curl 向 /user/thing 发出 POST 请求,我会得到完全相同的行为。 )
I'm using Catalyst to build a RESTful web service, so I create a Catalyst controller in the usual way
script/myapp_create.pl controller MyApp::Controller
I then fire up the catalyst test server
script/zoo_server.pl -rd
So far so good - I can now go to http://localhost:3000/user
and see the message "Matched MyApp::Controller::User in User."
I then replace the first BEGIN line in lib/MyApp/Controller/User.pm with the following line
BEGIN { extends 'Catalyst::Controller::REST' }
Before doing anything else, I want to check my ability to execute a POST request and watch the response. So in another terminal window, I type
curl http://localhost:3000/user --verbose --data "<test><m>whatever</m></test>" -H "Content-Type: text/xml"
At this point, since I have not implemented any POST methods, I am expecting to see a "405 Method Not Allowed" response. Instead, what I see from curl is this:
* About to connect() to localhost port 3000 (#0)
* Trying 127.0.0.1... connected
* Connected to localhost (127.0.0.1) port 3000 (#0)
> POST /user HTTP/1.1
> User-Agent: curl/7.19.6 (i386-apple-darwin10.0.0) libcurl/7.19.6 zlib/1.2.5
> Host: localhost:3000
> Accept: */*
> Content-Type: text/xml
> Content-Length: 28
>
* Empty reply from server
* Connection #0 to host localhost left intact
curl: (52) Empty reply from server
* Closing connection #0
This then appears to crash catalyst's test server. The server does not log anything, but future attempts to contact the server, e.g. doing another GET request to "localhost:3000/user", results in "couldn't connect to host" errors from curl.
I note that this only happens if I use Catalyst::Controller::REST. If I just make a regular controller, POSTing to it does not crash anything. So I'm assuming it happens on the deserialization action, which will be delegated to XML::Simple (as per the default for Catalyst::Controller::REST). Any ideas?
What I eventually want to do, by the way, is create a method like sub thing :Local :ActionClass('REST') ...
, and a corresponding sub thing_POST
. My understanding is that POST requests to /user/thing containing XML should then automatically get deserialized and put it into $c->request->data
, before thing_POST
is called. The above tests are a preliminary to this - designed to check what happens if no POST method is defined. (For what it's worth, I get exactly the same behavior if I create sub thing
and sub thing_POST
, and then use curl to issue a POST request to /user/thing.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我最终将其追溯到 XML::SAX。可重现的错误情况:
请注意,如果引用 XML,而不是在文件中,则它可以正常工作:
我猜我的 XML::SAX 安装出了问题。
I eventually traced this to XML::SAX. Reproducible bug condition:
Note that it works fine if the XML is quoted, rather than in a file:
Something wrong with my XML::SAX installation, I guess.
您已经定义了附加了 :Local 属性的操作 thing,这意味着分派的路径是 /user/thing (而不是那样,您将数据发布到 /user)。可能您想检查 Catalyst 手册 - 操作类型介绍
或者,如果您仍然遇到一些问题,您可以尝试在官方 #catalyst irc 频道询问。
You've defined your action thing with :Local attribute attached, which means the path which is dispatched is /user/thing (instead of that, you are posting your data to /user). May be you would like to check the Catalyst Manual - Action Types introduction
Alternatively, if you still experience some problems you could try asking at the official #catalyst irc channel.