Skip to content

Commit

Permalink
Refactor Request::Writer specs
Browse files Browse the repository at this point in the history
Revealed and fixed Transfer-Encoding double entry
  • Loading branch information
ixti committed Nov 17, 2014
1 parent dbeab17 commit b851b9c
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 30 deletions.
9 changes: 2 additions & 7 deletions lib/http/request/writer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,8 @@ def stream
def add_body_type_headers
if @body.is_a?(String) && !@headers['Content-Length']
@request_header << "Content-Length: #{@body.bytesize}"
elsif @body.is_a?(Enumerable)
encoding = @headers['Transfer-Encoding']
if encoding == 'chunked'
@request_header << 'Transfer-Encoding: chunked'
else
fail(RequestError, 'invalid transfer encoding')
end
elsif @body.is_a?(Enumerable) && 'chunked' != @headers['Transfer-Encoding']
fail(RequestError, 'invalid transfer encoding')
end
end

Expand Down
94 changes: 71 additions & 23 deletions spec/http/request/writer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,41 +3,89 @@
require 'spec_helper'

RSpec.describe HTTP::Request::Writer do
let(:io) { StringIO.new }
let(:body) { '' }
let(:headers) { HTTP::Headers.new }
let(:headerstart) { 'GET /test HTTP/1.1' }

subject(:writer) { described_class.new(io, body, headers, headerstart) }

describe '#initalize' do
def construct(body)
HTTP::Request::Writer.new(nil, body, [], '')
end
context 'when body is nil' do
let(:body) { nil }

it "doesn't throw on a nil body" do
expect { construct nil }.not_to raise_error
it 'does not raise an error' do
expect { writer }.not_to raise_error
end
end

it "doesn't throw on a String body" do
expect { construct 'string body' }.not_to raise_error
end
context 'when body is a string' do
let(:body) { 'string body' }

it "doesn't throw on an Enumerable body" do
expect { construct %w(bees cows) }.not_to raise_error
it 'does not raise an error' do
expect { writer }.not_to raise_error
end
end

it "does throw on a body that isn't string, enumerable or nil" do
expect { construct true }.to raise_error
context 'when body is an Enumerable' do
let(:body) { %w(bees cows) }

it 'does not raise an error' do
expect { writer }.not_to raise_error
end
end

it 'writes a chunked request from an Enumerable correctly' do
io = StringIO.new
writer = HTTP::Request::Writer.new(io, %w(bees cows), [], '')
writer.send_request_body
io.rewind
expect(io.string).to eq "4\r\nbees\r\n4\r\ncows\r\n0\r\n\r\n"
context 'when body is not string, enumerable or nil' do
let(:body) { 123 }

it 'raises an error' do
expect { writer }.to raise_error
end
end
end

describe '#add_body_type_headers' do
it 'properly calculates length of unicode string' do
writer = HTTP::Request::Writer.new(nil, 'Привет, мир!', {}, '')
writer.add_body_type_headers
expect(writer.join_headers).to match(/\r\nContent-Length: 21\r\n/)
describe '#stream' do
context 'when body is Enumerable' do
let(:body) { %w(bees cows) }
let(:headers) { HTTP::Headers.coerce 'Transfer-Encoding' => 'chunked' }

it 'writes a chunked request from an Enumerable correctly' do
writer.stream
expect(io.string).to end_with "\r\n4\r\nbees\r\n4\r\ncows\r\n0\r\n\r\n"
end

it 'writes Transfer-Encoding header only once' do
writer.stream
expect(io.string).to start_with "#{headerstart}\r\nTransfer-Encoding: chunked\r\n\r\n"
end

context 'when Transfer-Encoding not set' do
let(:headers) { HTTP::Headers.new }
specify { expect { writer.stream }.to raise_error }
end

context 'when Transfer-Encoding is not chunked' do
let(:headers) { HTTP::Headers.coerce 'Transfer-Encoding' => 'gzip' }
specify { expect { writer.stream }.to raise_error }
end
end

context 'when body is a unicode String' do
let(:body) { 'Привет, мир!' }

it 'properly calculates Content-Length if needed' do
writer.stream
expect(io.string).to start_with "#{headerstart}\r\nContent-Length: 21\r\n\r\n"
end

context 'when Content-Length explicitly set' do
let(:headers) { HTTP::Headers.coerce 'Content-Length' => 12 }

it 'keeps given value' do
writer.stream
expect(io.string).to start_with "#{headerstart}\r\nContent-Length: 12\r\n\r\n"
end
end
end
end
end

0 comments on commit b851b9c

Please sign in to comment.