Build the GitHub button's URL in Go, not in four templates - #639
Merged
Merged
Conversation
#631 moved GitHub's authorize URL into Go so the escaping was decided once. It left each theme assembling the URL that reaches it: href="/login/github{{ if .next }}{{ if ne .next "/" }}?next={{ .next | urlquery }}{{ end }}{{ end }}" A nested conditional building a URL, copied into four repositories — the same shape of problem, one step further out. GithubLoginURL decides it instead, and the templates print the result: href="{{ .github_login_url }}" Beyond being shorter, this makes the URL's shape the server's business: adding to it later touches no theme. next stays in the context because the email login still redirects to it in the browser once its AJAX call succeeds; that is behaviour rather than URL construction. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This was referenced Sep 25, 2026
There was a problem hiding this comment.
Copilot review overview
🟢 Approval recommended
The change cleanly centralizes URL construction server-side, updates the affected template, and adds targeted tests that validate both escaping and round-trip behavior.
Review effort: Lite
Findings: None
What changed in this PR
Moves construction of the /login/github button URL out of theme markup and into Go so URL shape/escaping is defined once server-side, with coverage to ensure next is correctly preserved and safely encoded.
Changes:
- Add
GithubLoginURL(next)helper to build/login/github(optionally with?next=...) using consistent escaping rules. - Pass
github_login_urlinto the login template context and simplify the template to render it directly. - Add unit tests covering empty/
/cases, escaping (including&), and round-trip parsing ofnext.
| File | Description |
|---|---|
| themes/default/templates/login.html | Replaces inline conditional URL-building with {{ .github_login_url }}. |
| blog/blog.go | Introduces GithubLoginURL, computes next once, and injects github_login_url into the render context. |
| blog/github_login_test.go | Adds tests to validate escaping behavior and round-trip parsing for the constructed login URL. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #638, prompted by a fair observation: it is odd that the themes carry this logic.
The leftover
#631 moved GitHub's authorize URL into Go so the escaping was decided once. It left each theme assembling the URL that reaches it:
A nested conditional building a URL, copied into four repositories — the same shape of problem the earlier work set out to remove, one step further out.
The change
GithubLoginURLdecides it, and the templates print the result:Beyond being shorter, this makes the URL's shape the server's business: if it ever needs another parameter, no theme changes again.
nextstays in the context because the email login still redirects to it in the browser once its AJAX call succeeds — behaviour rather than URL construction.Tests
TestGithubLoginURL— the empty and/cases give a bare path;&innextis escaped rather than starting a second parameterTestGithubLoginURL_SurvivesARoundTrip— what the button points at parses back to thenextit was built from, sinceGithubLoginreads it as a query parameterVerified against a local instance
/loginrequestnext/login/github?next=/admin/settings/login/github?next=%2Fadmin%2Fsettings?next=https://evil.example/login/github(dropped bySafeNext)Then followed it through: the button's URL redirects to GitHub with a state, and replaying GitHub's return with that state reaches the exchange — so the stored
nextand state still round-trip.Themes
Merge order as before: this first, then the themes. An un-updated theme renders an empty
hrefon the button, so unlike the last round they do want updating promptly — but nothing else on the page is affected.🤖 Generated with Claude Code