diff --git a/api.go b/api.go index 76af347..3eebd37 100644 --- a/api.go +++ b/api.go @@ -29,20 +29,30 @@ func apiPostCreateHugo(w http.ResponseWriter, r *http.Request) { p.Path = path p.Section = section p.Slug = slug - aliases = append(aliases, alias) err = p.replace() if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return } - for _, alias := range aliases { + aliases = append(aliases, alias) + for i, alias := range aliases { // Fix relativ paths if !strings.HasPrefix(alias, "/") { splittedPostPath := strings.Split(p.Path, "/") alias = strings.TrimSuffix(p.Path, splittedPostPath[len(splittedPostPath)-1]) + alias } - if alias != "" { - _ = createOrReplaceRedirect(alias, p.Path) + alias = strings.TrimSuffix(alias, "/") + if alias == p.Path { + alias = "" + } + aliases[i] = alias + } + if len(aliases) > 0 { + p.Parameters["aliases"] = aliases + err = p.replace() + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return } } w.Header().Set("Location", appConfig.Server.PublicAddress+p.Path) diff --git a/databaseMigrations.go b/databaseMigrations.go index 9432e6d..4e417d9 100644 --- a/databaseMigrations.go +++ b/databaseMigrations.go @@ -19,7 +19,6 @@ func migrateDb() error { CREATE TABLE post_parameters (id integer primary key autoincrement, path text not null, parameter text not null, value text); CREATE INDEX index_pp_path on post_parameters (path); CREATE TRIGGER AFTER DELETE on posts BEGIN delete from post_parameters where path = old.path; END; - CREATE TABLE redirects (fromPath text not null, toPath text not null, primary key (fromPath, toPath)); CREATE TABLE indieauthauth (time text not null, code text not null, me text not null, client text not null, redirect text not null, scope text not null); CREATE TABLE indieauthtoken (time text not null, token text not null, me text not null, client text not null, scope text not null); CREATE INDEX index_iat_token on indieauthtoken (token); diff --git a/http.go b/http.go index e26f77d..3b1fd05 100644 --- a/http.go +++ b/http.go @@ -174,14 +174,14 @@ func buildHandler() (http.Handler, error) { } } - // Redirects - allRedirectPaths, err := allRedirectPaths() + // Post aliases + allPostAliases, err := allPostAliases() if err != nil { return nil, err } - for _, path := range allRedirectPaths { + for _, path := range allPostAliases { if path != "" { - r.With(cacheMiddleware, minifier.Middleware).Get(path, serveRedirect) + r.With(cacheMiddleware).Get(path, servePostAlias) } } diff --git a/postAliases.go b/postAliases.go new file mode 100644 index 0000000..c1f8358 --- /dev/null +++ b/postAliases.go @@ -0,0 +1,39 @@ +package main + +import ( + "database/sql" + "net/http" +) + +func allPostAliases() ([]string, error) { + var aliases []string + rows, err := appDbQuery("select distinct value from post_parameters where parameter = 'aliases' and value != path") + if err != nil { + return nil, err + } + for rows.Next() { + var path string + _ = rows.Scan(&path) + aliases = append(aliases, path) + } + return aliases, nil +} + +func servePostAlias(w http.ResponseWriter, r *http.Request) { + row, err := appDbQueryRow("select path from post_parameters where parameter = 'aliases' and value = @alias", sql.Named("alias", r.URL.Path)) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + var path string + err = row.Scan(&path) + if err == sql.ErrNoRows { + serve404(w, r) + return + } else if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(w, r, path, http.StatusFound) + return +} diff --git a/redirects.go b/redirects.go deleted file mode 100644 index 824f931..0000000 --- a/redirects.go +++ /dev/null @@ -1,72 +0,0 @@ -package main - -import ( - "database/sql" - "errors" - "net/http" - "strings" -) - -var errRedirectNotFound = errors.New("redirect not found") - -func serveRedirect(w http.ResponseWriter, r *http.Request) { - redirect, err := getRedirect(r.URL.Path) - if err == errRedirectNotFound { - serve404(w, r) - return - } else if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return - } - // Send redirect - w.Header().Set("Location", redirect) - render(w, templateRedirect, &renderData{ - Data: redirect, - }) - w.WriteHeader(http.StatusFound) -} - -func getRedirect(fromPath string) (string, error) { - var toPath string - row, err := appDbQueryRow("with recursive f (i, fp, tp) as (select 1, fromPath, toPath from redirects where fromPath = ? union all select f.i + 1, r.fromPath, r.toPath from redirects as r join f on f.tp = r.fromPath) select tp from f order by i desc limit 1", fromPath) - if err != nil { - return "", err - } - err = row.Scan(&toPath) - if err == sql.ErrNoRows { - return "", errRedirectNotFound - } else if err != nil { - return "", err - } - return toPath, nil -} - -func allRedirectPaths() ([]string, error) { - var redirectPaths []string - rows, err := appDbQuery("select fromPath from redirects") - if err != nil { - return nil, err - } - for rows.Next() { - var path string - _ = rows.Scan(&path) - redirectPaths = append(redirectPaths, path) - } - return redirectPaths, nil -} - -func createOrReplaceRedirect(from, to string) error { - if from == "" || to == "" { - return errors.New("empty path") - } - if from == to { - // Don't need a redirect - return nil - } - from = strings.TrimSuffix(from, "/") - _, err := appDbExec("insert or replace into redirects (fromPath, toPath) values (?, ?)", from, to) - if err != nil { - return err - } - return reloadRouter() -}