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 this.rxViewPage.MatchString(r.URL.Path) { arc.renderError(w, "Not implemented.") // FIXME } else if this.rxSearch.MatchString(r.URL.Path) { arc.renderError(w, "Not implemented.") // FIXME } else if this.rxSearchRx.MatchString(r.URL.Path) { arc.renderError(w, "Not implemented.") // FIXME } else { arc.renderError(w, "Unknown route.") } } func (this *ArchiveServer) legacyRoute(w http.ResponseWriter, r *http.Request) { intval := func(sz string) int { ret, _ := strconv.Atoi(sz) return ret } get := r.URL.Query().Get hasGet := func(sz string) bool { return len(get(sz)) > 0 } redirectf := func(format string, a ...interface{}) { http.Redirect(w, r, fmt.Sprintf(format, a...), http.StatusTemporaryRedirect) } // hubid := 0 if hasGet("h") { hubid = intval(get("h")) } if hasGet("q") { if hasGet("rx") { redirectf(`/%d/rx/%s`, hubid, url.QueryEscape(get("q"))) } else { redirectf(`/%d/search/%s`, hubid, url.QueryEscape(get("q"))) } } else if hasGet("y") && hasGet("m") { year := intval(get("y")) month := intval(get("m")) if hasGet("p") { redirectf(`/%d/%d/%d/page-%d`, hubid, year, month, intval(get("p"))) } else { redirectf(`/%d/%d/%d`, hubid, year, month) } } else { if hi := this.lookupSourceByNumericString(get("h")); hi != nil { currentDate := hi.LatestDate() redirectf(`/%d/%d/%d`, hubid, currentDate.Year, currentDate.Month) } else { redirectf(`/`) } } }