7

Is it possible to to rewrite the base URL?

E.g. instead of www.host.com/ to use www.host.com/blah/ as a base url and so:

get '/' do
  ...
end

would work for www.host.com/blah/

I could append to all my routes '/blah/..' but any gems etc. would fail to work as well.

This can be done in Rails easily and I would like to have it in Sinatra as well.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
George
  • 193
  • 1
  • 8
  • What gems are you using that do redirects? – matt Jun 03 '11 at 02:01
  • sinatra-authentication. Basically I am also running sinatra through CGI and that complicated stuff as well. It has to be a more pretty solution. I was thinking of using the before and after filters. – George Jun 03 '11 at 02:05
  • 3
    I'm not entirely sure what you're trying to do: you should be able to write your app so it's independent of the base url, e.g. using the [`url` helper](http://www.sinatrarb.com/intro.html#Generating%20URLs). Then the path to the app is determined by how you set up your server, not the Sinatra app itself. Gems should work okay with this too. – matt Jun 03 '11 at 02:27
  • Let me clarify then. I am working on a server for which I have not complete access over. I have been assigned a directory for which I can work with my project over CGI. So instead of receiving '/' for the get in sinatra I receive 'foo/blah/'. '/about' becomes '/foo/blah/about' etc. kfl62 suggested something good, which I have seen already, but any gems that redirect to '/login' would fail as they would redirect to www.host.com/login instead of www.host.com/foo/blah/login – George Jun 03 '11 at 10:40
  • Does setting `enable :prefixed_redirects` help? – matt Jun 03 '11 at 15:29
  • 1
    I edited my answer with some examples. I still believe something like: `rewrite %r{/}, '/foo/blah'` will solve your problem. – kfl62 Jun 04 '11 at 21:43
  • @matt should have submitted his response as an answer. I found it very helpful. – Justin Force Nov 16 '11 at 22:53

3 Answers3

8

I use a rack middleware for this rack-rewrite and I am quite happy with it :)

    use Rack::Rewrite do
      rewrite %r{^/\w{2}/utils}, '/utils'
      rewrite %r{^/\w{2}/ctrl},  '/ctrl'
      rewrite %r{^/\w{2}/},      '/'
    end

EDIT:

Not sure if I understand your problem, but here are a config.ru file

# encoding: utf-8
require './config/trst_conf'
require 'rack-flash'
require 'rack/rewrite'

use Rack::Session::Cookie, :secret => 'zsdgryst34kkufklfSwsqwess'
use Rack::Flash
use Rack::Rewrite do
  rewrite %r{^/\w{2}/auth},  '/auth'
  rewrite %r{^/\w{2}/utils}, '/utils'
  rewrite %r{^/\w{2}/srv},   '/srv'
  rewrite %r{^/\w{2}/},      '/'
end

map '/auth' do
  run TrstAuth.new
end
map '/utils' do
  run TrstUtils.new
end
map '/srv' do
  map '/tsk' do
     run TrstSysTsk.new
  end
  map '/' do
    run TrstSys.new
  end
end
map '/' do
  run TrstPub.new
end

and an example Sinatra::Base subclass

# encoding: utf-8

class TrstAuth < Sinatra::Base

  # Render stylesheets
  get '/stylesheets/:name.css' do
    content_type 'text/css', :charset => 'utf-8'
    sass :"stylesheets/#{params[:name]}", Compass.sass_engine_options
  end

  # Render login screen
  get '/login' do
    haml :"/trst_auth/login", :layout => request.xhr? ? false : :'layouts/trst_pub'
  end

  # Authentication
  post '/login' do
    if user = TrstUser.authenticate(params[:login_name], params[:password])
      session[:user] = user.id
      session[:tasks] = user.daily_tasks
      flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.login_msg'), :class => "info"}}.to_json
      redirect "#{lang_path}/srv"
    else
      flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.login_err'), :class => "error"}}.to_json
      redirect "#{lang_path}/"
    end
  end

  # Logout
  get '/logout' do
    session[:user] = nil
    session[:daily_tasks] = nil
    flash[:msg] = {:msg => {:txt => I18n.t('trst_auth.logout_msg'), :class => "info"}}.to_json
    redirect "#{lang_path}/"
  end

end

maybe this helps :) full source on github.

kfl62
  • 2,434
  • 4
  • 29
  • 40
  • Thanks for this, I already came upon this but any redirects to '/login' etc see my comment above would fail. I am going to use this if I can not find anything better and rewrite the code of any gems :) – George Jun 03 '11 at 10:45
2

In a before block you can edit env['PATH_INFO]`; Sinatra will then use the edited value for routing.

For your example, something like this might work...

before do
    env['PATH_INFO'].sub!(/^\/blah/, '')
end

I agree with the other answers that using a middleware component is a more robust solution but if you want something concise and simple, that works inside the Sinatra app instead of via config.ru, then munging the Rack environment is not bad.

AlexChaffee
  • 8,092
  • 2
  • 49
  • 55
  • For anyone else looking for this, I just added a similar solution for Apache + CGI / FastCGI with RewriteEngine here: https://stackoverflow.com/a/52689478/823617 – Casper Oct 07 '18 at 14:36
1

You could have a look at https://github.com/josh/rack-mount, maybe that one can help you out?

Bert Goethals
  • 7,867
  • 2
  • 20
  • 32