Skip to content

Commit 07f4c9b

Browse files
committed
Change Reynard Request object to set form data.
1 parent a17fcbc commit 07f4c9b

File tree

5 files changed

+75
-8
lines changed

5 files changed

+75
-8
lines changed

lib/reynard/http/request.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ class Reynard
77
class Http
88
# Configures and performs an HTTP request.
99
class Request
10+
MULTIPART_FORM_DATA = "multipart/form-data"
11+
1012
attr_reader :uri
1113

1214
def initialize(request_context:, serializer_selection:)
@@ -36,7 +38,13 @@ def request_headers
3638

3739
def build_request
3840
request = request_class.new(uri, request_headers)
39-
if serializer
41+
if @serializer_selection&.content_type == MULTIPART_FORM_DATA
42+
request.set_form(
43+
serializer.data,
44+
serializer.mime_type,
45+
boundary: serializer.multipart_boundary
46+
)
47+
elsif serializer
4048
write_serializer_body(request)
4149
elsif @request_context.body
4250
write_serializer_params(request)

test/files/ok.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
OK!

test/integration/reynard_test.rb

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,42 @@ def teardown
4848
end
4949
end
5050

51+
test 'creates an object using multipart form data' do
52+
with_simple_service do
53+
name = 'An unexpected occurance'
54+
response =
55+
@reynard
56+
.serializer('application/json', nil)
57+
.operation('createBook')
58+
.body({ 'name' => name })
59+
.execute
60+
assert_equal '200', response.code
61+
book = response.object
62+
assert_kind_of Reynard::Models::Book, book
63+
assert_equal name, book.name
64+
end
65+
end
66+
67+
test 'creates an object using multipart form data including a file' do
68+
filename = File.join(FILES_ROOT, 'ok.txt')
69+
with_simple_service do
70+
File.open(filename) do |file|
71+
name = 'An unexpected occurance'
72+
response =
73+
@reynard
74+
.serializer('application/json', nil)
75+
.operation('createBook')
76+
.body({ 'name' => name, 'avatar' => file })
77+
.execute
78+
assert_equal '200', response.code
79+
book = response.object
80+
assert_kind_of Reynard::Models::Book, book
81+
assert_equal name, book.name
82+
assert_equal File.read(filename), book.avatar
83+
end
84+
end
85+
end
86+
5187
test 'returns an error when fetching an object fails' do
5288
with_simple_service do
5389
response = @reynard.operation('fetchBook').params(id: -1).execute

test/reynard/context_test.rb

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -218,17 +218,16 @@ def setup
218218
end
219219

220220
test 'allows users to post as multipart form data' do
221-
@request_body = nil
222-
stub_request(:post, 'http://example.com/v1/books').with do |request|
223-
@request_body = request.body
224-
end
221+
# Net/HTTP writes the multipart body directly to the socket instead of throught the body
222+
# accessor of the request object so it's not accessible through WebMock.
223+
stub_request(:post, 'http://example.com/v1/books')
225224
data = { 'name' => 'Parcival' }
226-
@context
225+
response = @context
227226
.serializer('application/json', nil)
228227
.operation('createBook')
229228
.body(data)
230229
.execute
231-
assert_includes(@request_body, 'Content-Disposition: form-data')
230+
assert response.success?
232231
end
233232

234233
test 'allows users to post as plain text' do

test/support/simple_service.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@ def service(http_request, http_response)
2525
else
2626
respond_with_not_found(http_response)
2727
end
28+
rescue Exception => e
29+
respond_with_internal_server_error(
30+
http_response,
31+
e.class.to_s,
32+
e.message,
33+
e.backtrace
34+
)
2835
end
2936

3037
private
@@ -34,11 +41,20 @@ def handle_collection(http_request, http_response)
3441
when 'GET'
3542
http_response.body = MultiJson.dump(all)
3643
when 'POST'
37-
book = add(MultiJson.load(http_request.body))
44+
book = add(parse_book(http_request))
3845
http_response.body = MultiJson.dump(book)
3946
end
4047
end
4148

49+
def parse_book(http_request)
50+
case http_request["Content-Type"]
51+
when /^multipart\/form-data/
52+
http_request.query
53+
else
54+
MultiJson.load(http_request.body)
55+
end
56+
end
57+
4258
def handle_member(id, http_response)
4359
book = find(id)
4460
if book
@@ -53,6 +69,13 @@ def respond_with_not_found(http_response)
5369
http_response.body = MultiJson.dump('error' => 'not_found')
5470
end
5571

72+
def respond_with_internal_server_error(http_response, error, message, backtrace)
73+
http_response.status = 500
74+
http_response.body = MultiJson.dump(
75+
'error' => error, 'message' => message, 'backtrace' => backtrace
76+
)
77+
end
78+
5679
def all
5780
@books
5881
end

0 commit comments

Comments
 (0)