aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStormwind <stormwind@stormwinds-page.de>2023-05-09 11:03:34 +0200
committerStormwind <stormwind@stormwinds-page.de>2023-05-09 12:37:15 +0200
commitb582ca5d8aafdf9bfaccbe67c74aa532cbfc4f1a (patch)
treefa5bd206af0191e5a002a6498d83bb50c8b61890
parent8cb48215bfdc7352ea39ee2c7241bd4d87636198 (diff)
Add error handeling pages (primarily for 404)
Now you can add special error pages for http error codes. Currently it works only for 404 errors. If a route is called, which isn't defined, the framwork gave our a generic 404 error page. Now you can redirect this error to a controller, which allowes you to create a special error handling for that case yourself. you just need to add a route "404 => MyErrorController" to your routing list. If it's not defined, noting will change and the old error message will be returned as beforehand.
-rw-r--r--lib/zero/router.rb24
-rw-r--r--spec/unit/zero/router/call_spec.rb14
2 files changed, 36 insertions, 2 deletions
diff --git a/lib/zero/router.rb b/lib/zero/router.rb
index 7f16933..0d3859a 100644
--- a/lib/zero/router.rb
+++ b/lib/zero/router.rb
@@ -16,6 +16,14 @@ module Zero
# router = Zero::Router.new(
# '/foo/:id' => FooController
# )
+ #
+ # # @example of a simple router
+ # # which supports an extra controller for a 404 error page
+ # router = Zero::Router.new(
+ # '/' => WelcomeController,
+ # 404 => NotFoundController
+ # )
+ #
class Router
# match for variables in routes
VARIABLE_MATCH = %r{:(\w+)[^/]?}
@@ -41,7 +49,14 @@ module Zero
# @param routes [Hash] a map of URLs to rack compatible applications
def initialize(routes)
@routes = {}
- routes.to_a.sort_by(&:first).reverse.each do |route, target|
+
+ routes.to_a.sort_by{|x| x[0].to_s}.reverse.each do |route, target|
+ # Support for special error handling
+ if route.is_a? Integer
+ @routes[route] = target
+ next
+ end
+
@routes[
Regexp.new(REGEX_BEGINNING +
route.gsub(VARIABLE_MATCH, VARIABLE_REGEX) +
@@ -58,6 +73,9 @@ module Zero
def call(env)
env[ENV_KEY_CUSTOM] ||= {}
@routes.each do |route, target|
+ # Skip all routes, which keys are Integers
+ next if route.is_a? Integer
+
match = route.match(env[ENV_KEY_PATH_INFO])
if match
match.names.each_index do |i|
@@ -66,6 +84,10 @@ module Zero
return target.call(env)
end
end
+ # If no route is found, we call the target 404 error route, if it's set
+ return @routes[404].call(env) unless @routes[404].nil?
+
+ # If no target for the 404 error is set, we return a default message
[404, {'Content-Type' => 'text/html'}, ['Not found!']]
end
end
diff --git a/spec/unit/zero/router/call_spec.rb b/spec/unit/zero/router/call_spec.rb
index 835d51d..dabf664 100644
--- a/spec/unit/zero/router/call_spec.rb
+++ b/spec/unit/zero/router/call_spec.rb
@@ -9,6 +9,10 @@ describe Zero::Router, '#call' do
let(:wrong_app) do
lambda {|env| [200, {'Content-Type' => 'text/html'}, 'Wrong'] }
end
+
+ let(:not_found_app) do
+ lambda {|env| [404, {'Content-Type' => 'text/html'}, ['Wrong way!']] }
+ end
let(:app) { SpecApp }
shared_examples_for 'a sample app' do
@@ -39,7 +43,7 @@ describe Zero::Router, '#call' do
end
context 'with nested routes' do
- let(:routes) {{ '/' => wrong_app, '/foo' => app, '/foo/bar' => wrong_app }}
+ let(:routes) {{ '/foo/bar' => wrong_app, '/foo' => app, '/' => wrong_app }}
let(:env) { EnvGenerator.get('/foo') }
it_behaves_like "a sample app"
end
@@ -76,6 +80,14 @@ describe Zero::Router, '#call' do
it_behaves_like "a sample app"
end
+ context 'with a route not found, but 404 error route set' do
+ let(:routes) {{ '/foo/bar/baz' => app, 404 => not_found_app }}
+ let(:env) { EnvGenerator.get('/foo/bar') }
+ let(:result) { ['Wrong way!'] }
+ let(:status_code) { 404 }
+ it_behaves_like "a sample app"
+ end
+
context 'with parameters' do
let(:routes) {{ '/foo/:id' => app }}
let(:env) { EnvGenerator.get('/foo/bar') }