Commit: 0078d7f9871010e23825e6a98dcd9ad35b4a7cc9 Parent: ac38a3786fa576876eca984485c4abfc092bf7a3 Author: Vi Grey Date: 2023-11-12 20:58 UTC Summary: Make /webring/id/{user_id} redirect to URL * Add --not-found flag for 404 html file * Fix empty flag value at last argument src/blanket-fort-webring.go | 5 ++++- src/flags.go | 58 +++++++++++++++++++++++++++++++++++++--------------------- src/http.go | 26 ++++++++++++++++++++++---- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/blanket-fort-webring.go b/src/blanket-fort-webring.go index 34b2662..2392798 100644 --- a/src/blanket-fort-webring.go +++ b/src/blanket-fort-webring.go @@ -9,7 +9,8 @@ import ( ) const ( - VERSION = "0.0.1" + PROGRAM = "blanket-fort-webring" + VERSION = "0.0.2" ) var ( @@ -36,6 +37,8 @@ func getWebringLink(id, action string) string { } else { return webringEntries[(x+int(nBig.Int64())+1)%webringLen].URL } + case "": + return webringEntries[x].URL } } } diff --git a/src/flags.go b/src/flags.go index a2185a9..875e5b9 100644 --- a/src/flags.go +++ b/src/flags.go @@ -9,35 +9,45 @@ import ( ) var ( - portNumber int - listPath string - help bool - version bool + notFoundPath string + portNumber int + listPath string + help bool + version bool ) func handleFlags(args []string) (err error) { for x := 0; x < len(args); x++ { arg := args[x] switch strings.ToLower(arg) { - case "--list", "-l": + case "--not-found", "-n": + x++ if x == len(args) { - err = errors.New(fmt.Sprintf("blanket-fort-webring: flag `%s` missing value\nUse `blanket-fort-webring --help` for details", arg)) + err = errors.New(fmt.Sprintf("%s: flag `%s` missing value\nUse `%s --help` for details", PROGRAM, arg, os.Args[1])) return } + if notFoundPath == "" { + notFoundPath = args[x] + } + case "--list", "-l": x++ + if x == len(args) { + err = errors.New(fmt.Sprintf("%s: flag `%s` missing value\nUse `%s --help` for details", PROGRAM, arg, os.Args[1])) + return + } if listPath == "" { listPath = args[x] } case "--port", "-p": + x++ if x == len(args) { - err = errors.New(fmt.Sprintf("blanket-fort-webring: flag `%s` missing value\nUse `blanket-fort-webring --help` for details", arg)) + err = errors.New(fmt.Sprintf("%s: flag `%s` missing value\nUse `%s --help` for details", PROGRAM, arg, os.Args[1])) return } - x++ if portNumber == 0 { if portNumber, _ = strconv.Atoi(args[x]); portNumber == 0 { portNumber = 0 - err = errors.New(fmt.Sprintf("blanket-fort-webring: invalid value for flag `%s`. Must be 1-65535\nUse `blanket-fort-webring --help` for details", arg)) + err = errors.New(fmt.Sprintf("%s: invalid value for flag `%s`. Must be 1-65535.\nUse `%s --help` for details", PROGRAM, arg, os.Args[1])) return } } @@ -47,7 +57,7 @@ func handleFlags(args []string) (err error) { case "--version": version = true default: - err = errors.New(fmt.Sprintf("blanket-fort-webring: invalid argument `%s`\nUse `blanket-fort-webring --help` for details", arg)) + err = errors.New(fmt.Sprintf("%s: invalid argument `%s`\nUse `%s --help` for details", PROGRAM, arg, os.Args[1])) return } } @@ -60,26 +70,32 @@ func handleFlags(args []string) (err error) { os.Exit(0) } if listPath == "" { - err = errors.New("blanket-fort-webring: missing flag `--list`\nUse `blanket-fort-webring --help` for details") + err = errors.New(fmt.Sprintf("%s: missing flag --list\nUse `%s --help` for details", PROGRAM, os.Args[1])) return } if portNumber == 0 { - err = errors.New("blanket-fort-webring: missing flag `--port`\nUse `blanket-fort-webring --help` for details") + err = errors.New(fmt.Sprintf("%s: missing flag --port\nUse `%s --help` for details", PROGRAM, os.Args[1])) return } return } func displayHelp() { - fmt.Printf("Usage: blanket-fort-webring [ OPTIONS ]...\n\nOptions:\n" + - " -h, --help Print Help (this message) and exit\n" + - " -l, --list Path of webring JSON list\n" + - " -p, --port Localhost port to run webring HTTP server on\n" + - " --version Print version information and exit\n\n" + - "Examples:\n" + - " blanket-fort-webring --port 9999 --list ~/list.json\n" + - " (This example starts blanket-fort-webring on 127.0.0.1:9999 and uses\n" + - " the webring json list at ~/list.json)\n") + fmt.Printf(`Usage: %s [ OPTIONS ]... + +Options: + -h, --help Print Help (this message) and exit + -l, --list Path of webring JSON list + -n, --not-found Path of 404 status page + -p, --port Localhost port to run webring HTTP server on + --version Print version information and exit + +Examples: + %s --port 9999 --list ~/list.json -n ~/404.html + (This example starts blanket-fort-webring on 127.0.0.1:9999, uses + the webring json list at ~/list.json, and uses the 404 page + ~/404.html) +`, PROGRAM, PROGRAM) } func displayVersion() { diff --git a/src/http.go b/src/http.go index 73e170b..1c15a4b 100644 --- a/src/http.go +++ b/src/http.go @@ -2,6 +2,7 @@ package main import ( "fmt" + "io" "net" "net/http" "os" @@ -15,9 +16,23 @@ const ( ) var ( - webringLinkRe = regexp.MustCompile(`^/webring/id/(\S*)/(prev|next|random)$`) + webringLinkRe = regexp.MustCompile(`(?U)^/webring/id/(\S*)(?:/(prev|next|random)?)?$`) ) +func handle404(w http.ResponseWriter) { + w.WriteHeader(http.StatusNotFound) + if notFoundPath != "" { + if f, err := os.Open(notFoundPath); err == nil { + defer f.Close() + w.Header().Set("content-type", "text/html") + io.Copy(w, f) + return + } + } + w.Write([]byte("404 - Page Not Found")) + return +} + func catchAll(w http.ResponseWriter, r *http.Request) { u := r.URL.Path if len(u) > 0 { @@ -26,10 +41,13 @@ func catchAll(w http.ResponseWriter, r *http.Request) { } } if webringReMatches := webringLinkRe.FindStringSubmatch(u); len(webringReMatches) > 2 { - webringLinkNew := getWebringLink(webringReMatches[1], webringReMatches[2]) - http.Redirect(w, r, webringLinkNew, http.StatusSeeOther) + if webringLinkNew := getWebringLink(webringReMatches[1], webringReMatches[2]); webringLinkNew != "" { + http.Redirect(w, r, webringLinkNew, http.StatusSeeOther) + } else { + handle404(w) + } } else { - w.WriteHeader(http.StatusNotFound) + handle404(w) } }