如何在ruby CGI脚本中访问原始请求主体?

时间:2018-09-16 11:17:37

标签: ruby cgi

在作为CGI程序运行的ruby脚本中,我需要访问HTTP POST请求的主体。请求正文包含JSON数据:

{"data":"a"}

我想将整个正文解析为JSON.parse进行处理。规范的做法是什么? Ruby docs没有提及请求正文。

我只在blog post中发现了一个提示

  

CGI尝试将请求正文解析为表单参数,因此一堆JSON笨拙地成为唯一的一个参数键。

这种方法似乎有效

puts cgi.params.keys.first # prints {"data":"a"}

但是一旦data的值是base64编码的字符串,其中包含用于填充的=就会失败:

{"data":"a="}

产生以下输出(末尾缺少字符):

puts cgi.params.keys.first # prints {"data":"a

解决此问题的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

您可能已经知道,对参数及其值进行urlencode时,它们用=name=Theo&language=ruby来定界,依此类推。

这就是第一个参数的名称停在=前面的字符处的原因。如该博文中所述,使用第一把钥匙的方法并不可靠。

相反,在CGI脚本中,您可以直接从stdin中读取请求正文,例如

request_body = $stdin.read

注意,当实例化一个CGI对象时,它将从stdin中读取所有内容,并尝试将其解析为params哈希。

这意味着,如果您仍想使用cgi库来构建响应,则需要在代码中的之前之前从stdin中读取,然后创建CGI对象。例如

# minimal example that just outputs the request body
require 'cgi'

request_body = $stdin.read

cgi = CGI.new

cgi.out("status" => "OK", "type" => "text/plain", "connection" => "close") do
  request_body
end

答案 1 :(得分:1)

显然,在Ruby中没有简单的解决方案。

但是有两种方法可以实现这一目标。

  1. 重新定义for folders in "${SFA[@]}" do echo /media/$SFA done 方法。 CGI模块中的此方法负责将POST和GET参数解析为params哈希。您可以在代码中重新定义此方法,以便在CGI::parse(params)哈希中添加一个名为RAW_DATA的额外参数。

    params
  2. 在创建CGI实例之前使用def CGI::parse(query) params = {} query.split(/[&;]/).each do |pairs | key, value = pairs.split('=', 2).collect { | v | CGI::unescape(v) } next unless key params[key] || = [] params[key].push(value) if value end #Add RAW_DATA to params params[:RAW_DATA] = query params.default = [].freeze params end 。 但这可能会阻止您使用其他CGI功能。

    因此,您可以将$ stdin临时替换为StringIO对象。

    $stdin.read()