Compare commits

..

4 Commits
v2.6.0 ... main

Author SHA1 Message Date
xuu
9ec281edea
vulncheck
Some checks failed
Go Bump / bump (push) Successful in 40s
Go Test / test (push) Failing after 52s
2024-04-06 18:39:35 -06:00
xuu
0afc7a5bed
fix: remove sigkill
Some checks failed
Go Test / test (push) Failing after 29s
Go Bump / bump (push) Successful in 31s
2024-02-29 11:02:00 -07:00
xuu
54fe38821c
feat: handle file upload
Some checks failed
Go Test / test (push) Failing after 45s
Go Bump / bump (push) Successful in 23s
2024-02-13 09:27:26 -07:00
xuu
f9c064e948
refactor: move into package
Some checks failed
Go Test / test (push) Failing after 32s
Go Bump / bump (push) Successful in 34s
2024-01-22 16:05:13 -07:00
9 changed files with 172 additions and 120 deletions

View File

@ -23,7 +23,7 @@ type info struct{}
func (info) RegisterHTTP(mux *http.ServeMux) { func (info) RegisterHTTP(mux *http.ServeMux) {
mux.HandleFunc("/app-info", func(w http.ResponseWriter, r *http.Request) { mux.HandleFunc("/app-info", func(w http.ResponseWriter, r *http.Request) {
name, version := service.AppName() name, version := service.AppName()
fmt.Fprint(w, name, version) fmt.Fprint(w, name, '@', version)
}) })
} }

View File

@ -2,19 +2,12 @@ package main
import ( import (
"context" "context"
"crypto/rand"
"errors"
"fmt"
"log"
"net/http"
"strconv" "strconv"
"strings"
"go.sour.is/pkg/env" "go.sour.is/pkg/env"
"go.sour.is/pkg/lg" "go.sour.is/pkg/lg"
"go.sour.is/pkg/service" "go.sour.is/pkg/service"
"go.sour.is/paste/v2/assets"
"go.sour.is/paste/v2/paste" "go.sour.is/paste/v2/paste"
) )
@ -28,104 +21,12 @@ var _ = apps.Register(50, func(ctx context.Context, svc *service.Harness) error
return err return err
} }
p, err := paste.New(store) srv, err := paste.NewService(store, randBytes)
if err != nil { if err != nil {
return err return err
} }
svc.Add(&pasteSRV{ svc.Add(srv)
ui: http.FileServer(http.FS(assets.GetUI())),
paste: p,
randBytes: int(randBytes),
})
return nil return nil
}) })
type pasteSRV struct {
ui http.Handler
paste *paste.Paste
randBytes int
}
func (a *pasteSRV) 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 *pasteSRV) 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 *pasteSRV) 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 *pasteSRV) 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, paste.ErrGone):
w.WriteHeader(http.StatusGone)
case errors.Is(err, paste.ErrNotFound):
w.WriteHeader(http.StatusNotFound)
case errors.Is(err, paste.ErrReadingContent):
w.WriteHeader(http.StatusInternalServerError)
}
fmt.Fprintf(w, "ERR %s", err)
return
}
}
func (p *pasteSRV) 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)
}

12
go.mod
View File

