10

I'm trying to write some Rack Middleware for a Rails 4.2 app that alters the response body using the gsub method. I found older examples that use a pattern like this:

class MyMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    # do some stuff
    [status, headers, response]
  end
end

What I'm finding is that there is no setter method for response.body. Is there another pattern I can start with to go about modifying the body?

rb-
  • 2,315
  • 29
  • 41

1 Answers1

13

The problem was that it expects an Array for the 3rd argument in the call method. This pattern got me working again.

# not real code, just a pattern to follow
class MyMiddleware
  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, response = @app.call(env)
    new_response = make_new_response(response.body)
    # also must reset the Content-Length header if changing body
    headers['Content-Length'] = new_response.bytesize.to_s
    [status, headers, [new_response]]
  end
end
Nowaker
  • 12,154
  • 4
  • 56
  • 62
rb-
  • 2,315
  • 29
  • 41
  • What is `make_new_response`? – Ozymandias Dec 05 '16 at 15:45
  • @AjaxLeung Anything you want. Just an example. Takes a string, returns a string. – JohnMetta Dec 16 '16 at 18:27
  • If you use `status, headers, response = @app.call(env)` on the first place, then everything after won't be able to "stop" the request. You skip the middleware stack for your middleware. – brcebn Oct 02 '20 at 11:04
  • I've updated the code from `new_response.length` to `new_response.bytesize`. The previous code would make the browsers truncate some of the response, as instructed by Content-Length. – Nowaker Oct 09 '20 at 17:42