package paste import ( "crypto/rand" "errors" "fmt" "log" "net/http" "strings" "go.sour.is/paste/v2/assets" "go.sour.is/pkg/lg" ) type service struct { ui http.Handler paste *Paste randBytes int } func NewService(store string, randBytes int64) (*service, error) { p, err := New(store) if err != nil { return nil, err } return &service{ ui: http.FileServer(http.FS(assets.GetUI())), paste: p, randBytes: int(randBytes), }, nil } func (a *service) RegisterHTTP(mux *http.ServeMux) { mux.Handle("/ui/", lg.Htrace(http.StripPrefix("/ui/", a.ui), "paste-assets")) mux.Handle("/api", http.StripPrefix("/api", a)) mux.Handle("/api/", http.StripPrefix("/api/", a)) mux.Handle("/paste", http.StripPrefix("/paste", a)) mux.Handle("/paste/", http.StripPrefix("/paste/", a)) } func (p *service) ServeHTTP(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodGet: switch { case strings.HasPrefix(r.URL.Path, "rng"): p.getRandom(w) case strings.HasPrefix(r.URL.Path, "get"), r.URL.Path != "": p.getPaste(w, strings.TrimPrefix(r.URL.Path, "get/")) default: http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } case http.MethodPost: switch { case r.URL.Path == "": p.postPaste(w, r) default: http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) } default: http.Error(w, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed) } } func (p *service) getRandom(w http.ResponseWriter) { log.Println("get random") s := make([]byte, p.randBytes) _, _ = rand.Read(s) w.Header().Set("content-type", "application/octet-stream") w.WriteHeader(http.StatusOK) _, _ = w.Write(s) } func (p *service) getPaste(w http.ResponseWriter, id string) { log.Println("get paste", id) w.Header().Set("content-type", "application/octet-stream") err := p.paste.Get(w, id) if err != nil { switch { case errors.Is(err, ErrGone): w.WriteHeader(http.StatusGone) case errors.Is(err, ErrNotFound): w.WriteHeader(http.StatusNotFound) case errors.Is(err, ErrReadingContent): w.WriteHeader(http.StatusInternalServerError) } fmt.Fprintf(w, "ERR %s", err) return } } func (p *service) postPaste(w http.ResponseWriter, r *http.Request) { w.Header().Set("content-type", "application/octet-stream") id, err := p.paste.Set(r.Body) if err != nil { fmt.Fprintf(w, "ERR %s", err) return } log.Println("post paste", id) fmt.Fprint(w, "OK ", id) }