@ -3,7 +3,7 @@ module go.sour.is/paste/v2
go 1.21 go 1.21
require ( require (
github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167 github.com/gomarkdown/markdown v0.0.0-20230922105210-14b16010c2ee
github.com/h2non/filetype v1.1.0 github.com/h2non/filetype v1.1.0
github.com/matryer/is v1.4.1 github.com/matryer/is v1.4.1
github.com/rs/cors v1.6.0 github.com/rs/cors v1.6.0
@ -11,7 +11,7 @@ require (
go.opentelemetry.io/otel/trace v1.18.0 go.opentelemetry.io/otel/trace v1.18.0
go.sour.is/paste v0.0.0-20231022150928-96338f2f4441 go.sour.is/paste v0.0.0-20231022150928-96338f2f4441
go.sour.is/pkg v0.0.6 go.sour.is/pkg v0.0.6
golang.org/x/sys v0.13.0 golang.org/x/sys v0.18.0
sour.is/x/toolbox v0.12.17 sour.is/x/toolbox v0.12.17
) )
@ -53,13 +53,13 @@ require (
go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect go.opentelemetry.io/otel/sdk/metric v0.41.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.23.0 // indirect
golang.org/x/sync v0.3.0 // indirect golang.org/x/sync v0.3.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.14.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
google.golang.org/grpc v1.58.0 // indirect google.golang.org/grpc v1.58.3 // indirect
google.golang.org/protobuf v1.31.0 // indirect google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/ini.v1 v1.57.0 // indirect gopkg.in/ini.v1 v1.57.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

12
go.sum
View File

@ -94,6 +94,8 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167 h1:LP/6EfrZ/LyCc+SXvANDrIJ4sP9u2NAtqyv6QknetNQ= github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167 h1:LP/6EfrZ/LyCc+SXvANDrIJ4sP9u2NAtqyv6QknetNQ=
github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU= github.com/gomarkdown/markdown v0.0.0-20200824053859-8c8b3816f167/go.mod h1:aii0r/K0ZnHv7G0KF7xy1v0A7s2Ljrb5byB7MO5p6TU=
github.com/gomarkdown/markdown v0.0.0-20230922105210-14b16010c2ee h1:gvsnG+uIVkOue7HrYAG2ZnOdLoJTqsLyuBFJaU0kX4M=
github.com/gomarkdown/markdown v0.0.0-20230922105210-14b16010c2ee/go.mod h1:JDGcbDT52eL4fju3sZ4TeHGsQwhG9nbDV21aMyhwPoA=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -358,6 +360,8 @@ golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -385,11 +389,15 @@ golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@ -443,10 +451,14 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o= google.golang.org/grpc v1.58.0 h1:32JY8YpPMSR45K+c3o6b8VL73V+rR8k+DeMIr4vRH8o=
google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc v1.58.0/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -29,8 +29,8 @@ type image struct {
store string store string
maxSize int64 maxSize int64
m_image_get metric.Int64Counter m_image_get metric.Int64Counter
m_image_post metric.Int64Counter m_image_post metric.Int64Counter
m_image_error metric.Int64Counter m_image_error metric.Int64Counter
} }
@ -68,7 +68,6 @@ func New(ctx context.Context, store string, maxSize int64) (a *image, err error)
) )
err = errors.Join(err, merr) err = errors.Join(err, merr)
return a, err return a, err
} }
func (a *image) RegisterHTTP(mux *http.ServeMux) { func (a *image) RegisterHTTP(mux *http.ServeMux) {
@ -119,6 +118,9 @@ func (a *image) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var err error var err error
defer r.Body.Close() defer r.Body.Close()
// var buf bytes.Buffer
// r.Body = io.NopCloser(io.TeeReader(r.Body, &buf))
var fd io.ReadCloser = r.Body var fd io.ReadCloser = r.Body
if r.URL.Path == "/3/upload" { if r.URL.Path == "/3/upload" {
span.AddEvent("Imgur Emulation") span.AddEvent("Imgur Emulation")
@ -128,15 +130,19 @@ func (a *image) ServeHTTP(w http.ResponseWriter, r *http.Request) {
rdr = base64.NewDecoder(base64.StdEncoding, rdr) rdr = base64.NewDecoder(base64.StdEncoding, rdr)
} }
fd = io.NopCloser(rdr) fd = io.NopCloser(rdr)
} else if fd, _, err = r.FormFile("image"); err != nil { } else if mp, hd, err := r.FormFile("image"); err == nil {
if err != nil { defer mp.Close()
span.RecordError(err) span.AddEvent(fmt.Sprint(hd))
w.WriteHeader(http.StatusBadRequest) fd = mp
return } else if mp, hd, err := r.FormFile("file"); err == nil {
} defer mp.Close()
defer fd.Close() span.AddEvent(fmt.Sprint(hd))
fd = mp
} else if err != nil {
span.RecordError(err)
w.WriteHeader(http.StatusBadRequest)
return
} }
w.WriteHeader(http.StatusOK)
} else { } else {
w.WriteHeader(http.StatusCreated) w.WriteHeader(http.StatusCreated)
} }

View File

@ -18,7 +18,7 @@ var apps service.Apps
var appName, version = service.AppName() var appName, version = service.AppName()
func main() { func main() {
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill) ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
go func() { go func() {
<-ctx.Done() <-ctx.Done()
defer cancel() // restore interrupt function defer cancel() // restore interrupt function

19
paste/public/index.html Normal file
View File

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<link rel="manifest" href="/ui/manifest.json">
<link rel="shortcut icon" href="/ui/favicon.ico">
<title>DN42 Paste</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link href="paste.css" rel="stylesheet">
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
</body>
</html>

0
paste/public/paste.css Normal file
View File

114
paste/service.go Normal file
View File

@ -0,0 +1,114 @@
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)
}