184 lines
4.5 KiB
Go
184 lines
4.5 KiB
Go
package archive
|
|
|
|
import (
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
func (this *ArchiveServer) lookupSourceByNumericString(slug string) *LogSource {
|
|
intval, err := strconv.Atoi(slug)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
if intval >= 0 && intval < len(this.cfg.Logs) {
|
|
return &this.cfg.Logs[intval]
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (this *ArchiveServer) lookupSource(slug string) *LogSource {
|
|
if src := this.lookupSourceByNumericString(slug); src != nil {
|
|
return src
|
|
}
|
|
|
|
for i, ls := range this.cfg.Logs {
|
|
for _, s := range ls.Slugs {
|
|
if s == slug {
|
|
return &this.cfg.Logs[i]
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil // not found
|
|
}
|
|
|
|
func (this *ArchiveServer) bestSlugFor(ls *LogSource) (string, error) {
|
|
for i := 0; i < len(this.cfg.Logs); i += 1 {
|
|
if ls != &this.cfg.Logs[i] {
|
|
continue
|
|
}
|
|
|
|
if len(this.cfg.Logs[i].Slugs) > 0 {
|
|
return this.cfg.Logs[i].Slugs[0], nil // first slug is preferred
|
|
} else {
|
|
return fmt.Sprintf(`%d`, i), nil // no slugs present? use numeric log index
|
|
}
|
|
|
|
}
|
|
|
|
return "", errors.New("Unregistered log source")
|
|
}
|
|
|
|
func (this *ArchiveServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Server", SERVER_VERSION)
|
|
|
|
if r.Method != "GET" {
|
|
http.Error(w, "Expected GET", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
if len(r.URL.Path) == 0 {
|
|
http.Error(w, "Invalid request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Handle static assets
|
|
|
|
static, err := Asset(r.URL.Path[1:])
|
|
if err == nil {
|
|
http.ServeContent(w, r, r.URL.Path[1:], this.startup, bytes.NewReader(static))
|
|
return
|
|
}
|
|
|
|
// Handle application routes
|
|
|
|
arc := NewArchiveState(this)
|
|
|
|
if r.URL.Path == `/` {
|
|
ls := &this.cfg.Logs[0]
|
|
slug, _ := this.bestSlugFor(ls)
|
|
dt := ls.LatestDate()
|
|
http.Redirect(w, r, fmt.Sprintf(`/%s/%d/%d`, slug, dt.Year, dt.Month), http.StatusTemporaryRedirect)
|
|
|
|
} else if len(r.URL.Query().Get("y")) > 0 || len(r.URL.Query().Get("q")) > 0 || len(r.URL.Query().Get("h")) > 0 {
|
|
this.legacyRoute(w, r)
|
|
|
|
} else if r.URL.Path == `/download` {
|
|
arc.renderError(w, "Not implemented.") // FIXME
|
|
|
|
} else if matches := this.rxViewRoot.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
|
if ls := this.lookupSource(matches[1]); ls != nil {
|
|
arc.selectSource(ls, matches[1])
|
|
y, _ := strconv.Atoi(matches[2])
|
|
m, _ := strconv.Atoi(matches[3])
|
|
arc.ym = YearMonth{Year: y, Month: time.Month(m)} // 1-based months
|
|
arc.renderView(w)
|
|
|
|
} else {
|
|
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
|
|
}
|
|
|
|
} else if matches := this.rxViewPage.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
|
if ls := this.lookupSource(matches[1]); ls != nil {
|
|
arc.selectSource(ls, matches[1])
|
|
y, _ := strconv.Atoi(matches[2])
|
|
m, _ := strconv.Atoi(matches[3])
|
|
arc.ym = YearMonth{Year: y, Month: time.Month(m)} // 1-based months
|
|
arc.page, _ = strconv.Atoi(matches[4])
|
|
arc.renderView(w)
|
|
|
|
} else {
|
|
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
|
|
}
|
|
|
|
} else if matches := this.rxSearch.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
|
if ls := this.lookupSource(matches[1]); ls != nil {
|
|
arc.selectSource(ls, matches[1])
|
|
arc.query, _ = url.QueryUnescape(matches[2])
|
|
arc.queryIsRegex = false
|
|
arc.renderSearch(w)
|
|
|
|
} else {
|
|
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
|
|
}
|
|
|
|
} else if matches := this.rxSearchRx.FindStringSubmatch(r.URL.Path); len(matches) > 0 {
|
|
if ls := this.lookupSource(matches[1]); ls != nil {
|
|
arc.selectSource(ls, matches[1])
|
|
arc.query, _ = url.QueryUnescape(matches[2])
|
|
arc.queryIsRegex = true
|
|
arc.renderSearch(w)
|
|
|
|
} else {
|
|
arc.renderError(w, fmt.Sprintf("Unknown source '%s'", matches[1]))
|
|
}
|
|
} else {
|
|
arc.renderError(w, "Unknown route.")
|
|
|
|
}
|
|
}
|
|
|
|
func (this *ArchiveServer) legacyRoute(w http.ResponseWriter, r *http.Request) {
|
|
u := URLHelper{w, r}
|
|
|
|
hubid := 0
|
|
if u.hasGet("h") {
|
|
hubid = u.intval(u.get("h"))
|
|
}
|
|
|
|
//
|
|
|
|
if u.hasGet("q") {
|
|
if u.hasGet("rx") {
|
|
u.redirectf(`/%d/rx/%s`, hubid, url.QueryEscape(u.get("q")))
|
|
} else {
|
|
u.redirectf(`/%d/search/%s`, hubid, url.QueryEscape(u.get("q")))
|
|
}
|
|
|
|
} else if u.hasGet("y") && u.hasGet("m") {
|
|
year := u.intval(u.get("y"))
|
|
month := u.intval(u.get("m"))
|
|
if u.hasGet("p") {
|
|
u.redirectf(`/%d/%d/%d/page-%d`, hubid, year, month, u.intval(u.get("p")))
|
|
} else {
|
|
u.redirectf(`/%d/%d/%d`, hubid, year, month)
|
|
}
|
|
|
|
} else {
|
|
if hi := this.lookupSourceByNumericString(u.get("h")); hi != nil {
|
|
currentDate := hi.LatestDate()
|
|
u.redirectf(`/%d/%d/%d`, hubid, currentDate.Year, currentDate.Month)
|
|
} else {
|
|
u.redirectf(`/`)
|
|
}
|
|
|
|
}
|
|
}
|