Short URLs

This commit is contained in:
Jan-Lukas Else 2020-12-22 22:15:29 +01:00
parent 75a960e975
commit 9da9e37f32
8 changed files with 90 additions and 1 deletions

View File

@ -97,6 +97,15 @@ func migrateDb() error {
return err return err
}, },
}, },
&migrator.Migration{
Name: "00008",
Func: func(tx *sql.Tx) error {
_, err := tx.Exec(`
create table shortpath (id integer primary key autoincrement, path text not null, unique(path));
`)
return err
},
},
), ),
) )
if err != nil { if err != nil {

View File

@ -173,6 +173,9 @@ func buildHandler() (http.Handler, error) {
r.With(cacheMiddleware).Get(path, serveAsset) r.With(cacheMiddleware).Get(path, serveAsset)
} }
// Short paths
r.With(cacheMiddleware).Get("/s/{id:[0-9a-fA-F]+}", redirectToLongPath)
paginationPath := "/page/{page:[0-9-]+}" paginationPath := "/page/{page:[0-9-]+}"
feedPath := ".{feed:rss|json|atom}" feedPath := ".{feed:rss|json|atom}"

View File

@ -51,6 +51,7 @@ func servePost(w http.ResponseWriter, r *http.Request) {
if canonical == "" { if canonical == "" {
canonical = p.fullURL() canonical = p.fullURL()
} }
w.Header().Add("Link", fmt.Sprintf("<%s>; rel=shortlink", p.shortURL()))
render(w, templatePost, &renderData{ render(w, templatePost, &renderData{
blogString: p.Blog, blogString: p.Blog,
Canonical: canonical, Canonical: canonical,

View File

@ -12,6 +12,14 @@ func (p *post) fullURL() string {
return appConfig.Server.PublicAddress + p.Path return appConfig.Server.PublicAddress + p.Path
} }
func (p *post) shortURL() string {
s, err := shortenPath(p.Path)
if err != nil {
return ""
}
return appConfig.Server.PublicAddress + s
}
func (p *post) firstParameter(parameter string) (result string) { func (p *post) firstParameter(parameter string) (result string) {
if pp := p.Parameters[parameter]; len(pp) > 0 { if pp := p.Parameters[parameter]; len(pp) > 0 {
result = pp[0] result = pp[0]

View File

@ -85,6 +85,9 @@ func initRendering() error {
}) })
return mentions return mentions
}, },
"shorturl": func(p *post) string {
return p.shortURL()
},
// Others // Others
"dateformat": func(date string, format string) string { "dateformat": func(date string, format string) string {
d, err := dateparse.ParseLocal(date) d, err := dateparse.ParseLocal(date)

64
shortPath.go Normal file
View File

@ -0,0 +1,64 @@
package main
import (
"database/sql"
"errors"
"fmt"
"net/http"
"strconv"
"github.com/go-chi/chi"
)
func shortenPath(p string) (string, error) {
if p == "" {
return "", errors.New("empty path")
}
id := getShortPathID(p)
if id == -1 {
_, err := appDbExec("insert or ignore into shortpath (path) values (@path)", sql.Named("path", p))
if err != nil {
return "", err
}
id = getShortPathID(p)
}
if id == -1 {
return "", errors.New("failed to retrieve short path for " + p)
}
return fmt.Sprintf("/s/%x", id), nil
}
func getShortPathID(p string) (id int) {
if p == "" {
return -1
}
row, err := appDbQueryRow("select id from shortpath where path = @path", sql.Named("path", p))
if err != nil {
return -1
}
err = row.Scan(&id)
if err != nil {
return -1
}
return id
}
func redirectToLongPath(rw http.ResponseWriter, r *http.Request) {
id, err := strconv.ParseInt(chi.URLParam(r, "id"), 16, 64)
if err != nil {
serve404(rw, r)
return
}
row, err := appDbQueryRow("select path from shortpath where id = @id", sql.Named("id", id))
if err != nil {
serve404(rw, r)
return
}
var path string
err = row.Scan(&path)
if err != nil {
serve404(rw, r)
return
}
http.Redirect(rw, r, path, http.StatusFound)
}

View File

@ -35,7 +35,7 @@ func (p *post) tgPost() {
message.WriteString(title) message.WriteString(title)
message.WriteString("\n\n") message.WriteString("\n\n")
} }
message.WriteString(p.fullURL()) message.WriteString(p.shortURL())
sendTelegramMessage(message.String(), tg.BotToken, tg.ChatID) sendTelegramMessage(message.String(), tg.BotToken, tg.ChatID)
} }

View File

@ -1,6 +1,7 @@
{{ define "title" }} {{ define "title" }}
<title>{{ with p .Data "title" }}{{ . }} - {{end}}{{ .Blog.Title }}</title> <title>{{ with p .Data "title" }}{{ . }} - {{end}}{{ .Blog.Title }}</title>
{{ include "postheadmeta" . }} {{ include "postheadmeta" . }}
{{ with shorturl .Data }}<link rel="shortlink" href="{{ . }}">{{ end }}
{{ end }} {{ end }}
{{ define "main" }} {{ define "main" }}