Skip to content

Commit

Permalink
Merge pull request #119 from kovyrin/kovyrin/expose-response-headers
Browse files Browse the repository at this point in the history
Expose response HTTP headers to the caller
  • Loading branch information
arthurnn authored Jul 12, 2024
2 parents c9c8b5e + c2d2d92 commit a61951f
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 7 deletions.
11 changes: 7 additions & 4 deletions lib/twirp/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -178,23 +178,26 @@ def rpc(rpc_method, input, req_opts=nil)
# natively with twirp-ruby. For normal Faraday, this is a noop.
def rpc_response_thennable(resp)
return yield resp unless resp.respond_to?(:then)

resp.then do |resp|
yield resp
end
end

def rpc_response_to_clientresp(resp, content_type, rpcdef)
if resp.status != 200
return ClientResp.new(error: self.class.error_from_response(resp))
return ClientResp.new(error: self.class.error_from_response(resp), headers: resp.headers)
end

if resp.headers['Content-Type'] != content_type
return ClientResp.new(error: Twirp::Error.internal("Expected response Content-Type #{content_type.inspect} but found #{resp.headers['Content-Type'].inspect}"))
return ClientResp.new(
error: Twirp::Error.internal("Expected response Content-Type #{content_type.inspect} but found #{resp.headers['Content-Type'].inspect}"),
headers: resp.headers
)
end

data = Encoding.decode(resp.body, rpcdef[:output_class], content_type)
return ClientResp.new(data: data, body: resp.body)
return ClientResp.new(data: data, body: resp.body, headers: resp.headers)
end

end
Expand Down
4 changes: 2 additions & 2 deletions lib/twirp/client_json.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,11 @@ def rpc(rpc_method, attrs={}, req_opts=nil)

def rpc_response_to_clientresp(resp)
if resp.status != 200
return ClientResp.new(error: self.class.error_from_response(resp))
return ClientResp.new(error: self.class.error_from_response(resp), headers: resp.headers)
end

data = Encoding.decode_json(resp.body)
return ClientResp.new(data: data, body: resp.body)
return ClientResp.new(data: data, body: resp.body, headers: resp.headers)
end

end
Expand Down
4 changes: 3 additions & 1 deletion lib/twirp/client_resp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,13 @@ class ClientResp
attr_accessor :data
attr_accessor :body
attr_accessor :error
attr_accessor :headers

def initialize(data: nil, body: nil, error: nil)
def initialize(data: nil, body: nil, error: nil, headers: nil)
@data = data
@error = error
@body = body
@headers = headers
end
end
end
3 changes: 3 additions & 0 deletions test/client_json_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ def test_client_json_success
assert_nil resp.error
refute_nil resp.data
assert_equal 3, resp.data["blah_resp"]
refute_nil resp.headers
end

def test_client_json_thennable
Expand Down Expand Up @@ -77,6 +78,7 @@ def test_client_json_error
refute_nil resp.error
assert_equal :invalid_argument, resp.error.code
assert_equal "dont like empty", resp.error.msg
refute_nil resp.headers
end

def test_client_bad_json_route
Expand All @@ -88,6 +90,7 @@ def test_client_bad_json_route
assert_nil resp.data
refute_nil resp.error
assert_equal :bad_route, resp.error.code
refute_nil resp.headers
end


Expand Down
8 changes: 8 additions & 0 deletions test/client_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ def test_proto_serialized_request_body_attrs
resp = c.make_hat(inches: 666)
assert_nil resp.error
refute_nil resp.data
refute_nil resp.headers
end

def test_proto_serialized_request_body
Expand All @@ -128,6 +129,7 @@ def test_proto_serialized_request_body
resp = c.make_hat(Example::Size.new(inches: 666))
assert_nil resp.error
refute_nil resp.data
refute_nil resp.headers
end

def test_proto_twirp_error
Expand All @@ -139,6 +141,7 @@ def test_proto_twirp_error
refute_nil resp.error
assert_equal :internal, resp.error.code
assert_equal "something went wrong", resp.error.msg
refute_nil resp.headers
end

def test_proto_intermediary_plain_error
Expand All @@ -153,6 +156,7 @@ def test_proto_intermediary_plain_error
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
assert_equal "Response is not JSON", resp.error.meta[:not_a_twirp_error_because]
assert_equal "plain text error from proxy", resp.error.meta[:body]
refute_nil resp.headers
end

def test_proto_redirect_error
Expand All @@ -166,6 +170,7 @@ def test_proto_redirect_error
assert_equal "Unexpected HTTP Redirect from location=http://rainbow.com", resp.error.msg
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
assert_equal "Redirects not allowed on Twirp requests", resp.error.meta[:not_a_twirp_error_because]
refute_nil resp.headers
end

def test_proto_missing_response_header
Expand All @@ -176,6 +181,7 @@ def test_proto_missing_response_header
refute_nil resp.error
assert_equal :internal, resp.error.code
assert_equal 'Expected response Content-Type "application/protobuf" but found nil', resp.error.msg
refute_nil resp.headers
end

def test_error_with_invalid_code
Expand All @@ -187,6 +193,7 @@ def test_error_with_invalid_code
refute_nil resp.error
assert_equal :internal, resp.error.code
assert_equal "Invalid Twirp error code: unicorn", resp.error.msg
refute_nil resp.headers
end

def test_error_with_no_code
Expand All @@ -201,6 +208,7 @@ def test_error_with_no_code
assert_equal "true", resp.error.meta[:http_error_from_intermediary]
assert_equal 'Response is JSON but it has no "code" attribute', resp.error.meta[:not_a_twirp_error_because]
assert_equal '{"msg":"I have no code of honor"}', resp.error.meta[:body]
refute_nil resp.headers
end

# Call .rpc on JSON client
Expand Down

0 comments on commit a61951f

Please sign in to comment.