I'm parsing a URL in my Rails application. I want to get the domain example.com stripped of any protocol, subdomain, directories, etc.
My method:
def clean_host(url)
uri = URI.parse(url)
return uri
end
What I actually get for example.com/ is:
scheme:
user:
password:
host:
port:
path: example.com/
query:
opaque:
registry:
fragment:
parser:
What I eventually want is to get the domain example.com stripped of any protocol, subdomain, directories, etc.
I've looked into domainatrix but it wont bundle with my project. Is there a way to do this with Ruby's URI.parse? Or will I have to look into other avenues?
The problem is that example.com/ isn't a full URL. URI rightly assumes it's a path. If it were me and you're going to have a lot of these fragments I'd just brute force it.
> "example.com/".sub(%r{^.*?://}, '').sub(%r{/.*$}, '')
=> "example.com"
> "http://subdomain.example.com/path/here".sub(%r{^.*?://}, '').sub(%r{/.*$}, '')
=> "subdomain.example.com"
Stripping the subdomain off is another ball of wax as you'd need to example the TLD to determine what is appropriate so you don't end up with say "com.uk"
You should just be able to do request.domain assuming you are doing this in a controller.
You can also use request.path and request.subdomain
For example: http://www.domain.com/users/123
request.subdomain => 'www'
request.domain => 'domain.com'
request.path => '/users/123'
Related
How do I turn SSL HTTPS off for a given path? I saw Enable SSL for certain resource actions but that was to enable HTTPS for a single path. My config has
config.force_ssl = true
However when I show a page that has an iframe and embeds an external source
<iframe src='http://www.
Then it doesn't even appear (Chrome) because it is mixed content. So I want to disable SSL for that single route that has an iframe. (I really want to turn it on & off depending on the content.)
I tried adding this to my routes.rb
get 'frame', :constraints => { :protocol => 'http' }
but that gave an error http://127.0.0.1:3000/posts/136/frame
No route matches [GET] "/posts/136/frame"
even though the route shows up
frame_post GET /posts/:id/frame(.:format) posts#frame {:protocol=>"http"}
I also saw Force SSL for specific routes in Rails 3.1 and tried
gem 'rack-ssl-enforcer' # Gemfile
config.middleware.use Rack::SslEnforcer, :except => [ /\/frame$/ ], :strict => true # application.rb
but it still always redirects to https. I also tried
force_ssl :except => :frame # posts_controller.rb
But that didn't work either.
I'm using Rails 4.1.
Rack ssl enforcer is a great solution for this - your regular expression is wrong. In your form, the regex would only exclude a path that is entirely '/frame', and would not exclude a path that had anything before /frame
If you want to exclude any path that ends with /frame, The correct regular expression would be:
\.*\/frame$/
Resulting in a config:
config.middleware.use Rack::SslEnforcer, :except => [ \.*\/frame$/ ], :strict => true
I have a situation in which two cookies have the same name but slightly different domains (cookie1 has the domain example.com whereas cookie2 has sub-domain inclusive .example.com).
cookies[ :cookie_name ] = { :value => "test_value_cookie_1", :domain => "example.com" }
cookies[ :cookie_name ] = { :value => "test_value_cookie_2", :domain => ".example.com" }
I want to detect when both cookies exist, but unfortunately I can't out figure how to access a cookie by it's own domain. I can say
if cookies[ :cookie_name ].blank?
but how do I say
if cookies[ :cookie_name, :domain => ".example.com" ].blank?
or
if cookies[ :cookie_name ].domain[ ".example.com" ].blank?
I'm using "actionpack-2.3.11/lib/action_controller/cookies". I don't understand why you can set information like the domain, but not access it.
Apparently what I wanted to do was impossible. The HTTP spec only allows cookies to be accessed by name even though they can be set by domain:
When requesting a URL from an HTTP server, the browser will match the
URL against all cookies and if any of them match, a line containing
the name/value pairs of all matching cookies will be included in the
HTTP request. Here is the format of that line: Cookie:
NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ...
http://curl.haxx.se/rfc/cookie_spec.html
I got the following back from delayed_job:
[Worker(XXXXXX pid:3720)] Class#XXXXXXX failed with URI::InvalidURIError: bad URI(is not URI?): https://s3.amazonaws.com/cline-local-dev/2/attachments/542/original/mac-os-x[1].jpeg?AWSAccessKeyId=xxxxxxxx&Expires=1295403309&Signature=xxxxxxx%3D - 3 failed attempts
The way this URI comes from in my app is.
In my user_mailer I do:
#comment.attachments.each do |a|
attachments[a.attachment_file_name] = open(a.authenticated_url()) {|f| f.read }
end
Then in my attachments model:
def authenticated_url(style = nil, expires_in = 90.minutes)
AWS::S3::S3Object.url_for(attachment.path(style || attachment.default_style), attachment.bucket_name, :expires_in => expires_in, :use_ssl => attachment.s3_protocol == 'https')
end
That being said, is there some type of URI.encode or parsing I can do to prevent a valid URI (as I checked the URL works in my browser) for erroring and killing delayed_job in rails 3?
Thank you!
Ruby has (at least) two modules for dealing with URIs.
URI is part of the standard library.
Addressable::URI, is a separate gem, and more comprehensive, and claims to conform to the spec.
Parse a URL with either one, modify any parameters using the gem's methods, then convert it using to_s before passing it on, and you should be good to go.
I tried ' open( URI.parse(URI.encode( a.authenticated_url() )) ' but that errord with OpenURI::HTTPError: 403 Forbidden
If you navigated to that page via a browser and it succeeded, then later failed going to it directly via code, it's likely there is a cookie or session state that is missing. You might need to use something like Mechanize, which will maintain that state while allowing you to navigate through a site.
EDIT:
require 'addressable/uri'
url = 'http://www.example.com'
uri = Addressable::URI.parse(url)
uri.query_values = {
:foo => :bar,
:q => '"one two"'
}
uri.to_s # => "http://www.example.com?foo=bar&q=%22one%20two%22"
An example:
[Dev]> ActionController::Base.helpers.sanitize('test')
=> 'test'
[Dev]> ActionController::Base.helpers.sanitize('test')
=> '<a>test</a>'
Extremely frustrating!
This seems to be a bug in the method contains_bad_protocols? in action_controller/vendor/html-scanner/html/sanitizer.rb. This method is defined as:
def contains_bad_protocols?(attr_name, value)
uri_attributes.include?(attr_name) &&
(value =~ /(^[^\/:]*):|(�*58)|(p)|(%|%)3A/
&& !allowed_protocols.include?(value.split(protocol_separator).first))
end
And allowed_protocols as:
self.allowed_protocols = Set.new(%w(ed2k ftp http https irc mailto news gopher nntp
telnet webcal xmpp callto feed svn urn aim rsync tag ssh sftp rtsp afs))
Thus:
allowed_protocols.include? 'http' => true
allowed_protocols.include? 'Http' => false
I'm using ActionMailer to send a sign up confirmation email. The email needs to contain a link back to the site to verify the user, but I can't persuade Rails to generate a full URL (including the domain etc).
I'm using:
<%= url_for :controller => 'login', :action => 'verify', :guid => #user.new_user.guid, :only_path => false, :host => 'http://plantality.com' %>
in my view
Part b:
In development mode Rails gripes if I don't specify the host explicilty in the link above. But I don't want to do this in production. Any solutions?
To solve the problem to pass a host for generating URLs in ActionMailer, check out this plugin and the reason why I wrote it.
To solve the first issue, use named routes when applicable. Instead of
<%= url_for :controller => 'login', :action => 'verify', :guid => #user.new_user.guid, :only_path => false, :host => 'http://plantality.com' %>
assuming the route is called login, use
<%= login_url(:guid => #user.new_user.guid) %>
Note, I'm using login_url, not login_path.
I'm not sure if it is what you want but in config/environments/development.rb you can specify default options for mailer urls
config.action_mailer.default_url_options = {
:host => "your.host.org",
:port => 3000
}
you can do the same in config/environments/production.rb
I don't know why the previous solutions seem so complicated, but since I'm here why not give my 2 cents...
Go to /config/environments and add:
config.absolute_site_url = 'your site url'
for the respective environment (ie. in development.rb, test.rb, or production.rb). Restart web server.
This allows you to call Rails.application.config.absolute_site_url to get the desired URL. No need for plugins or weird cheat, just store the site url as an application wide variable.
I think its not 100% correct way but this can also be a solution :
See the Using asset hosts section in the documentation. You need to specify an asset_host. You can also construct it dynamically from the request chaining "#{request.protocol}#{request.host_with_port}/login/?guid=#{#user.new_user.guid}"
To generate url, try this
Rails.application.routes.url_helpers.user_url(User.first.id, host: 'yourhost.io')
this will generate url like this:
http://yourhost.io/users/1
As well you can pass some params
expires = Time.now + 2.days
params = {expires: expires}
u = User.first.id
Rails.application.routes.url_helpers.user_url(u, params, host: 'host.com')
will generate:
http://yourhost.io/users/1.expires=2018-08-12+15%253A52%253A15+%252B0300
so you can werifi in action if link is not expired