Ruby 脚本不会将 POST 请求的主体发送到服务器

标签 ruby post request webserver

我正在用 Ruby 编写一个模拟服务器来测试我们的内部 API。我想在服务器响应中包含一个 POST 请求体。我用 Net::HTTP::ServerNet::HTTP类(class)。 现在模拟服务器看起来像这样:

require 'net/http/server'
require 'pp'
require 'json'

Net::HTTP::Server.run(:port => 8080) do |request,stream|
  pp request
  [200, {'Content-Type' => 'text/html'}, [request[:body]]]
end

发送带正文的 POST 请求的脚本是这样的:

require 'net/http'
require 'uri'

url = URI.parse(http://localhost:8080/)
x = {"country" => "Ukraine", "city" => 'Kiev'}

http = Net::HTTP.new(url.host, url.port)
request = Net::HTTP::Post.new(url.path)
request.set_form_data(x)
response = http.request(request)

puts "Request body: #{request.body}"
puts "Response Body: #{response.body}"

但是服务器日志表明 POST 请求不包含正文:

#Output from server    
{:method=>"POST"@0,
 :uri=>{:path=>"/"},
 :version=>"1.1"@12,
 :headers=>
  {"Accept"@17=>"*/*"@25,
   "User-Agent"@30=>"Ruby"@42,
   "Content-Type"@48=>"application/x-www-form-urlencoded"@62,
   "Connection"@97=>"close"@109,
   "Host"@116=>"localhost:8080"@122,
   "Content-Length"@138=>"25"@154}}

#Output from script file:
Request body: country=Ukraine&city=Kiev
Response body:  

我做错了什么?

相关:Parse body of POST reqest in self-made server in Ruby

最佳答案

不支持发布请求。它们不包含在规范中。如果请求体内容长度不是 4096 的倍数,调用 stream.body 将被阻塞。

因为 https://github.com/postmodern/net-http-server/blob/master/lib/net/http/server/stream.rb通话

IO.read(4096, '')

如果您事先不知道大小,可以通过以非阻塞方式读取套接字来绕过。例如,以下处理程序将尝试读取请求主体,然后简单地将其返回到响应主体中。如果在 header 中提供了 Content-Length,它将阻塞等待流发送足够的数据直到指定的字节数。

class PostHandler
 BUF_SIZE = 4096

 def call(request, stream)
    case request[:method].to_s
    when "POST"
        body = nil
        if request[:headers]["Content-Type"] == "application/x-www-form-urlencoded"
            body = readBlock(stream.socket, request[:headers]["Content-Length"].to_i)
        else
            body = readNonblock(stream.socket)
        end
        unless body.nil?
            return [200, {}, [body] ]
        end
     end 

     [404, {}, [""]]
  end 

  private

  # blocking way to read the stream
  def readBlock(socket, length)
    socket.read(length)
  end

  # non-blocking alternative
  # stop reading as soon as it would block
  def readNonblock(socket)
    buffer = ""
    loop {
       begin
           buffer << socket.read_nonblock(BUF_SIZE)
       rescue Errno::EAGAIN
           # Resource temporarily unavailable - read would block
           break
       end
    }
    buffer
  end

end 

关于Ruby 脚本不会将 POST 请求的主体发送到服务器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6651789/

相关文章:

ruby - [...] 在 Ruby 中调用哪个方法?

ruby-on-rails - 抽成 Assets :precompile takes 28 minutes on 1. 9.2

php - 通过 AJAX 发送特殊字符( "&lt"、 "&gt"、 "&amp")

java - Jmeter API : how to add post data to httpsampler

java - RoboSpice:如何在 SpiceRequest 中触发 RequestListener.onRequestFailure 方法

ruby - 在 Mavericks 上禁用 Ruby 的应用程序小睡

ruby - "exception class/object expected"ruby​​ 无法挽救哈希对象

json - 如何在 vuejs 中将 JSON 对象发布到 Web 服务器?

python - 使用Python提取数据

php - Symfony2 - file_get_contents() 在同一项目 api url 上失败