ActionDispatch host method

I’m working on a large legacy Rails 3 project, in the ApplicationController there is a list of safe hosts and we have a method to see if the request.host is in that list. Locally I can call request.host and I get localhost back. However; in production, on Sentry there are some 200,000 errors: undefined method 'host=' for #<ActionDispatch::Request:0x007ff28f2833e8>.

I’m a little confused as to why this works locally but is apparently causing problems in production.

Without looking at the rest of your code, it’s hard to say. But are you sure you are calling just request.host and not trying for a comparison == but only typing the one = (meaning assignment)? That’s something that has tripped me up from time to time over the past 20 years of Web programming. I’m embarrassed to say just how recently, in fact.

Walter

Ah thanks, I’m pretty infamous for assigning rather than comparing especially in tests but I’m afraid this is not the case in this instance. The method looks like this:

    def block_unknown_hosts
       unless KNOWN_HOSTS.include?(request.host)
        request.host = ''
      end
    end

We get that undefined method error every few seconds in Sentry (which makes sense because this is a before_filter from the ApplicationController.

That’s a puzzler, then. Are you using the same version of Rails in both places?

The only thing that error is saying is that the instance of request doesn’t have a “writer” method defined for host. It’s not a nil reference error, it’s a no method error. I would start by adding some logging around the assignment. See what instance of request you are getting, see what the methods available on that instance are, etc. You may also try using hash syntax to write this, like this:

request[:host] = ‘’

See if that allows you to write it out. If it’s not a symbol key, then try a string instead. I think that request in that context is a HashWithIndifferentAccess, so all three methods (dot syntax, hash with symbol keys, and hash with string keys) should all work equally. But I may be wrong in that assumption. That’s where I would start looking for answers.

Walter

Thanks @walterdavis I think the issue was in attempting to assign the new host in the unless statement: request.host = '' apparently Rails doesn’t like that. I’m not sure if there is a way of setting the host in the application controller, if not I guess we’ll just have to raise an error in the event of a request from a bad host.