Skip to content

Commit

Permalink
errors: add a catch-all handler to give feedback to the proxy user
Browse files Browse the repository at this point in the history
This generic error handler helps to give context in case of target
server errors.

Indeed without this commit, the user of the proxy would see a `500
Internal server error`. Now, with the current change the real error is
catched and a 502 HTTP error is responded to the user, with some
details in a json object `{error: error.message}`.

E.g. when targeting a server which has a bad SSL certificate, the user
will now receive this response:

```
HTTP/1.1 502 Bad Gateway
access-control-allow-origin: *
access-control-allow-methods: OPTIONS
access-control-allow-methods: GET
access-control-allow-methods: POST
access-control-allow-methods: PUT
access-control-allow-methods: PATCH
access-control-allow-methods: DELETE
access-control-allow-headers: Content-Type, Authorization, x-bump-proxy-token, x-requested-with
content-type: application/json
x-content-type-options: nosniff
Content-Length: 127

{"error":"SSL_connect returned=1 errno=0 peeraddr=212.95.74.75:443 state=error: certificate verify failed (hostname mismatch)"}
```
  • Loading branch information
paulRbr committed Nov 25, 2024
1 parent 1046d84 commit aa080b4
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 1 deletion.
4 changes: 4 additions & 0 deletions proxy_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ class ProxyServer < Sinatra::Base
halt 401, {error: "Token has #{error.to_s.downcase}"}.to_json
end

error do |error|
halt 502, {error: error.message}.to_json
end

# Handle CORS headers
before do
headers "Access-Control-Allow-Origin" => "*",
Expand Down
24 changes: 23 additions & 1 deletion spec/proxy_server_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
include Rack::Test::Methods

def app
ProxyServer
@app ||= ProxyServer
end

def expect_header(k, v)
Expand Down Expand Up @@ -187,6 +187,28 @@ def expect_json_body(k, v)
expect_header("access-control-allow-origin", "*")
end
end

context "when target request returns an error" do
before(:each) do
# This sinatra config setting simulates the production
# behavior (because in dev/test the generic error handler is
# not called, instead errors are raised for real)
@app = Sinatra.new(ProxyServer) do
set :raise_errors, false
end
stub_request(:get, "https://jsonplaceholder.typicode.com/posts")
.to_raise(OpenSSL::SSL::SSLError)
header "x-bump-proxy-token", proxy_token
header "Content-Type", "application/json"
get "/#{target_url}"
end

it "returns a 502 and forwards the error message" do
expect(last_response.status).to eq(502)
response_body = JSON.parse(last_response.body)
expect(response_body["error"]).to eq("Exception from WebMock")
end
end
end

context "but is invalid" do
Expand Down

0 comments on commit aa080b4

Please sign in to comment.