如何读取机架请求中的POST数据

use*_*220 21 ruby rack

当我运行curl命令时

curl -v -H "Content-type: application/json" -X POST -d '{"name":"abc", "id":"12", "subject":"my subject"}' http://localhost:9292
Run Code Online (Sandbox Code Playgroud)

要将带有数据的POST请求发送到我的Rack应用程序,我的代码打印出来{}.这来自puts req.POST()下面的代码.

为什么打印出来{}而不是POST数据?如何在Rack应用程序中正确访问POST数据?

require 'json'

class Greeter
  def call(env)
    req = Rack::Request.new(env)
    if req.post?
      puts req.POST()
    end
    [200, {"Content-Type" => "application/json"}, [{x:"Hello World!"}.to_json]]
  end
end

run Greeter.new
Run Code Online (Sandbox Code Playgroud)

Nei*_*ter 23

从阅读POST的文档,看起来它是基于其他内容类型为您提供解析数据.如果你想处理"application/json",你可能需要

JSON.parse( req.body.read )
Run Code Online (Sandbox Code Playgroud)

代替.要检查这一点,请尝试

puts req.body.read
Run Code Online (Sandbox Code Playgroud)

你现在的位置puts req.POST.


req.body是一个I/O对象,而不是一个字符串.请参阅body文档并查看源代码.您可以看到这实际上与mudasobwa的答案相同.

请注意,Rack应用程序中的其他代码可能会读取相同的I/O,例如Sinatra或Rails中的param解析器.为了确保它们看到相同的数据而不会出现错误,您可能需要req.body.rewind在读取代码中的请求正文之前和之后调用.但是,如果您处于这种情况,您可能会考虑您的框架是否具有通过控制器上的某个选项直接处理JSON或请求内容类型处理程序声明等的选项 - 很可能会有一个选项来处理这种类型的框架内的请求.

  • 仅供参考 - 从中​​间件读取I/O流可能会破坏Rails应用程序.当你得到这个值时,你需要确保运行`req.env ['rack.input'].rewind`来重置流. (2认同)
  • @lookitsatravis 同样的用例把我带到了这里。我相信您早已解决了您的问题,但对于任何阅读的人来说:在尝试通过机架攻击中的帖子正文数据进行过滤时,最简单的方法就是将 ActiveSupport 导入到文件中。读取和倒回 I/O 流是一个非常烦人的过程。 (2认同)

Ale*_*kin 11

尝试:

env['rack.input'].read
Run Code Online (Sandbox Code Playgroud)

我在" 如何使用Rack接收JSON对象 "中找到它,虽然它对我来说仍然听起来很奇怪,但它可能有效.

  • 它不仅会读取第一个lin,它还会为流提供一个分隔符(默认为`\n`).这会破坏JSON解析和请求签名等内容.更好的做`env [''rack.input'].阅读` (4认同)
  • fyi,`gets`只读第一行 (2认同)