Sinatra控制器params方法在JSON发布请求中为空 [英] Sinatra controller params method coming in empty on JSON post request

查看:102
本文介绍了Sinatra控制器params方法在JSON发布请求中为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Sinatra应用程序,并且在我的大多数控制器中,json均会传入并在params对象中自动获取.但是,除非我用before方法拉出request.body参数将它们解析为JSON并将它们合并到params哈希中,否则我将获得一个根本不会获得params的后期操作.

I've got a Sinatra app and in most of my controllers json comes in and is picked up automatically in the params object. However, I've got a post action that doesn't get the params at all unless I play a trick with a before method to pull the request.body parameters parse them as JSON and merge them into the params hash.

这里是控制器,以及过滤方法:

Here is the controller, along with the filter method:

before do
  if request.request_method == "POST"
    body_parameters = request.body.read
    params.merge!(JSON.parse(body_parameters))
  end
end


post '/locations/new' do
  content_type :json
  puts "params after post params method = #{params.inspect}"
  ... other code ...
end

我看到的输出基本上是控制器动作中的参数实际上正确地存在于其中.但是,如果我注释掉before调用,则参数为空.

The output I see is basically that the parameters in the controller action actually are in there correctly. However, if I comment out the before call the params are empty.

之前的感觉本身就像是骇客.我希望这些参数无论如何都会出现...我在那里肯定做错了什么,但我不知道那是什么.

The before itself feels like a hack. I would expect those params to come in no matter what...I must be doing something wrong in there but I don't know what it is.

任何帮助将不胜感激...

Any help would be deeply appreciated...

推荐答案

为了回答这个问题,我们首先要看一些HTTP请求(仅是简单的telnet'messages' ;可以很容易地手动创建).首先,当您提交普通的HTML <form>时会发生什么? POST请求看起来与此非常相似(可能带有一些额外的参数,但是我们现在不必担心这一点):

In order to answer this question, we're first going to have to look at some HTTP requests (which are no more than simple telnet 'messages'; this can easily be recreated by hand). First, what happens when you submit a normal HTML <form>? The POST request will look very similar to this (probably with some extra parameters, but we don't need to worry about that right now):

POST /submit-form HTTP/1.1
Host: localhost
Content-Type: application/x-www-form-urlencoded
Content-Length: 12

name=JohnDoe

按字符键入字符(将/sample-form替换为任何形式操作的URL,并将Host替换为您的IP或主机名)将与您的浏览器发送的内容相同.要学习的重要内容是参数语法:formname=formvalue. Sinatra使用此语法将POST请求的正文解释为params哈希!!因此,与此基本不兼容的JSON请求将显示在因此,params哈希.

Typing that character-by-character (replacing the /sample-form with whatever the URL is for any form action, and the Host with your IP or hostname) will be same thing your browser would send. The important thing to learn from this is the parameter syntax: formname=formvalue. Sinatra interprets the body of the POST request into the params hash using this syntax! Therefore, JSON requests, being substantially incompatible with this, will not show up in the params hash because of this.

但是,您在before块中所做的事情显示了正确的解决方案.上面的params{'name' => 'JohnDoe'},而request.body.read将返回原始正文name=JohnDoe.

However, what you're doing in your before block shows the proper solution. While params from the above would be {'name' => 'JohnDoe'}, request.body.read will return the original body, name=JohnDoe.

了解了这一点,就可以理解为什么"hacky"解决方案有效:POST请求的原始主体由JSON.parse解释,然后插入到空的params哈希中.看起来很笨拙的原因是因为params在此示例中是不必要的中间人.应该执行以下操作:

In knowing this, one can come to understand why your 'hacky' solution works: the original body of the POST request gets interpreted by JSON.parse, then gets inserted into the empty params hash. The reason it seems hacky is because params is a needless middleman in this example. The following should do the job:

post '/locations/new' do
    @json = JSON.parse(request.body.read)
    # @json now contains a hash of the submitted JSON content
end

但是,采用更好做法的解决方案要么仅在提供JSON内容时响应,要么在提交标准表单时做出不同响应.从上面的示例HTTP POST请求中可以看出,HTML表单用application/x-www-form-urlencoded MIME类型标识,而JSON用application/json标识.如果您要检查POST请求的MIME类型的细节,请查看此问题,并提供一些很好的答案有关如何执行此操作的信息与Sinatra合作!

However, a solution exercising better practice would either only respond if JSON content is provided, or respond differently if a standard form is submitted. As seen in the above example HTTP POST request, an HTML form is identified with the application/x-www-form-urlencoded MIME type, whereas JSON is identified with application/json. If you want the specifics on checking the POST request's MIME type, check out this question with some great answers on how to do this with Sinatra!

这篇关于Sinatra控制器params方法在JSON发布请求中为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