我正在用 Ruby 编写一个模拟服务器来测试我们的内部 API。我想在服务器响应中包含一个 POST 请求体。我用 Net::HTTP::Server和 Net::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:
我做错了什么?
最佳答案
不支持发布请求。它们不包含在规范中。如果请求体内容长度不是 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/