Add custom short code support to web UI

Allow users to optionally specify their own short code when
shortening a URL, instead of always generating a random one.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 21:55:59 -07:00
parent 131924520d
commit f96e8cfaf2
3 changed files with 27 additions and 8 deletions

View File

@@ -5,6 +5,7 @@ import (
"database/sql" "database/sql"
"embed" "embed"
"net/http" "net/http"
"regexp"
"strings" "strings"
"git.wntrmute.dev/mc/mcdsl/auth" "git.wntrmute.dev/mc/mcdsl/auth"
@@ -82,6 +83,14 @@ func (srv *server) postURL(w http.ResponseWriter, r *http.Request) {
return return
} }
customShort := strings.TrimSpace(r.FormValue("custom"))
if customShort != "" {
if !regexp.MustCompile(`^[a-zA-Z0-9]+$`).MatchString(customShort) {
http.Error(w, "custom short code must be letters and numbers only", http.StatusBadRequest)
return
}
}
url, err = links.CleanString(url, stripQuery) url, err = links.CleanString(url, stripQuery)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
@@ -89,7 +98,7 @@ func (srv *server) postURL(w http.ResponseWriter, r *http.Request) {
} }
ctx := context.Background() ctx := context.Background()
short, err := links.StoreURL(ctx, srv.db, url) short, err := links.StoreURL(ctx, srv.db, url, customShort)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return return

View File

@@ -134,14 +134,16 @@ func Lookup(ctx context.Context, db *sql.DB, s string) (string, error) {
return short, nil return short, nil
} }
func StoreURL(ctx context.Context, db *sql.DB, s string) (string, error) { func StoreURL(ctx context.Context, db *sql.DB, s string, customShort string) (string, error) {
short, err := Lookup(ctx, db, s) if customShort == "" {
if err == nil { short, err := Lookup(ctx, db, s)
return short, nil if err == nil {
} return short, nil
}
if err != sql.ErrNoRows { if err != sql.ErrNoRows {
return "", err return "", err
}
} }
u, err := FromString(s) u, err := FromString(s)
@@ -149,6 +151,10 @@ func StoreURL(ctx context.Context, db *sql.DB, s string) (string, error) {
return "", err return "", err
} }
if customShort != "" {
u.Short = customShort
}
err = u.Store(ctx, db) err = u.Store(ctx, db)
if err != nil { if err != nil {
return "", err return "", err

View File

@@ -13,6 +13,10 @@
<label for="value">URL</label> <label for="value">URL</label>
<input type="text" id="value" name="value" placeholder="https://..." required> <input type="text" id="value" name="value" placeholder="https://..." required>
</div> </div>
<div class="form-group">
<label for="custom">Custom short code (optional)</label>
<input type="text" id="custom" name="custom" placeholder="e.g. mylink" pattern="[a-zA-Z0-9]+" title="Letters and numbers only">
</div>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" name="strip"> Strip query string <input type="checkbox" name="strip"> Strip query string