I have an idea to move site from PHP (Joomla + pure php) to Ruby on Rails (Refinery CMS). Old site has links with .html and .php extensions. Is there a way to keep old urls the same (I don't want to loose Google PageRank)? I tried to use config.use_custom_slugs = true config with Refenery, but it drop '.' from url. (store.php becomes storephp, also FAQ.html becomes faqhtml ... etc )
Any help appreciated! Thanks.
In Rails I can do it next way
#Application Controller
def unknown_path
#it works for all urls, here I can load page with needed slug
render :text => "#{request.fullpath}"
end
#routes.rb
match "*a", :to => "application#unknown_path" #in the end
And it will make any url working. So I could use custom slug if it exist or raise 404
But CMS dosn't allow to create really custom slugs
Why not 301
Trying to explain: you get an external link coming to Page 1, then your Page 1 links internally to Page 2. Link to page 1 gets 1000 amount of page rank from the link. Link to page 2 gets 900 Therefore a link to 301 gets 1000 and the page that the 301 points to gets 900. So: 900 is better than it disappearing altogether, but I'm trying avoiding creating this situation. That how it works.
As per my answer on Refinery's issue tracker, where this was also asked, do you have to do this in Rails? What about rewriting the request before it even gets to Rails using proxy software such as nginx with HttpRewriteModule?
I ran into a similar issue when moving from wordpress to Comfortable Mexican Sofa ( another Rails CMS engine).
I ended up doing this in my routes.rb ( here is a sample of one of the redirects ( I don't have a lot - total of 15 redirects like that), which is generic Rails solution that can be used by RefineryCMS as well I think.
get '/2009/01/28/if-programming-languages-were-cars/', to: redirect('/blog/2009/01/if-programming-languages-were-cars-translated-into-russian')
This actually generates a proper redirect like so ( impossible to see in the browser, but if you curl you'll see this:
curl http://gorbikoff.com/2009/01/28/if-programming-languages-were-cars/
<html>
<body>
You are being redirected.
</body>
</html>
And if we check headers - we see a proper 301 response:
curl -I http://gorbikoff.com/2009/01/28/if-programming-languages-were-cars/
returns
HTTP/1.1 301 Moved Permanently
Content-Type: text/html
Content-Length: 158
Connection: keep-alive
Status: 301 Moved Permanently
Location: http://gorbikoff.com/blog/2009/01/if-programming-languages-were-cars-translated-into-russian
X-UA-Compatible: IE=Edge,chrome=1
Cache-Control: no-cache
X-Request-Id: 9ec0d0b29e94dcc26433c3aad034eab1
X-Runtime: 0.002247
Date: Wed, 10 Jul 2013 15:11:22 GMT
X-Rack-Cache: miss
X-Powered-By: Phusion Passenger 4.0.5
Server: nginx/1.4.1 + Phusion Passenger 4.0.5
Specific to your case
So that's the general approach. However for what you are trying to do ( redirect all urls that end in .php like yourdomain.com/store.php to yourdomain.com/store) you should be able to do something like this. This assumes that you'll (map your new structure exactly, otherwise you may need to create a bunch of custom redirects like I mentioned in the beginning or do some Regex voodoo) :
NON-Redirect Solution
Don't redirect user, just render new page at the same address (it's a twist on solution you put in your question):
This is the only way that's more or less robust, if you don't want to do a redirect.
# routes.rb
# You don't need to match for .html - as they will be handled automatically by rails.
match '/*\.php', to: "application#php_path"
# application_controller.rb
# This doesn't have to be application controller,
# you may do this in your home_controller if you wish.
def php_path
require 'open-uri'
file = open "http://#{request.host_with_port}#{request.fullpath.gsub!(/(.php)/,'')}"
render :inline => file.read
end
Redirect Solution:
According to Google 301 is the preferred way https://support.google.com/webmasters/answer/93633?hl=en .
match '/*\.php', to: redirect {|params, request|
"http://#{request.host_with_port}#{request.fullpath.gsub(/(.php)/,'')}"
}
This will provide a Response Header Status Code 200. As far as the world is concerned you are serving PHP through passenger ( run curl -I against my site using this sample urls - these are just arbitrary params to illustrate my point)
curl -I http://gorbikoff.com/about?name=nick
curl -I http://gorbikoff.com/about.php?name=nick
You may need to fidget with this based on your specifics ( https vs http, etc, and maybe some virtual routes need to be address separately. Also remember about precedence in the route.rb ) but I think this might work for you.
EDIT
I just realized that this solution works out of the box in Comfortable Mexican Sofa ( it just ignores format ( .php is treated same way .html would be treated). However I tried my solutions in non-cms based rails 3 project I have ( it's not public) and my solution still holds with slight change - I just fixed it (sorry for the confusion).
I suggest also to check official guide at (I'm assuming you are on Rails 3.2.13 since RefinderyCMS doesn't support Rails 4 officially yet)
http://guides.rubyonrails.org/v3.2.13/routing.html#redirection
And check out Rails API
http://api.rubyonrails.org/v3.2.13/classes/ActionDispatch/Routing/Redirection.html#method-i-redirect
Hope that helps
Related
I'm using Sinatra and the shotgun server.
When I type in http://localhost:9393/tickets, my page loads as expected. But, with an extra "/" on the end, Sinatra suggests that I add
get '/tickets/' do
How do I get the server to accept the extra "/" without creating the extra route?
The information in Sinatra's "How do I make the trailing slash optional?" section looks useful, but this means I would need to add this code to every single route.
Is there an easier or more standard way to do that?
My route is set up as
get '/tickets' do
It looks like the FAQ doesn't mention an option that was added in 2017 (https://github.com/sinatra/sinatra/pull/1273/commits/2445a4994468aabe627f106341af79bfff24451e)
Put this in the same scope where you are defining your routes:
set :strict_paths, false
With this, Sinatra will treat /tickets/ as if it were /tickets so you don't need to add /? to all your paths
This question is actually bigger than it appears at first glance. Following the advice in "How do I make the trailing slash optional?" does solve the problem, but:
it requires you to modify all existing routes, and
it creates a "duplicate content" problem, where identical content is served from multiple URLs.
Both of these issues are solvable but I believe a cleaner solution is to create a redirect for all non-root URLs that end with a /. This can easily be done by adding Sinatra's before filter into the existing application controller:
before '/*/' do
redirect request.path_info.chomp('/')
end
get '/tickets' do
…
end
After that, your existing /tickets route will work as it did before, but now all requests to /tickets/ will be redirected to /tickets before being processed as normal.
Thus, the application will respond on both /ticket and /tickets/ endpoints without you having to change any of the existing routes.
PS: Redirecting the root URL (eg: http://localhost:9393/ → http://localhost:9393) will create an infinite loop, so you definitely don't want to do that.
When using fresh_when strong_etag: #collection in a Rails view, the etag is generated before being gzipped by Apache, thus it lacks the "-gzip" suffix.
However, if Apache is set to gzip responses, the Etag that the browser sends will contain the "-gzip" suffix.
This may or may not be connected to using Phusion Passenger as the proxy server for Rails.
Suggested solutions include having Apache strip the "-gzip" suffix by adding RequestHeader edit "If-None-Match" "^(.*)-gzip$" "$1" to the site's directives. However, this does not appear to work as intended.
Is there another way to rewrite the header to strip the suffix so that Etags can be successfully compared?
This can be accomplished in Rails by adding a before_action to the Application controller (to affect all requests).
class ApplicationController < ActionController::Base
before_action :fix_etag_header
...
private
def fix_etag_header
if request.headers["HTTP_IF_ONE_MATCH"]
request.headers["HTTP_IF_NONE_MATCH"].sub! "-gzip", ""
end
end
end
Obviously, this circumvents the directive that a compressed resource should have a unique Etag from the same resource uncompressed. That could cause issues if those aspects of an HTTP request are altered or addressed by other code.
However, in most instances, this is a "good enough" solution especially when considering that it requires only 6 lines.
Firstly I want to make clear that I am not familiar with Ruby, at all.
I'm building a Discord Bot in Go as an exercise, the bot fetches UrbanDictionary definitions and sends them to whoever asked in Discord.
However, UD doesn't have an official API, and so I'm using this. It's an Heroku App written in Ruby. From what I understood, it scrapes the UD page for the given search.
I want to add random to my Bot, however the API doesn't support it and I want to add it.
As I see it, it's not hard since http://www.urbandictionary.com/random.php only redirects you to a normal link of the site. This way if I can follow the link to the "normal" one, get the link and pass it on the built scraper it can return just as any other link.
I have no idea how to follow it and I was hoping I could get some pointers, samples or whatsoever.
Here's the "ruby" way using net/http and uri
require 'net/http'
require 'uri'
uri = URI('http://www.urbandictionary.com/random.php')
response = Net::HTTP.get_response(uri)
response['Location']
# => "http://www.urbandictionary.com/define.php?term=water+bong"
Urban Dictionary is using an HTTP redirect (302 status code, in this case), so the "new" URL is being passed back as an http header (Location). To get a better idea of what the above is doing, here's a way just using curl and a system call
`curl -I 'http://www.urbandictionary.com/random.php'`. # Get the headers using curl -I
split("\r\n"). # Split on line breaks
find{|header| header =~ /^Location/}. # Get the 'Location' header
split(' '). # Split on spaces
last # Get the last element in the split array
I am having trouble with some Ruby CGI.
I have a home page (index.cgi) which is a mix of HTML and Ruby, and has a login form in it.
On clicking on the Submit button the POST's action is the same page (index.cgi), at which point I check to make sure the user has entered data into the correct fields.
I have a counter which increases by 1 each time a field is left empty. If this counter is 0 I want to change the current loaded page to something like contents.html.
With this I have:
if ( errorCount > 0 )
do nothing
else
....
end
What do I need to put where I have the ....?
Unfortunately I cannot use any frameworks as this is for University coursework, so have to use base Ruby.
As for using the CGI#header method as you have suggested, I have tried using this however it is not working for me.
As mentioned my page is index.cgi. This is made of a mixture of Ruby and HTML using "here doc" statements.
At the top of my code page I have my shebang line, following by a HTML header statement.
I then do the CGI form validation part, and within this I have tried doing something like: print this.cgi( { 'Status' => '302 Moved', 'location' =>
'{http://localhost:10000/contents.html' } )
All that happens is that this line is printed at the top of the browser window, above my index.cgi page.
I hope this makes sense.
To redirect the browser to another URL you must output an 30X HTTP response that contains the Location: /foo/bar header. You can do that using the CGI#header method.
Instead of dealing with these details that you do not yet master, I suggest you use a simple framework as Sinatra or, at least, write your script as a Rack-compatible application.
If you really need to use the bare CGI class, have a look at this simple example: https://github.com/tdtds/amazon-auth-proxy/blob/master/amazon-auth-proxy.cgi.
I am a ruby newbie and have been trying Sinatra for quite some time now, one thing that Iam not able to figure out is why does a '/' in the url make such a big difference.
I mean isnt:
get 'some_url' do
end
and
get 'some_url/' do
end
Supposed to point to the same route? why is that Sinatra considers it as different routes? I spent a good one hour trying to figure that out.
According to RFC 2616 and RFC 2396 (RFCs defining resource identity) those URLs do not define the same resource. Therefore Sinatra treats them differently. This is esp. important if you imagine the route returning a page with relative links. This link
click me
Would point to /bar if you're coming from /foo, to /foo/bar if you're coming from /foo/.
You can use the following syntax to define a route matching both:
get '/foo/?' do
# ...
end
Or the Regexp version mentioned in the comments above.
They are different routes. The second is a URL with a directory extension ('/'); the first is a URL with no extension. A lot of frameworks (like Rails) will interpret both as the same route, or append the `/' (e.g., Django, and Apache can be configured to do that as well), but technically they are different URLs.