In my controller I have the following
post "/buy_item" do
redirect '/login' unless session[:name]
@owner = Market::User.user_by_name(params[:owner])
@item = @owner.item_by_id(params[:item].to_i)
@current_user = Market::User.user_by_name(session[:name])
if @current_user.buy_item?(@item)
@current_user.buy_item(@item)
else
redirect '/error'
end
end
when I’m forcing an “else” I get correctly redirected to /error, but directly after that I get redirected to another page (/?loggedin=true). redirect "/?loggedin=true" is the last line of the post "/login" method. So, it seems that it is calling POST /login somehow..
The route for /error looks like this:
get "/error" do
redirect '/login' unless session[:name]
template = ERB.new File.new($VIEWS_FOLDER + "/error.erb").read, nil, "%"
template.result(binding)
end
Nothing in /error.erb is redirecting, when I call localhost:4567/error directly it doesn’t get redirected.
Here’s the log:
127.0.0.1 – – [03/Oct/2012 17:15:03] “POST /login HTTP/1.1” 303 – 0.0012
localhost – – [03/Oct/2012:17:15:03 CEST] “POST /login HTTP/1.1” 303 0
localhost:4567/login -> /login
127.0.0.1 – – [03/Oct/2012 17:15:03] “GET /?loggedin=true HTTP/1.1” 200 3916 0.0055
localhost – – [03/Oct/2012:17:15:03 CEST] “GET /?loggedin=true
HTTP/1.1” 200 3916localhost:4567/login -> /?loggedin=true
127.0.0.1 – – [03/Oct/2012 17:15:05] “POST /buy_item HTTP/1.1” 303 – 0.0030
localhost – – [03/Oct/2012:17:15:05 CEST] “POST /buy_item HTTP/1.1”
303 0localhost:4567/?loggedin=true -> /buy_item
127.0.0.1 – – [03/Oct/2012 17:15:05] “GET /error HTTP/1.1” 200 1609 0.0039
localhost – – [03/Oct/2012:17:15:05 CEST] “GET /error HTTP/1.1” 200
1609localhost:4567/?loggedin=true -> /error
127.0.0.1 – – [03/Oct/2012 17:15:05] “GET /?loggedin=true HTTP/1.1” 200 3916 0.0063
localhost – – [03/Oct/2012:17:15:05 CEST] “GET /?loggedin=true
HTTP/1.1” 200 3916localhost:4567/login -> /?loggedin=true
You have two redirects inside your route
'/buy_item'; and in'/error'you do not return after theredirect.redirectdoes something to your HTTP header and it is good practice to return after the call, i.e. in both routes/buy_itemand/error:I have worked on a large Sinatra app and there were a lot of problems with redirect, the above patch should help. Moreover I recommend you to take a look at the HTTP RFC and make yourself familiar with the Post-Redirect-Get scheme. To to redirects with custom status code, you can do
redirect '/foo', 303.