Can't get custom error pages to work in Padrino - ruby

I started to build a website with padrino. At the moment the main class of my app is the simplest thing in the world:
class App < Padrino::Application
enable :sessions
get :index do
send_file 'public/view/index.html'
end
error 404 do
send_file 'public/view/errors/404.html'
end
end
So the views are simply htmls - the idea behind it is to use angularjs to render all the thingies provided by a rest api. I guess that's fairly standard.
My problem is - although it works fine for rendering the home page (localhost:3000/), the custom error doesn't work at all; let's say I try localhost:3000/test - the standard "Sinatra doesn’t know this ditty" page is rendered instead.
I'm running padrino 0.12.4 with WEBrick 1.3.1. What am I doing wrong here?

I believe what's going on here is that when you go to localhost:3000/test, your Sinatra app is looking for the "test" action under your App Controller. Obviously this action is not being found because it's not listed as a route! Therefore explicitly tell Sinatra to return a 404 page if the diddy wasn't found:
error Sinatra::NotFound do
content_type 'text/plain'
[404, 'Not Found']
end

Related

Modular Sinatra app returns 404's under Passenger

I have a modular Sinatra app which runs fine when executed with rackup. The config.ru file is defined as follows:
map '/' do
run My::Controllers::Default
end
map '/api' do
run My::Controllers::Api
end
When I run the app under nginx/passenger I get nothing but 404's, even for the '/' route. Suspecting that something was wrong with routing, I modified config.ru as follows:
run My::Controllers::Default
After restarting nginx, I was served the default page of the app. However, the default page of the app reaches into the api route to get some documentation to display, and that part returns a 404. Given that config.ru is able to run the Default controller, I'm sure that the issue has nothing to do with being able to load all of the relevant ruby files--which seems to be the problem in other related questions I've found on SO.
With that in mind I modified config.ru as follows:
map '/api' do
run My::Controllers::Api
end
run My::Controllers::Default
At this point I'm back to getting nothing but 404's, even for the '/' route. It seems that the map statement is confusing the webserver and making it unable to find the correct routes.
If I just run the app using rackup everything behaves as expected, so I'm really at a loss to explain what I'm seeing.
I remember this being the answer. Let me know if it works for you. If it does I'll "Accept" the answer so that others will find it.
Middleware
A bug in passenger prevents it from understanding the map statement in config.ru https://groups.google.com/forum/#!msg/phusion-passenger/PoEEp9YcWbY/1y0QL_i3tHYJ
class PassengerFix
def initialize(app)
#app = app
end
def call(env)
env["SERVER_NAME"] = env["HTTP_HOST"]
return #app.call(env)
end
end
config.ru
configure do
use PassengerFix
end

Error handlers don't run in modular Sinatra app

I have a Sinatra application that uses the modular style. Everything works fine apart from my error handler blocks which don't get invoked. Here's the relevant code:
app.rb
require_relative './routes/base'
require_relative './routes/routing'
module Example
class App < Sinatra::Application
use Routes::Base
use Routes::Routing
end
end
base.rb
require 'sinatra/base'
module Example
module Routes
class Base < Sinatra::Application
configure do
# etc.
end
# Error pages.
error 404 do # <- Doesn't get invoked.
erb :not_found
end
error 500 do # <- Doesn't get invoked.
erb :internal_server_error
end
end
end
end
routing.rb
module Example
module Routes
class Routing < Base
get '/?' do
erb :home
end
end
end
end
Why don't my error handlers work?
Thanks in advance.
The use method is for adding middleware to an app, you can’t use it to compose an app like this.
In your example you actually have three different Sinatra applications, two of which are being run as middleware. When a Sinatra app is run as middleware then any request that matches one of its routes is handled by that app, otherwise the request is passed to the next component in the Rack stack. Error handlers will only apply if the request has been handled by the same app. The app that you have defined the error handlers in has no routes defined, so all requests will be passed on down the stack — the error handlers will never be used.
One way to organise a large app like this would be to simply use the same class and reopen it in the different files. This other question has an example that might be useful: Using Sinatra for larger projects via multiple files.

Rendering 404 in sinatra if file not found

I have a basic sinatra app that renders files from a directory. What I'd like is returns 404 if page does not exist. Currently it raise 500 error.
get '/:page' do
erb :"pages/#{params[:page]}", layout: :"layouts/application"
end
Try this ;)
# 404 Error!
not_found do
status 404
erb :oops
end
Make yourself a 404 page with whatever name you like (mine is oops.erb, for example), and this should work just fine.
not_found is Sinatra's error-handling helper for grabbing error 500s and 404 not-founds that it returns. You can then change the HTTP status and corresponding view using it. Check out the documentation for all of Sinatra's error handler's: they're super useful!
You could do something like:
get '/:page' do
requested_erb = File.join(root, 'pages', params[:page])
pass unless File.exists?(requested_erb)
erb :"#{requested_erb}", :layout: :"layouts/application"
end
I haven't tested this, so there might be some issues with the above code, but that's the general idea in my head.

Sinatra error when handling .php routes

I'm creating a Sinatra app to replace a legacy PHP based app.
get '/page.php' do
# ... do something
end
I'm trying to define a route like this but I get "Sinatra doesn't know this ditty." error page.
At the top of the page, I have this
configure do
mime_type :php, 'text/html'
end
Any idea how to tell Sinatra to use the whole path including the file extension as part of it?

sinatra-authentication gem not looking for correct views?

I am attempting to write a small blogging engine for myself in sinatra and mongoid and am trying to use the sinatra-authentication gem to do login/out.
I have gotten sinatra, mongoid, and haml all working but when I visit any sinatra-authentication page nginx throws an internal server error.
this is the error I am getting
Errno::ENOENT - No such file or directory - /opt/nginx/html/raptor.patrickarlt.com/views/layout.haml:
you can see all my files including more from my nginx error log here https://gist.github.com/854156
get '/' works confirming Sinatra is working
get '/haml' works confirming haml is working
get '/private' redirects to '/login' confirming sinatra-authentication is working
get '/login' internal server error
Ruby 1.9.2
Nginx 0.8.54
Passenger 3.0.2
sinatra-authentication assumes you're using a layout unless the current request is an XMLHttpRequest (see the code). You have two options:
Create a layout for your application in views/layout.haml as described a couple paragraphs down at http://sinatra-book.gittr.com/#templates
Override sinatra-authentication's use_layout? method as such:
module Sinatra
module Helpers
def use_layout?
false
end
end
end

Resources