115 lines
2.5 KiB
Go
115 lines
2.5 KiB
Go
|
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)
|
||
|
}
|