1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
|
require 'spec_helper'
require 'acceptance/webmock_shared'
require 'ostruct'
require 'acceptance/httpclient/httpclient_spec_helper'
describe "HTTPClient" do
include HTTPClientSpecHelper
before(:each) do
WebMock.reset_callbacks
HTTPClientSpecHelper.async_mode = false
end
include_examples "with WebMock"
it "should raise a clearly readable error if request with multipart body is sent" do
stub_request(:post, 'www.example.com').with(body: {type: 'image'})
expect {
HTTPClient.new.post_content('www.example.com', type: 'image', file: File.new('spec/fixtures/test.txt'))
}.to raise_error(ArgumentError, "WebMock does not support matching body for multipart/form-data requests yet :(")
end
it "should yield block on response if block provided" do
stub_request(:get, "www.example.com").to_return(body: "abc")
response_body = ""
http_request(:get, "http://www.example.com/") do |body|
response_body = body
end
expect(response_body).to eq("abc")
end
it "should not yield block on empty response if block provided" do
stub_request(:get, "www.example.com").to_return(body: "")
response_body = ""
http_request(:get, "http://www.example.com/"){ raise }
expect(response_body).to eq("")
end
it "should match requests if headers are the same but in different order" do
stub_request(:get, "www.example.com").with(headers: {"a" => ["b", "c"]} )
expect(http_request(
:get, "http://www.example.com/",
headers: {"a" => ["c", "b"]}).status).to eq("200")
end
describe "when using async requests" do
before(:each) do
HTTPClientSpecHelper.async_mode = true
end
include_examples "with WebMock"
end
it "should work with get_content" do
stub_request(:get, 'www.example.com').to_return(status: 200, body: 'test', headers: {})
str = ''.dup
HTTPClient.get_content('www.example.com') do |content|
str << content
end
expect(str).to eq('test')
end
it "should work via JSONClient subclass" do
stub_request(:get, 'www.example.com').to_return(
status: 200,
body: '{"test": "foo"}',
headers: {'Content-Type' => 'application/json'}
)
content = JSONClient.get('www.example.com').content
expect(content).to eq("test" => "foo")
end
context "multipart bodies" do
let(:header) {{
'Accept' => 'application/json',
'Content-Type' => 'multipart/form-data'
}}
let(:body) {[
{
'Content-Type' => 'application/json',
'Content-Disposition' => 'form-data',
:content => '{"foo": "bar", "baz": 2}'
}
]}
let(:make_request) {HTTPClient.new.post("http://www.example.com", body: body, header: header)}
before do
stub_request(:post, "www.example.com")
end
it "should work with multipart bodies" do
make_request
end
end
context "Filters" do
class Filter
def filter_request(request)
request.header["Authorization"] = "Bearer 0123456789"
request.header.request_uri.query = "webmock=here"
end
def filter_response(request, response)
response.header.set('X-Powered-By', 'webmock')
end
end
before do
@client = HTTPClient.new
@client.request_filter << Filter.new
stub_request(:get, 'www.example.com').with(
query: {'webmock' => 'here'},
headers: {'Authorization' => 'Bearer 0123456789'})
end
it "supports request filters" do
expect(@client.request(:get, 'http://www.example.com/').status).to eq(200)
end
it "supports response filters" do
res = @client.request(:get, 'http://www.example.com/')
expect(res.header['X-Powered-By'].first).to eq('webmock')
end
end
context 'when a client instance is re-used for another identical request' do
let(:client) { HTTPClient.new }
let(:webmock_server_url) {"http://#{WebMockServer.instance.host_with_port}/"}
before { WebMock.allow_net_connect! }
it 'invokes the global_stub_request hook for each request' do
# Mock time to ensure that date headers match
now = Time.now
allow(Time).to receive(:now).and_return(now)
request_signatures = []
WebMock.globally_stub_request do |request_sig|
request_signatures << request_sig
nil # to let the request be made for real
end
http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" })
if defined? HTTP::CookieJar
http_request(:get, webmock_server_url, client: client, headers: { "Cookie" => "bar=; foo=" })
else
# If http-cookie is not present, then the cookie headers will saved between requests
http_request(:get, webmock_server_url, client: client)
end
expect(request_signatures.size).to eq(2)
# Verify the request signatures were identical as needed by this example
expect(request_signatures.first).to eq(request_signatures.last)
end
end
context 'session headers' do
it "client sends a User-Agent header when given an agent_name explicitly to the client" do
user_agent = "Client/0.1"
stub_request(:get, "www.example.com").with(headers: { 'User-agent' => "#{user_agent} #{HTTPClient::LIB_NAME}" })
HTTPClient.new(agent_name: user_agent).get("www.example.com")
end
it "client sends the Accept, User-Agent, and Date by default" do
WebMock.disable_net_connect!
stub_request(:get, "www.example.com").with do |req|
req.headers["Accept"] == "*/*" &&
req.headers["User-Agent"] == "#{HTTPClient::DEFAULT_AGENT_NAME} #{HTTPClient::LIB_NAME}" &&
req.headers["Date"]
end
http_request(:get, "www.example.com")
end
it "explicitly defined headers take precedence over session defaults" do
headers = { 'Accept' => 'foo/bar', 'User-Agent' => 'custom', 'Date' => 'today' }
stub_request(:get, "www.example.com").with(headers: headers)
HTTPClient.new.get("www.example.com", nil, headers)
end
end
context 'httpclient response header' do
it 'receives request_method, request_uri, and request_query from the request header' do
stub_request :get, 'www.example.com'
message = HTTPClient.new.get 'www.example.com'
expect(message.header.request_uri.to_s).to eq('www.example.com')
end
end
context 'httpclient streams response', net_connect: true do
before do
WebMock.allow_net_connect!
WebMock.after_request(except: [:other_lib]) do |_, response|
@response = response
end
end
it 'sets the full body on the webmock response' do
body = ''
HTTPClient.new.request(:get, 'http://www.example.com/') do |http_res, chunk|
body += chunk
end
expect(@response.body).to eq body
end
end
context 'credentials' do
it 'are detected when manually specifying Authorization header' do
stub_request(:get, "http://www.example.com/").with(basic_auth: ['username', 'password']).to_return(status: 200)
headers = {'Authorization' => 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='}
expect(http_request(:get, 'http://www.example.com/', {headers: headers}).status).to eql('200')
end
end
end
|