Skip to content

Commit

Permalink
Handle hole/lang renames globally
Browse files Browse the repository at this point in the history
We must wrap the affected routes in a Group with the middleware applied
to that group, moving the middleware higher doesn't work. See
go-chi/chi#892 for details.

This lays the groundwork for future hole/lang renames like Lisp → Common
Lisp.

Updates code-golf#1318
  • Loading branch information
JRaspass authored and Yewzir committed Dec 14, 2024
1 parent c396b59 commit e5509a8
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 40 deletions.
23 changes: 16 additions & 7 deletions js/_hole-common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,14 @@ async function getHoleLangNotesContent(lang: string): Promise<string> {
}

const renamedHoles: Record<string, string> = {
'eight-queens': 'n-queens',
'billiard': 'billiards',
'eight-queens': 'n-queens',
'factorial-factorisation-ascii': 'factorial-factorisation',
'grid-packing': 'css-grid',
'billiard': 'billiards',
'grid-packing': 'css-grid',
};

const renamedLangs: Record<string, string> = {
perl6: 'raku',
};

export function init(_tabLayout: boolean, setSolution: any, setCodeForLangAndSolution: any, updateReadonlyPanels: any, getEditor: () => any) {
Expand Down Expand Up @@ -68,9 +72,14 @@ export function init(_tabLayout: boolean, setSolution: any, setCodeForLangAndSol

for (const [key, value] of Object.entries(localStorage)) {
if (key.startsWith('code_')) {
const hole = key.split('_')[1];
if (hole in renamedHoles) {
localStorage.setItem(key.replace(hole, renamedHoles[hole]), value);
const [prefix, hole, lang, scoring] = key.split('_');

const newHole = renamedHoles[hole] ?? hole;
const newLang = renamedLangs[lang] ?? lang;

const newKey = [prefix, newHole, newLang, scoring].join('_');
if (key !== newKey) {
localStorage.setItem(newKey, value);
localStorage.removeItem(key);
}
}
Expand Down Expand Up @@ -877,4 +886,4 @@ export function ctrlEnter(func: Function) {
return func();
}
};
}
}
42 changes: 42 additions & 0 deletions middleware/redir_holes_langs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package middleware

import (
"net/http"
"strings"
)

// RedirHolesLangs redirects old values for {hole} and {lang}.
func RedirHolesLangs(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
newPath := r.URL.Path

// FIXME Consider using chi.RouteContext(r.Context()).RoutePattern()
// and filling in hole/lang, more robust than strings.Replace().

switch r.PathValue("hole") {
case "billiard":
newPath = strings.Replace(newPath, "/billiard", "/billiards", 1)
case "eight-queens":
newPath = strings.Replace(newPath, "/eight-queens", "/n-queens", 1)
case "factorial-factorisation-ascii":
newPath = strings.Replace(newPath, "/factorial-factorisation-ascii",
"/factorial-factorisation", 1)
case "grid-packing":
newPath = strings.Replace(newPath, "/grid-packing", "/css-grid", 1)
}

if r.PathValue("lang") == "perl6" {
newPath = strings.Replace(newPath, "/perl6", "/raku", 1)
}

if newPath == r.URL.Path {
next.ServeHTTP(w, r)
} else {
if r.URL.RawQuery != "" {
newPath += "?" + r.URL.RawQuery
}

http.Redirect(w, r, newPath, http.StatusPermanentRedirect)
}
})
}
53 changes: 31 additions & 22 deletions routes/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ func Router(db *sqlx.DB) http.Handler {
r.Get("/users/{name}", userGET)

// HTML routes that need middleware.Golfer.
r.With(middleware.Golfer).Group(func(r chi.Router) {
r.With(middleware.RedirHolesLangs, middleware.Golfer).Group(func(r chi.Router) {
r.Get("/", homeGET)
r.Get("/{hole}", holeGET)
r.Get("/about", aboutGET)
Expand All @@ -55,24 +55,29 @@ func Router(db *sqlx.DB) http.Handler {
r.Get("/cheevos/{cheevo}", apiCheevoGET)
r.Get("/golfers/{golfer}", apiGolferGET)
r.Get("/holes", apiHolesGET)
r.Get("/holes/{hole}", apiHoleGET)
r.Get("/langs", apiLangsGET)
r.Get("/langs/{lang}", apiLangGET)
r.Get(
"/mini-rankings/{hole}/{lang}/{scoring:bytes|chars}/{view:top|me|following}",
apiMiniRankingsGET,
)
r.Get("/panic", apiPanicGET)
r.Get("/solutions-log", apiSolutionsLogGET)
r.Get("/suggestions/golfers", apiSuggestionsGolfersGET)
r.Get("/wiki/*", apiWikiPageGET)

// API routes that require a logged-in golfer.
r.With(middleware.GolferArea).Group(func(r chi.Router) {
r.Get("/notes", apiNotesGET)
r.Delete("/notes/{hole}/{lang}", apiNoteDELETE)
r.Get("/notes/{hole}/{lang}", apiNoteGET)
r.Put("/notes/{hole}/{lang}", apiNotePUT)
// API routes that use {hole} or {lang}.
r.With(middleware.RedirHolesLangs).Group(func(r chi.Router) {
r.Get("/holes/{hole}", apiHoleGET)
r.Get("/langs/{lang}", apiLangGET)
r.Get(
"/mini-rankings/{hole}/{lang}/{scoring:bytes|chars}"+
"/{view:top|me|following}",
apiMiniRankingsGET,
)

// API routes that require a logged-in golfer.
r.With(middleware.GolferArea).Group(func(r chi.Router) {
r.Get("/notes", apiNotesGET)
r.Delete("/notes/{hole}/{lang}", apiNoteDELETE)
r.Get("/notes/{hole}/{lang}", apiNoteGET)
r.Put("/notes/{hole}/{lang}", apiNotePUT)
})
})
})
r.Get("/callback", callbackGET)
Expand Down Expand Up @@ -114,20 +119,24 @@ func Router(db *sqlx.DB) http.Handler {
r.Get("/medals", redir("/rankings/medals/all/all/all"))
r.Get("/solutions", redir("/rankings/misc/solutions"))

r.Get("/holes/{hole}/{lang}/{scoring}", rankingsHolesGET)
r.Get("/recent-holes/{lang}/{scoring}", rankingsHolesGET)
r.With(middleware.RedirHolesLangs).Group(func(r chi.Router) {
r.Get("/holes/{hole}/{lang}/{scoring}", rankingsHolesGET)
r.Get("/recent-holes/{lang}/{scoring}", rankingsHolesGET)

r.Get("/cheevos/{cheevo}", rankingsCheevosGET)
r.Get("/medals/{hole}/{lang}/{scoring}", rankingsMedalsGET)
r.Get("/langs/{lang}/{scoring}", rankingsLangsGET)
r.Get("/misc/{type}", rankingsMiscGET)
r.Get("/cheevos/{cheevo}", rankingsCheevosGET)
r.Get("/medals/{hole}/{lang}/{scoring}", rankingsMedalsGET)
r.Get("/langs/{lang}/{scoring}", rankingsLangsGET)
r.Get("/misc/{type}", rankingsMiscGET)
})
})
r.Route("/recent", func(r chi.Router) {
r.Get("/", redir("/recent/solutions/all/all/bytes"))
r.Get("/{lang}", recentGET)

r.Get("/golfers", recentGolfersGET)
r.Get("/solutions/{hole}/{lang}/{scoring}", recentSolutionsGET)

r.With(middleware.RedirHolesLangs).Group(func(r chi.Router) {
r.Get("/{lang}", recentGET)
r.Get("/solutions/{hole}/{lang}/{scoring}", recentSolutionsGET)
})
})
r.Get("/scores/{hole}/{lang}", scoresGET)
r.Get("/scores/{hole}/{lang}/all", scoresAllGET)
Expand Down
7 changes: 1 addition & 6 deletions routes/scores.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,9 @@ func scoresGET(w http.ResponseWriter, r *http.Request) {
if holeID == "all-holes" {
holeID = "all"
}

switch langID {
case "all-langs":
if langID == "all-holes" {
langID = "all"
case "perl6":
langID = "raku"
}

if scoring == "" {
scoring = "bytes"
}
Expand Down
28 changes: 23 additions & 5 deletions t/redirects.t
Original file line number Diff line number Diff line change
@@ -1,9 +1,27 @@
use t;
use HTTP::Tiny;
use Test;

constant $path = '/foo?bar=baz';
my constant $query = '?foo=bar';

# TODO
# is $ua->get( $_ . PATH )->{url}, 'https://code.golf' . PATH, $_
# for <http{,s}://{,www.}code{-golf.io,.golf}>;
for <
GET /api/holes/billiard /api/holes/billiards
GET /api/langs/perl6 /api/langs/raku
DELETE /api/notes/billiard/perl6 /api/notes/billiards/raku
GET /api/notes/billiard/perl6 /api/notes/billiards/raku
PUT /api/notes/billiard/perl6 /api/notes/billiards/raku
GET /billiard /billiards
GET /rankings/recent-holes/perl6/bytes /rankings/recent-holes/raku/bytes
GET /recent/perl6 /recent/raku
GET /recent/solutions/billiard/perl6/bytes /recent/solutions/billiards/raku/bytes
GET /scores/billiard/perl6 /scores/billiards/raku
> -> $method, $start, $end {
state $ua = HTTP::Tiny.new :!max-redirect;

my $location = $ua.request(
$method, "https://app:443$start$query",
)<headers><location>;

is $location, $end ~ $query, "$method $start$end";
}

done-testing;

0 comments on commit e5509a8

Please sign in to comment.