I have a custom rack middleware used by my Rails 4 application. The middleware itself is just here to default Accept
and Content-Type
headers to application/json
if the client did not provide a valid information (I'm working on an API). So before each request it changes those headers and after each request it adds a custom X-Something-Media-Type head with a custom media type information.
I would like to switch to Puma, therefore I'm a bit worried about the thread-safety of such a middleware. I did not play with instances variables, except once for the common @app.call
that we encounter in every middleware, but even here I reproduced something I've read in RailsCasts' comments :
def initialize(app)
@app = app
end
def call(env)
dup._call(env)
end
def _call(env)
...
status, headers, response = @app.call(env)
...
Is the dup._call
really useful in order to handle thread-safety problems ?
Except that @app
instance variable I only play with the current request built with the current env variable :
request = Rack::Request.new(env)
And I call env.update
to update headers and forms informations.
Is it dangerous enough to expect some issues with that middleware when I'll switch from Webrick
to a concurrent web server such as Puma
?
If yes, do you know a handful way to make some tests en isolate portions of my middleware which are non-thread-safe ?
Thanks.
Yes, it's necessary to dup
the middleware to be thread-safe. That way, anything instance variables you set from _call
will be set on the duped instance, not the original. You'll notice that web frameworks that are built around Rack work this way:
One way to unit test this is to assert that _call
is called on a duped instance rather than the original.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With