Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dynamic rule-based redirects #1914

Closed
8 tasks done
Tracked by #1916
acelaya opened this issue Nov 8, 2023 · 4 comments · Fixed by #2040
Closed
8 tasks done
Tracked by #1916

Dynamic rule-based redirects #1914

acelaya opened this issue Nov 8, 2023 · 4 comments · Fixed by #2040
Labels
Milestone

Comments

@acelaya
Copy link
Member

acelaya commented Nov 8, 2023

Summary

This RFC describes how dynamic redirects could be improved to support multiple combinations of rules, and then, be able to add more rules in future.

The first iteration should consist on preparing the base implementation for this to work, and potentially migrate device-specific long URLs to be the first supported redirect rule.

Use case

Supporting multiple dynamic redirect rules has been requested in the past, specially since device-specific redirects were implemented.


@acelaya acelaya added the feature label Nov 8, 2023
@acelaya acelaya added this to the 4.0.0 milestone Nov 8, 2023
@acelaya acelaya added this to Shlink Nov 8, 2023
@acelaya acelaya moved this to Todo in Shlink Feb 1, 2024
@acelaya acelaya moved this from Todo to In Progress in Shlink Feb 24, 2024
@acelaya
Copy link
Member Author

acelaya commented Feb 24, 2024

Preliminary persistence model

erDiagram
    short_urls 1--many(0) short_url_redirect_rules : has
    short_url_redirect_rules many(1)--many(1) redirect_conditions : has
    short_urls {
        string long_url
    }
    short_url_redirect_rules {
        int short_url_id
        int priority
        string long_url
    }
    redirect_conditions {
        string name UK "Example: device-android, query-foo-bar, language-en-US"
        string type "enum(device, language, query...)"
        string match_key "optional/nullable"
        string match_value
    }
Loading
  • redirect_conditions:
    • The name will be generated combining type+match_key+match_value, or just type+match_value if match_key is null.
    • The name will be used as the public way to identify conditions, avoiding the autonumeric primary key to be exposed.

EDIT: While implementing the API model, it was proved that a properly normalized persistence would get in the way, so conditions will finally not have a unique name nor be shared between rules. Every rule will have its set of conditions.

This means more duplicated data in the database, but it should have a very low impact anyway.

@acelaya
Copy link
Member Author

acelaya commented Feb 24, 2024

Dynamic redirects

Short URL redirects currently work like this:

  1. RedirectAction is dispatched if an existing short URL could be matched.
  2. ShortUrlRedirectionBuilder is invoked, and tries to resolve the long URL to redirect to.
    • Using the User-Agent header it tries to match a device long URL
    • If it cannot match, it falls back to the regular long URL
  3. Depending on how Shlink is configured, it appends extra path and/or query params, if needed.

With the new system, we can keep steps 1 and 3 unmodified, and the ShortUrlRedirectionBuilder contract, as its only public method already expects the ShortUrl and the Request object, which will be needed to match rules and conditions.

We'll have to inject a new service though, which will be the one iterating over rules and trying to match one. Every condition will try to be matched by using a type-specific plugin which knows how to extract and match the appropriate information from the Request object.

@acelaya
Copy link
Member Author

acelaya commented Feb 25, 2024

API model

I'm thinking the simplest solution is to allow editing or listing rules and conditions always linked to a short URL, so the preliminary endpoints could look like this:

  • GET /short-urls/{shortCode}/redirect-rules[?domain={domain}]
  • POST /short-urls/{shortCode}/redirect-rules[?domain={domain}]

Then in the UI, we'll call the first one just before editing a short URL, and the second one after creating/editing a short URL succeeded.

The only drawback about this approach is if the short URL creation works and saving the rules fails, which would leave an inconsistent state, but it's a negligible risk.

The benefit is that it simplifies the short URL creation/edition endpoint, which was something that got more complex when device long URLs were implemented and I always regretted.

@acelaya
Copy link
Member Author

acelaya commented Feb 27, 2024

CLI handling

I have realized device long URLs were never supported in the CLI, which I guess it's good now, as it's one less thing to change.

For redirect rules, I think a set of new commands is the best approach. Something like short-url:list-rules and short-url:set-rules.

EDIT: The complexity on the structure of rules and conditions, makes it hard to allow them to be programatically editable via command flags and arguments.

So I will instead add a single command for now, short-url:manage-rules, which will allow to interactively edit the rules and conditions via questions wit multiple steps.

EDIT 2: This is how it looks like. It's not perfect, but it should be usable.

manage-rules-command.webm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

1 participant