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
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,20 @@ https://udl.fdo.cr/?r=https://reservation.com/restaurants/silvestre

This will bypass the limitation of Safari (embedded webview) that doesn't allow your Universal Links to trigger. You should now have a working "open in app" UX.

### Default destination support
If the `DEFAULT_DESTINATION` environment variable is set and no `r` query parameter is provided:

- A request to the root path:

- `https://udl.fdo.cr/` will redirect to `DEFAULT_DESTINATION`

- A request with a path:

- `https://udl.fdo.cr/restaurants/silvestre` will redirect to `DEFAULT_DESTINATION + "/restaurants/silvestre"`

The original `?r=` format continues to work as before. If `DEFAULT_DESTINATION` is not set, behavior remains unchanged.


`https://udl.fdo.cr` is a **public (free to use) UDL Server** instance for anyone to try out and use on your own. It has usage limits (throttling), which should be more than enough for most low-medium traffic websites.

If this service adds value to you or your company please consider sponsoring me right here on GitHub. I offer different sponsor tiers too where I will host a private instance without usage limits for ensured reliability. [Read more about this on my profile](https://github.com/sponsors/fdocr) to support the OSS work I do on my free time.
Expand Down
62 changes: 52 additions & 10 deletions spec/server_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
require "./spec_helper"

def with_default_destination(value)
original = ENV["DEFAULT_DESTINATION"]?
ENV["DEFAULT_DESTINATION"] = value
yield
ensure
if original
ENV["DEFAULT_DESTINATION"] = original
else
ENV.delete("DEFAULT_DESTINATION")
end
end

def without_default_destination
original = ENV["DEFAULT_DESTINATION"]?
ENV.delete("DEFAULT_DESTINATION")
yield
ensure
ENV["DEFAULT_DESTINATION"] = original if original
end

describe "UDL Server" do
context "success" do
it "redirects to the Target URI parameter if valid" do
Expand All @@ -16,6 +36,24 @@ describe "UDL Server" do
response.headers["Location"].should eq(target_url)
end

it "redirects to DEFAULT_DESTINATION when root path has no r parameter and DEFAULT_DESTINATION is set" do
with_default_destination("https://example.com") do
get "/"

response.status_code.should eq(302)
response.headers["Location"].should eq("https://example.com")
end
end

it "redirects to DEFAULT_DESTINATION + path when path has no r parameter and DEFAULT_DESTINATION is set" do
with_default_destination("https://example.com") do
get "/about"

response.status_code.should eq(302)
response.headers["Location"].should eq("https://example.com/about")
end
end

it "populates apple-app-site-association file" do
get "/.well-known/apple-app-site-association"

Expand All @@ -26,20 +64,24 @@ describe "UDL Server" do
end

context "failure" do
it "renders fallback page if target redirect not provided" do
get "/"
it "renders fallback page if target redirect not provided and DEFAULT_DESTINATION is not set" do
without_default_destination do
get "/"

response.status_code.should eq(200)
response.body.should contain("Something went wrong")
response.body.should contain("Check out the <a href=\"https://github.com/fdocr/udl-server#Troubleshooting\">README</a> for more details")
response.status_code.should eq(200)
response.body.should contain("Something went wrong")
response.body.should contain("Check out the <a href=\"https://github.com/fdocr/udl-server#Troubleshooting\">README</a> for more details")
end
end

it "renders fallback page if requesting any other path" do
get "/about-us"
it "renders fallback page if requesting any other path and DEFAULT_DESTINATION is not set" do
without_default_destination do
get "/about-us"

response.status_code.should eq(200)
response.body.should contain("Something went wrong")
response.body.should contain("Check out the <a href=\"https://github.com/fdocr/udl-server#Troubleshooting\">README</a> for more details")
response.status_code.should eq(200)
response.body.should contain("Something went wrong")
response.body.should contain("Check out the <a href=\"https://github.com/fdocr/udl-server#Troubleshooting\">README</a> for more details")
end
end

it "renders fallback page if r parameter is an invalid URL" do
Expand Down
25 changes: 22 additions & 3 deletions src/server.cr
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,19 @@ error_context = "Use the root path instead, i.e. `/?r=TARGET_URL_HERE`"

get "/" do |env|
begin
target_uri = URI.parse(env.params.query["r"])
redirect_param = env.params.query["r"]?

# If no r parameter, redirect to DEFAULT_DESTINATION (only if set)
unless redirect_param
if default_destination = ENV["DEFAULT_DESTINATION"]?
env.redirect default_destination
next
else
raise "Missing redirect parameter"
end
end

target_uri = URI.parse(redirect_param)

# Check that it's a valid URL
valid_uri = /https?/ =~ target_uri.scheme && target_uri.host
Expand Down Expand Up @@ -48,8 +60,15 @@ get "/.well-known/apple-app-site-association" do |env|
end

get "/*" do |env|
udl_error = "Invalid path `#{env.request.path}` - #{error_context}"
render "src/views/fallback.ecr"
# If DEFAULT_DESTINATION is set, redirect to it + path; otherwise show fallback.
if default_target = ENV["DEFAULT_DESTINATION"]?
path = env.request.path
final_url = default_target.rstrip("/") + "/" + path.lstrip("/")
env.redirect final_url
else
udl_error = "Invalid path `#{env.request.path}` - #{error_context}"
render "src/views/fallback.ecr"
end
end

error 404 do
Expand Down