我正在Ruby中编写一个模拟服务器来测试我们的内部API。我想在服务器响应中包含一个POST请求体。我使用Net::HTTP::Server和Net::HTTP类。 现在模拟服务器看起来像这样:
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:
我做错了什么?
答案 0 :(得分:2)
不支持发布请求。它们不包含在规范中。如果请求主体内容长度不是4096的倍数,则调用stream.body将阻塞。
因https://github.com/postmodern/net-http-server/blob/master/lib/net/http/server/stream.rb调用
IO.read(4096, '')
如果您事先不知道尺寸,可以通过非阻塞方式读取插座来解决。例如,下面的处理程序将尝试读取Request主体,然后只需在Response主体中返回它。如果标题中提供了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
答案 1 :(得分:1)
我认为net-http-server存在问题。
尝试使用WEBrick作为您的服务器:
require 'webrick'
include WEBrick
def start_webrick(config = {})
config.update(:Port => 8080)
server = HTTPServer.new(config)
yield server if block_given?
['INT', 'TERM'].each {|signal|
trap(signal) {server.shutdown}
}
server.start
end
start_webrick {|server|
server.mount_proc('/') {|req, resp|
resp.body = req.body
}
}
这对我有用,输出是:
country=Ukraine&city=Kiev
答案 2 :(得分:1)
此刻我正在做类似的事情。对于“快速和肮脏”测试,我建议curl。例如:
获取:强>
curl http://localhost:3000/locations"
发表:强>
curl http://localhost:3000/locations -d "location[country]=Ukraine&location[city]=Kiev"
<强> PUT:强>
curl http://localhost:3000/locations/1 -X PUT -d "location[country]=Ukraine"
删除:强>
curl http://localhost:3000/locations/1 -X DELETE"
话虽如此,对于更强大的测试,假设您正在使用Rails / Rack,我使用Cucumber进行API的集成测试。您可以在其中使用rais / rack帮助程序,例如,在用例中,用于POST:
url = "http://localhost:3000/locations/"
hash = { "location" => { "country => "Ukraine", "city" => "Kiev" }
post url, hash