Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion context/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ use Utopia::Redirection::Rewrite,
use Utopia::Redirection::DirectoryIndex,
index: 'index.html'

# Redirect (error) status codes to actual pages:
~~~

Place {ruby Utopia::Redirection::Errors} after all client-visible redirection middleware. It maps unhandled error responses to internal error documents while retaining the original response status. Because its internal requests invoke the downstream application directly, redirects configured before it are bypassed:

~~~ ruby
use Utopia::Redirection::Errors,
404 => '/errors/file-not-found'
~~~
Expand Down
6 changes: 5 additions & 1 deletion guides/middleware/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ use Utopia::Redirection::Rewrite,
use Utopia::Redirection::DirectoryIndex,
index: 'index.html'

# Redirect (error) status codes to actual pages:
~~~

Place {ruby Utopia::Redirection::Errors} after all client-visible redirection middleware. It maps unhandled error responses to internal error documents while retaining the original response status. Because its internal requests invoke the downstream application directly, redirects configured before it are bypassed:

~~~ ruby
use Utopia::Redirection::Errors,
404 => '/errors/file-not-found'
~~~
Expand Down
4 changes: 4 additions & 0 deletions lib/utopia/redirection/errors.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
module Utopia
module Redirection
# A middleware which performs internal redirects based on error status codes.
#
# Place this middleware after client-visible redirection middleware in the
# application configuration. Internal error-document requests invoke the
# delegate directly, bypassing middleware configured before this one.
class Errors < Protocol::HTTP::Middleware
# @param codes [Hash<Integer,String>] The redirection path for a given error code.
def initialize(app, codes = {})
Expand Down
1 change: 1 addition & 0 deletions setup/site/config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

use Utopia::Redirection::DirectoryIndex

# Handle error documents after client redirects so internal requests bypass them:
use Utopia::Redirection::Errors, {
404 => "/errors/file-not-found"
}
Expand Down
25 changes: 22 additions & 3 deletions test/utopia/redirection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ def tracked_body(name, events)
}) do
use Utopia::Redirection::Rewrite, {"/" => "/welcome/index"}
use Utopia::Redirection::DirectoryIndex
use Utopia::Redirection::Moved, "/a", "/b"
use Utopia::Redirection::Moved, "/hierarchy/", "/hierarchy", flatten: true
use Utopia::Redirection::Moved, "/weird", "/status", status: 333
use Utopia::Redirection::Errors, {
404 => "/error",
418 => "/teapot"
}
use Utopia::Redirection::Moved, "/a", "/b"
use Utopia::Redirection::Moved, "/hierarchy/", "/hierarchy", flatten: true
use Utopia::Redirection::Moved, "/weird", "/status", status: 333
end
end

Expand Down Expand Up @@ -84,6 +84,25 @@ def tracked_body(name, events)
expect(last_response.read).to be == "File not found :("
end

it "bypasses client redirects for internal error documents" do
application = Utopia::Application.build(Protocol::HTTP::Middleware.for do |request|
if request.path_info == "/error"
Utopia::Response.text("Internal error document")
else
Utopia::Response[404, {}, []]
end
end) do
use Utopia::Redirection::Rewrite, {"/error" => "/redirected"}
use Utopia::Redirection::Errors, 404 => "/error"
end

response = application.call(Protocol::HTTP::Request["GET", "/missing"])

expect(response.status).to be == 404
expect(response.headers["location"]).to be == nil
expect(response.read).to be == "Internal error document"
end

it "closes the response replaced by an error document" do
events = []
application = Utopia::Application.build(Protocol::HTTP::Middleware.for do |request|
Expand Down
Loading