aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/http.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/http.go')
-rw-r--r--src/http.go138
1 files changed, 102 insertions, 36 deletions
diff --git a/src/http.go b/src/http.go
index 3feda8c..fce82ba 100644
--- a/src/http.go
+++ b/src/http.go
@@ -1,4 +1,4 @@
-package src
+package app
import (
"cmp"
@@ -8,14 +8,16 @@ import (
"log"
"math"
"net/http"
- "os"
- "path/filepath"
"slices"
"strconv"
"strings"
+ "time"
+ . "git.thomasvoss.com/euro-cash.eu/pkg/try"
+
+ "git.thomasvoss.com/euro-cash.eu/src/dbx"
"git.thomasvoss.com/euro-cash.eu/src/email"
- "git.thomasvoss.com/euro-cash.eu/src/mintage"
+ "git.thomasvoss.com/euro-cash.eu/src/i18n"
)
type middleware = func(http.Handler) http.Handler
@@ -29,11 +31,17 @@ func Run(port int) {
mwareC := chain(mwareB, countryHandler) // [C]ountry
mwareM := chain(mwareC, mintageHandler) // [M]intage
+ mux.Handle("GET /codes/", fs)
mux.Handle("GET /designs/", fs)
mux.Handle("GET /favicon.ico", fs)
mux.Handle("GET /fonts/", fs)
mux.Handle("GET /storage/", fs)
- mux.Handle("GET /style.min.css", fs)
+ if Debugp {
+ mux.Handle("GET /style.css", fs)
+ mux.Handle("GET /style-2.css", fs)
+ } else {
+ mux.Handle("GET /style.min.css", fs)
+ }
mux.Handle("GET /coins/designs", mwareC(final))
mux.Handle("GET /coins/mintages", mwareM(final))
mux.Handle("GET /collecting/crh", mwareC(final))
@@ -42,7 +50,7 @@ func Run(port int) {
portStr := ":" + strconv.Itoa(port)
log.Println("Listening on", portStr)
- log.Fatal(http.ListenAndServe(portStr, mux))
+ Try(http.ListenAndServe(portStr, mux))
}
func chain(xs ...middleware) middleware {
@@ -56,7 +64,10 @@ func chain(xs ...middleware) middleware {
func firstHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- ctx := context.WithValue(r.Context(), "td", &templateData{})
+ ctx := context.WithValue(r.Context(), "td", &templateData{
+ Debugp: Debugp,
+ Printers: i18n.Printers,
+ })
next.ServeHTTP(w, r.WithContext(ctx))
})
}
@@ -80,33 +91,37 @@ func finalHandler(w http.ResponseWriter, r *http.Request) {
original page they came from. */
if path == "/language" {
http.SetCookie(w, &http.Cookie{
- Name: "redirect",
- Value: cmp.Or(r.Referer(), "/"),
+ Name: "redirect",
+ Value: cmp.Or(r.Referer(), "/"),
+ Expires: time.Now().Add(24 * time.Hour),
})
}
data := r.Context().Value("td").(*templateData)
- t.Execute(w, data)
+ if err := t.Execute(w, data); err != nil {
+ log.Println(err)
+ }
}
func i18nHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
- var p, pZero Printer
+ var p, pZero i18n.Printer
if c, err := r.Cookie("locale"); err == nil {
- p = printers[strings.ToLower(c.Value)]
+ p = i18n.Printers[c.Value]
}
td := r.Context().Value("td").(*templateData)
- td.Printer = cmp.Or(p, defaultPrinter)
if p == pZero {
+ td.Printer = bestFitLanguage(r.Header.Get("Accept-Language"))
http.SetCookie(w, &http.Cookie{
Name: "redirect",
Value: r.URL.Path,
})
templates["/language"].Execute(w, td)
} else {
+ td.Printer = p
next.ServeHTTP(w, r)
}
})
@@ -123,32 +138,50 @@ func countryHandler(next http.Handler) http.Handler {
func mintageHandler(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
td := r.Context().Value("td").(*templateData)
- td.Code = strings.ToLower(r.FormValue("code"))
- if !slices.ContainsFunc(td.Countries, func(c country) bool {
- return c.Code == td.Code
- }) {
- td.Code = td.Countries[0].Code
- }
- td.Type = strings.ToLower(r.FormValue("type"))
+ td.Type = r.FormValue("type")
switch td.Type {
case "circ", "nifc", "proof":
default:
td.Type = "circ"
}
- path := filepath.Join("data", "mintages", td.Code)
- f, err := os.Open(path)
- if err != nil {
- throwError(http.StatusInternalServerError, err, w, r)
- return
+ td.FilterBy = r.FormValue("filter-by")
+ switch td.FilterBy {
+ case "country", "year":
+ default:
+ td.FilterBy = "country"
}
- defer f.Close()
- td.Mintages, err = mintage.Parse(f, path)
- if err != nil {
- throwError(http.StatusInternalServerError, err, w, r)
- return
+ mt := dbx.NewMintageType(td.Type)
+
+ switch td.FilterBy {
+ case "country":
+ td.Code = r.FormValue("country")
+ if !slices.ContainsFunc(td.Countries, func(c country) bool {
+ return c.Code == td.Code
+ }) {
+ td.Code = td.Countries[0].Code
+ }
+
+ m, err := dbx.GetMintagesByCountry(td.Code, mt)
+ if err != nil {
+ throwError(http.StatusInternalServerError, err, w, r)
+ return
+ }
+ td.CountryMintages = makeCountryMintageTable(m, td.Printer)
+ case "year":
+ var err error
+ td.Year, err = strconv.Atoi(r.FormValue("year"))
+ if err != nil || td.Year < 1999 {
+ td.Year = 1999
+ }
+ m, err := dbx.GetMintagesByYear(td.Year, mt)
+ if err != nil {
+ throwError(http.StatusInternalServerError, err, w, r)
+ return
+ }
+ td.YearMintages = makeYearMintageTable(m, td.Printer)
}
next.ServeHTTP(w, r)
@@ -157,8 +190,9 @@ func mintageHandler(next http.Handler) http.Handler {
func setUserLanguage(w http.ResponseWriter, r *http.Request) {
loc := r.FormValue("locale")
- _, ok := printers[strings.ToLower(loc)]
+ _, ok := i18n.Printers[loc]
if !ok {
+ /* TODO: Make this page pretty? */
w.WriteHeader(http.StatusUnprocessableEntity)
fmt.Fprintf(w, "Locale ā€˜%s’ is invalid or unsupported", loc)
return
@@ -182,11 +216,7 @@ func setUserLanguage(w http.ResponseWriter, r *http.Request) {
func throwError(status int, err error, w http.ResponseWriter, r *http.Request) {
w.WriteHeader(status)
- go func() {
- if err := email.ServerError(err); err != nil {
- log.Print(err)
- }
- }()
+ go email.Send("Server Error", err.Error())
errorTmpl.Execute(w, struct {
Code int
Msg string
@@ -195,3 +225,39 @@ func throwError(status int, err error, w http.ResponseWriter, r *http.Request) {
Msg: http.StatusText(status),
})
}
+
+func bestFitLanguage(qry string) i18n.Printer {
+ type option struct {
+ bcp string
+ quality float64
+ }
+ var xs []option
+
+ for subqry := range strings.SplitSeq(qry, ",") {
+ var o option
+ subqry = strings.TrimSpace(subqry)
+ parts := strings.Split(subqry, ";")
+ o.bcp = strings.ToLower(parts[0])
+ if len(parts) == 1 {
+ o.quality = 1
+ } else {
+ n, err := fmt.Sscanf(parts[1], "q=%f", &o.quality)
+ if n != 1 || err != nil {
+ /* Malformed query string; just give up */
+ return i18n.DefaultPrinter
+ }
+ }
+ xs = append(xs, o)
+ }
+
+ slices.SortFunc(xs, func(x, y option) int {
+ return cmp.Compare(y.quality, x.quality)
+ })
+
+ for _, x := range xs {
+ if p, ok := i18n.Printers[x.bcp]; ok {
+ return p
+ }
+ }
+ return i18n.DefaultPrinter
+}