红宝石sinatra之谜

时间:2012-12-10 22:47:09

标签: ruby sinatra

我有以下Sinatra代码:

post '/bucket' do
  # determine if this call is coming from filling out web form
  is_html = request.content_type.to_s.downcase.eql?('application/x-www-form-urlencoded')

  # If this is a curl call, then get the params differently
  unless is_html
      params = JSON.parse(request.env["rack.input"].read)
  end

  p params[:name]
end

如果我使用Curl调用此方法,params会有值,但是当通过网络表单调用时,paramsnilparams[:name]则没有。我花了几个小时搞清楚它为什么会发生并向其他人寻求帮助,但没有人能真正知道发生了什么。

有一点需要注意的是,如果我注释掉这一行:

params = JSON.parse(request.env["rack.input"].read)

然后params具有“网络表单”发布的正确值。

实际上,如果CURL调用调用此代码,目标是获取params值,因此我使用了:

params = JSON.parse(request.env["rack.input"].read)

但它搞砸了网络形式的帖子。谁能解开这个谜团?

1 个答案:

答案 0 :(得分:2)

就个人而言,我会通过在表单中​​设置隐藏值来做不同的事情,例如:

<input type="hidden" name="webform" value="true">

然后使用它:

if (params['webform'])
  # this is a request from the form
else
  # this is a request from Curl
end

如果您看到它,您就知道该请求来自您的网络表单。如果params['webform']不存在则不是来自Curl。

我把它保存到一个文件中并用Ruby运行它:

require 'sinatra'

get '/bucket' do
  params[:name]
end

使用http://localhost:4567/bucket?name=foo调用正在运行的脚本显示:

foo

在浏览器中。

如果我修改源代码如下:

require 'sinatra'

post '/bucket' do
  params[:name]
end

重新启动它并加载一个简单的HTML文件:

<html>
  <body>
    <form name="form" method="post" action="http://localhost:4567/bucket">
      <input type="hidden" name="webform" value="true"></input>
      <input type="input" name="name"></input>
      <input type="submit"></input>
    </form>
  </body>
</html>

并输入foobar并提交,我看到了:

foobar

在浏览器窗口中。

如果我将脚本更改为:

require 'sinatra'

post '/bucket' do
  if (params[:webform])
    'webform is set'
  else
    'webform is not set'
  end
end

然后重新启动Sinatra并重新提交表单,我看到了:

webform is set

如果我使用Curl调用它:

curl --data "name=foo" http://127.0.0.1:4567/bucket

我在命令行上看到这个作为Curl的回复:

webform is not set

如果我将脚本更改为:

require 'sinatra'

post '/bucket' do
  if (params[:webform])
    'webform is set'
  else
    params[:name]
  end
end

重新启动脚本,再次使用Curl命令调用它,我看到了:

foo

在命令行上。