Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Disable Content-Type header in Rails / Rack

I'm writing a Rails controller method that returns HTTP 102 (processing):

render nothing: true, status: :processing, content_type: nil

However, I get a Rack::Lint::LintError (by way of unicorn):

Content-Type header found in 102 response, not allowed

I've not found any obvious way to disable this header. Nilling it in response.headers, removing it from the hash, nilling out response.content_type, passing it as nil in the render option, all seem to have no effect.

I read in https://stackoverflow.com/a/4032459/3712 that it is not Rails that adds the header if it's missing, but Rack. However, it's Rack itself that is complaining!

How can the header addition be disabled?

Or am I better off disabling Rack linting?

Or is there something else I'm missing?

PS: I checked the Rack source for the version I'm using (1.4.5): the Content-Type header is not added for status codes with no entity body, which according to rack-1.4.5/lib/rack/utils.rb includes all 1xx status codes. So I don't think it's Rack that's actually adding the header.

PPS: after several hours of debugging, the culprit is the to_a call on the response, which calls assign_default_content_type_and_charset! in actionpack-3.2.11/lib/action_dispatch/http/response.rb:

def assign_default_content_type_and_charset!
  return if headers[CONTENT_TYPE].present?

  @content_type ||= Mime::HTML
  @charset      ||= self.class.default_charset

  type = @content_type.to_s.dup
  type << "; charset=#{@charset}" unless @sending_file

  headers[CONTENT_TYPE] = type
end

There doesn't seem to be much I can do about this without some intrusive hacking, like adding special-purpose middleware, or monkeypatching actionpack's ActionDispatch::Response.

like image 493
Barry Kelly Avatar asked Mar 21 '23 13:03

Barry Kelly


1 Answers

To fix this, I added a new Rails middleware class:

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

  def call(env)
    status, headers, body = @app.call(env)
    # ActionDispatch::Response always inserts Content-Type header
    # Remove it for status codes that don't allow it
    headers.delete('Content-Type') if (100..199).include?(status.to_i)
    return [status, headers, body]
  end
end

Configured thusly in application.rb:

config.middleware.use "::RemoveContentType"

Work for my use case of 102. Solution can be updated to handle other status codes beyond 1xx.

like image 136
Barry Kelly Avatar answered Mar 23 '23 13:03

Barry Kelly