🚀 See the 2024 Ruby on Rails Community Survey results!
Article  |  Development

Debugging HTTP Requests with Sinatra

Reading time: ~ 2 minutes

Debugging HTTP Requests with Sinatra

Recently I was working on a task where I was attempting to connect to a third party API (from a Rails app using the HTTParty gem). The API had a fairly complicated authorization header that needed to be built, by concatenating the body of the request itself along with various authorization headers, then being hashed, and then being base64 encoded and escaped. If the header was improperly formed, all I saw was a 403 Forbidden response - not particularly helpful for debugging.

Building a simple debugging server

I could debug the process of actually building the header by logging to the console, but that couldn't verify a couple important things:

  • Whether the header was then actually being included in the request being sent to the API
  • Whether the header value was set to the value I expected, and that the HTTParty gem was not modifying the header in some way that I wasn't aware of

I wanted to come up with a way that I could verify these, so that then I could focus on debugging the building of the header itself. I'd used Sinatra before for lightweight applications, so I thought I'd use it to run a local server with a route that would simply print out all of the headers and values included in my request.

require 'sinatra'
require 'json'

get '/view-headers' do
  content_type :text
  puts JSON.pretty_generate(request.env)
end

Assuming that this file is named debug_server.rb, it can be run with $ ruby debug_server.rb

Making the request

Once the server is running, it will log to the console by default (this can be configured, see the Sinatra Docs).

In my case, I was making the request from a Rails application using the HTTParty module, but there is nothing Rails or Ruby specific about this use case. Here's a rough approximation of the class that was making the request:

require 'httparty'

class APIClient
  include HTTParty

  # Standard Sinatra address
  base_uri "127.0.0.1:4567"

  # This is a method to build your header based on the requirements of the API
  def build_header
    "This is the header method that I'm trying to test"
  end

  def test_header_in_request
    uri = "/view-headers"
    auth_header = build_header
    headers = { "Test-Header-Name" => auth_header }
    self.class.get(uri, headers: headers)
  end
end

In this case the build_header method is quite simple, but could be as complex as you want. When the test_header_in_request method is called, the request is sent with the additional "Test-Header" being set.

Viewing the request headers

Now, in my console where Sinatra is running, I can see the output of this request: Console Output And I can see that my header is included, with the value I expect. Pretty handy! And if I want to filter what is printed or add any other logic, I can do that in my Sinatra route - request.env is just a hash of the request, and the request object has other methods that are useful for debugging as well.

I've put all of the code shown here in a git repository if you want to experiment for yourself. Good luck!

Have a project that needs help?