Alter response.body in Rack Middleware
Asked Answered
A

1

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?

Annorah answered 10/4, 2015 at 15:9 Comment(0)
A
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
Annorah answered 13/4, 2015 at 18:46 Comment(4)
What is make_new_response?Abdominous
@AjaxLeung Anything you want. Just an example. Takes a string, returns a string.Contrabassoon
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.Haunch
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.Ingraft

© 2022 - 2024 — McMap. All rights reserved.