Remove charset from Rails content type - ruby-on-rails

I have a old-stupid service making request to my app that fails when the Content-Type include the charset line
Content-Type text/html; charset=utf-8
and I don't know how to remove it from my rails response. Every time that I override the headers forcing just the first part (Content-Type text/html) Rails adds the charset to the header...

For Rails 3/4, the code that handles this is in ActionDispatch::Response.assign_default_content_type_and_charset! in actionpack/lib/action_dispatch/http/response.rb.
Setting response.headers['Content-Type'] instead of response.content_type should eliminate the charset. Chubas' solution does this for all responses.
For Rails 2, the code that handles this is in content_type= and charset= in actionpack/lib/action_controller/response.rb.
As Carson's solution describes, setting ActionController::Base.default_charset = nil should eliminate the charset.

This worked for me:
class MyController
after_filter :remove_charset
def remove_charset
headers['Content-type'] = "text/html"
end
end
If you're working on development, make sure you clear your browser's cache.
There is this method, but didn't work for me. I don't know why, it may even be a bug.

The only way I was able to get it to work is by setting the default charset
ActionController::Base.default_charset = nil
Also, setting the Content-Transfer-Encoding header to binary will turn off the charset.

Putting this in the controller did it for me:
ActionDispatch::Response::default_charset = nil
I put in in my base controller to remove it from all responses.

Related

Rails failing to parse Accept header when charset given

When hitting an API in a Rails app, it seems that certain headers fail to be parsed. For example, this works:
Accept: application/json
But this doesn't:
Accept: application/json; charset=utf-8
Is failing to understand this 2nd header a legitimate problem with the header? Even if it is, how can I make Rails understand it, or at least understand that it's a request for Json?
The issue is that, in Rails 3.2.14, the Mime::Type.parse method does not support specifying a charset parameter in the Accept header; in fact it only supports the "q" parameter (see the Q_SEPARATOR_REGEXP constant).
In Rails 4, however, the method has been updated to support arbitrary parameters (see this commit), so upgrading to Rails 4 should fix this problem.
If you can't upgrade to Rails 4, I would suggest doing a temporary hack in some Rack middleware to strip out the charset (this assumes you don't actually intend to honour the acceptable charset):
class AcceptCharsetStripper
def initialize(app)
#app = app
end
def call(env)
env["HTTP_ACCEPT"].gsub!(/;\s*charset=\S+/, "")
#app.call(env)
end
end

How do you add a custom HTTP response header in Rails?

I'm looking to add custom HTTP response headers to a Ruby on Rails app that is currently hosted on Heroku.
Use:
response.headers['HEADER NAME'] = 'HEADER VALUE'
either in a specific method or to a before_filter method of your application controller depending on whether you need this to be added in a specific or to all of your responses.
UPDATE for Rails 5 - February 24th, 2018
As noted by #BrentMatzelle in the comments, for Rails 5:
response.set_header('HEADER NAME', 'HEADER VALUE')
In rails 5, the following solution works (in action methods)
response.set_header("Header-Name", "Header value")
Reference: edgeapi
In Rails 3 or above, simply
headers['Header-Name'] = 'header value'
works in controllers. This is even the recommended way; according to the documentation,
Response is mostly a Ruby on Rails framework implementation detail, and should never be used directly in controllers. Controllers should use the methods defined in ActionController::Base instead. For example, if you want to set the HTTP response’s content MIME type, then use ActionController::Base#headers instead of Response#headers.
And this is still true in Rails 7.0.
In rails 4, set the response headers in the application.rb or respective environment files. Once you done that, you can override the header value wherever you required in the controller. Refer this url for more details.
In rails 4 works following:
class API::V1::BaseController
after_action :set_version_header
protected
def set_version_header
response.headers['X-ComanyName-Api-Version'] = 'V1'
end
end
If your headers are static, e.g. your own custom Server header, you can simply update config.action_dispatch.default_headers. The following example sets a custom Server header; add it to your config/application.rb or config/environments/...:
config.action_dispatch.default_headers["Server"] = "MyServer/#{config.version}"
(Assuming you set config.version earlier)
For more, see Rails Guides: Configuring Rails Applications: Configuring Action Dispatch:
config.action_dispatch.default_headers is a hash with HTTP headers that are set by default in each response.
This will be less work each request than running a controller callback.
NB: For more than one header use merge! to not remove existing essential XSS etc headers.

Rails 3 application/octet-stream

