Skip to content

Middleware is not thread safe #108

@pbstriker38

Description

@pbstriker38

def call is creating an instance variable of @request. This is not thread safe and causes undefined method 'helpers' for nil (NoMethodError) because another request has come in and replaced @request with a non interceptable_request?.

There are 2 approaches to fix this.

Option 1

dup the middleware in call. This seems wasteful.

def call(env)
  dup._call(env)
end

def _call(env)
  status, headers, response = @app.call(env)

  @request = ActionDispatch::Request.new(env)

  if interceptable_request? && html_response?(headers)
    html = html_from(response)
    html = inject_options(html)
    html = inject_javascript(html)
    headers["Content-Length"] = html.bytesize.to_s if html
    response = [ html ]
  end

  [ status, headers, response ]
end

Option 2

Do not use instance variables in call and pass local variables where necessary.

def call(env)
  status, headers, response = @app.call(env)

  request = ActionDispatch::Request.new(env)

  if interceptable_request?(request) && html_response?(headers)
    view_helpers = request.controller_instance.helpers
    html = html_from(response)
    html = inject_options(html, view_helpers)
    html = inject_javascript(html, view_helpers)
    headers["Content-Length"] = html.bytesize.to_s if html
    response = [ html ]
  end

  [ status, headers, response ]
end

Let me know which option is preferable and I can work on the pull request.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions