如何使用Ruby Mechanize设置POST请求的主体?

如何使用Ruby Mechanize设置POST请求的主体?,ruby,mechanize-ruby,Ruby,Mechanize Ruby,如何使用Ruby Mechanize gem设置POST请求的主体。我知道你能行 mechanize.post(url, query, headers) 但是我想用JSON字符串设置POST请求的主体。可能吗?因此,与jQuery类似: $.ajax({ type: 'POST', url: 'myurl', data: "{'key1':'value1','key2':'value2'}", ... }); 我真的不喜欢你在评论中链接到的答案,因为它使用了

如何使用Ruby Mechanize gem设置POST请求的主体。我知道你能行

mechanize.post(url, query, headers)
但是我想用JSON字符串设置POST请求的主体。可能吗?因此,与jQuery类似:

$.ajax({
    type: 'POST',
    url:  'myurl',
    data: "{'key1':'value1','key2':'value2'}",
    ...
});

我真的不喜欢你在评论中链接到的答案,因为它使用了to_json(),这是一种rails方法,而你问题的标记并不表示你的问题属于rails。无论如何,我认为答案需要一些讨论

以下是机械化方法:

Mechanize#post(url, query, headers)
…您的既定目标是:

我想设置POST请求的主体

机械化后()允许你将请求的主体设置成你想要的任何东西,但是你也必须考虑这个问题:

What is the server side expecting?  
您给出了一个jquery ajax()请求示例,以了解您想要做什么。jquery在发送ajax()请求时使用以下默认内容类型头:

这告诉服务器post请求的主体将被写入特定的密码中。嗯,这不是什么秘密;看起来是这样的:

name1=val1&name2=val2
该密码的名称是
x-www-form-urlencoded
。因为服务器在内容类型头中被赋予了密码的名称,所以服务器知道如何读取post请求的主体

在Mechanize#post()方法中,第二个参数是'query',Mechanize文档对查询参数这样说:

查询由字符串指定,或

由哈希表示的键值对列表,或

数组的数组

如果您想在Mechanize#post()请求的正文中使用名为
x-www-form-urlencoded
,则可以提供一个包含名称/值对的哈希,例如

my_hash = {
  'data' => '{"key1":"value1","key2":"value2"}'
}
然后调用Mechanize#post(),如下所示:

my_agent.post(
  'http://target_site.com', 
  my_hash, 
  {'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'},
)
json_str = post_variables['data']   
json_str = request.body.read
#Then probably:
hash = JSON.parse(json_str)
然后,Mechanize将使用名为
x-www-form-urlencoded
的密码将“query”散列转换为字符串,并将该字符串插入post请求的正文中。在服务器端,接收post请求的应用程序可以通过如下方式检索json字符串:

my_agent.post(
  'http://target_site.com', 
  my_hash, 
  {'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'},
)
json_str = post_variables['data']   
json_str = request.body.read
#Then probably:
hash = JSON.parse(json_str)
您应该知道,post请求的主体还可以使用其他密码。其中一个名为
json
,它是一个使用javascript语法格式化的字符串,例如:

  '{
    "id": 1,
    "name": "A green door",
    "price": 12.50,
    "tags": ["home", "green"]
  }'
请注意,json格式中没有“=”符号或“&”符号,正如
x-www-form-urlencoded
格式一样,因此
json
密码与
x-www-form-urlencoded
密码大不相同

如果您想在post请求的正文中使用
json
密码,那么在调用
Mechanize#post(url、查询、标题)
时需要更改两件事:

  • 为'query'参数提供字符串
  • 告诉服务器post请求的主体使用了
    json
    密码
  • 像这样:

    json_str = '{"key1":"value1","key2":"value2"}'
    
    my_agent.post(
      'http://target_site.com', 
      json_str, 
      {'Content-Type' => 'application/json'},
    )
    
    为查询参数传递字符串参数时,Mechanize在将字符串插入post请求主体之前不会对该字符串进行任何处理。在服务器端,接收post请求的应用程序可以通过如下操作检索json字符串:

    my_agent.post(
      'http://target_site.com', 
      my_hash, 
      {'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'},
    )
    
    json_str = post_variables['data']   
    
    json_str = request.body.read
    #Then probably:
    hash = JSON.parse(json_str)
    
    一个缺陷是服务器可以忽略Content-Type头,并尝试使用它已经决定的密码读取post请求的主体。如果post请求的主体没有使用服务器期望的密码写入,那么您将得到一个错误


    请注意,您发布的“数据”字符串不是有效的json,因为它在属性和值周围使用单引号。

    这似乎是答案,我在发布前错过了它:-如果这个问题应该关闭,这对meMy来说没关系json字符串非常小且扁平,所以我只是手动生成它,但你是对的,我的问题更一般。还有,关于json无效的一点很好,我甚至没有意识到,因为我发送它的服务器已经接受了它。@RTF,我想你实际上看到的是你在评论中链接到的问题中未接受的答案。显然,这是设置post请求主体的另一种方法。@RTF,在您的ajax()示例中,jquery文档说,如果“数据”是字符串(如您所指定的),那么jquery将不会将字符串处理为
    x-www-form-urlencoded
    格式,因此我回答的部分前提就不存在了。我猜,因为jquery示例没有指定contentType属性,您最终会得到默认的Content-Type头
    application/x-www-form-urlencoded
    ,但帖子正文将采用
    json
    格式,这可能会使服务器出错。在任何情况下,您的jquery示例都充分展示了您想要做的事情——我只是误解了它……请注意,jquery ajax()“data”属性的工作原理与Mechanize#post()“query”参数类似:如果您提供了一个对象/散列,那么对象/散列将转换为
    x-www-urlencoded
    格式的字符串;如果您提供了一个字符串,它将被插入到请求的主体中而不被触及。