I am working on an application where I use paperclip for uploading images, then the image is manipulated in a flash app and returned to my application using application/octet-stream. The problem is that the parameters from flash are not available using params. I have seen examples where something like
File.open(..,..) {|f| f.write(request.body) }
but when I do this, the file is damaged some how.
How can I handle this in rails 3?
After you make sure that the request parameters have hit the Rails application, you may want to ensure that there were no parsing problems. Try to add these lines in you controller's action:
def update # (or whatever)
logger.debug "params: #{params.inspect}"
# I hope you do not test this using very large files ;)
logger.debug "request.raw_post: #{request.raw_post.inspect}"
# ...
end
Maybe the variable names got changed somehow? Maybe something escaped the parameter string one time too much?
Also, you have said that the file into which you want to save the request body is damaged. How exactly?
The request.body object does not need to be String. It may be a StringIO, for example, so you may want to type this:
File.open(..,..) {|f| f.write(request.body.read) }

How to remove Set-Cookie header from response in rails 3?

I have some actions that respond with static content. I also need them cached on client.
Similar question was asked in the past for rails 2
Is it possible to omit set-cookie header from the response in Rails 2.3?
Use the built in option.
env['rack.session.options'][:skip] = true
or
request.session_options[:skip] = true
or in older versions use this
env['rack.session.options'][:defer] = true
or
request.session_options[:defer] = true
You can find the documentation for it here http://rack.rubyforge.org/doc/Rack/Session/Abstract/ID.html
Try this: Remove charset from Rails content type or http://guides.rubyonrails.org/action_controller_overview.html#setting-custom-headers
Hope this would help.

How do I view the HTTP response to an ActiveResource request?

I am trying to debug an ActiveResource call that is not working.
What's the best way to view the HTTP response to the request ActiveResource is making?
Monkey patch the connection to enable Net::HTTP debug mode. See https://gist.github.com/591601 - I wrote it to solve precisely this problem. Adding this gist to your rails app will give you Net::HTTP.enable_debug! and Net::HTTP.disable_debug! that you can use to print debug info.
Net::HTTP debug mode is insecure and shouldn't be used in production, but is extremely informative for debugging.
Add a new file to config/initializers/ called 'debug_connection.rb' with the following content:
class ActiveResource::Connection
# Creates new Net::HTTP instance for communication with
# remote service and resources.
def http
http = Net::HTTP.new(#site.host, #site.port)
http.use_ssl = #site.is_a?(URI::HTTPS)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl
http.read_timeout = #timeout if #timeout
# Here's the addition that allows you to see the output
http.set_debug_output $stderr
return http
end
end
This will print the whole network traffic to $stderr.
It's easy. Just look at the response that comes back. :)
Two options:
You have the source file on your computer. Edit it. Put a puts response.inspect at the appropriate place. Remember to remove it.
Ruby has open classes. Find the right method and redefine it to do exactly what you want, or use aliases and call chaining to do this. There's probably a method that returns the response -- grab it, print it, and then return it.
Here's a silly example of the latter option.
# Somewhere buried in ActiveResource:
class Network
def get
return get_request
end
def get_request
"I'm a request!"
end
end
# Somewhere in your source files:
class Network
def print_request
request = old_get_request
puts request
request
end
alias :old_get_request :get_request
alias :get_request :print_request
end
Imagine the first class definition is in the ActiveRecord source files. The second class definition is in your application somewhere.
$ irb -r openclasses.rb
>> Network.new.get
I'm a request!
=> "I'm a request!"
You can see that it prints it and then returns it. Neat, huh?
(And although my simple example doesn't use it since it isn't using Rails, check out alias_method_chain to combine your alias calls.)
I like Wireshark because you can start it listening on the web browser client end (usually your development machine) and then do a page request. Then you can find the HTTP packets, right click and "Follow Conversation" to see the HTTP with headers going back and forth.
This only works if you also control the server:
Follow the server log and fish out the URL that was called:
Completed in 0.26889 (3 reqs/sec) | Rendering: 0.00036 (0%) | DB: 0.02424 (9%) | 200 OK [http://localhost/notifications/summary.xml?person_id=25738]
and then open that in Firefox. If the server is truely RESTful (ie. stateless) you will get the same response as ARes did.
Or my method of getting into things when I don't know the exact internals is literally just to throw in a "debugger" statement, start up the server using "script/server --debugger" and then step through the code until I'm at the place I want, then start some inspecting right there in IRB.....that might help (hey Luke btw)
Maybe the best way is to use a traffic sniffer.
(Which would totally work...except in my case the traffic I want to see is encrypted. D'oh!)
I'd use TCPFlow here to watch the traffic going over the wire, rather than patching my app to output it.
the firefox plugin live http headers (http://livehttpheaders.mozdev.org/) is great for this. Or you can use a website tool like http://www.httpviewer.net/

Resources