diff --git a/cmd/testapi/main.go b/cmd/testapi/main.go new file mode 100644 index 0000000..9416bc8 --- /dev/null +++ b/cmd/testapi/main.go @@ -0,0 +1,124 @@ +package main + +import ( + "context" + "flag" + "fmt" + "io" + "log" + "net/http" + "os" + "os/signal" + "strings" + "syscall" + "time" + + "golang.org/x/time/rate" +) + +func main() { + ctx, can := signal.NotifyContext(context.Background(), syscall.SIGINT) + defer can() + + if err := run(ctx); err != nil { + panic(err) + } +} + +func run(ctx context.Context) error { + fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + port := fs.Int("p", 8080, "port") + if err := fs.Parse(os.Args[1:]); err != nil { + return err + } + + S := &S{ + ctx: ctx, + limiter: rate.NewLimiter(10, 10), + } + + s := &http.Server{ + Addr: fmt.Sprintf(":%d", *port), + Handler: S, + } + + go func() { + <-ctx.Done() + ctx, can := context.WithTimeout(context.Background(), time.Second) + defer can() + s.Shutdown(ctx) + }() + + log.Println("listening on", *port) + if err := s.ListenAndServe(); err != nil && ctx.Err() == nil { + return err + } + log.Println("shut down") + return nil +} + +type S struct { + ctx context.Context + limiter *rate.Limiter +} + +func (s *S) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := s.serveHTTP(w, r); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +func (s *S) serveHTTP(w http.ResponseWriter, r *http.Request) error { + switch strings.Split(r.URL.Path[1:], "/")[0] { + case "ws", "v1": + return s.serveAPI(w, r) + } + return s.serveStatic(w, r) +} + +func (s *S) serveStatic(w http.ResponseWriter, r *http.Request) error { + return io.EOF +} + +func (s *S) serveAPI(w http.ResponseWriter, r *http.Request) error { + if err := s.injectContext(w, r); err == io.EOF { + http.Redirect(w, r, "/", http.StatusSeeOther) + return nil + } else if err != nil { + return err + } + + switch strings.Split(r.URL.Path[1:], "/")[0] { + case "ws": + return s.serveWS(w, r) + case "v1": + return s.serveV1(w, r) + } + http.NotFound(w, r) + return nil +} + +type Session struct { + ID string +} + +func (s *S) injectContext(w http.ResponseWriter, r *http.Request) error { + id, err := r.Cookie("uuid") + if err != nil || id.Value == "" { + return io.EOF + } + ctx := r.Context() + ctx = context.WithValue(ctx, "session", Session{ + ID: id.Value, + }) + *r = *r.WithContext(ctx) + return nil +} + +func (s *S) serveWS(w http.ResponseWriter, r *http.Request) error { + return io.EOF +} + +func (s *S) serveV1(w http.ResponseWriter, r *http.Request) error { + return io.EOF +} diff --git a/go.mod b/go.mod index 6d923f3..6ec80f4 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,5 @@ module gitea.inhome.blapointe.com/bel/out go 1.22.3 + +require golang.org/x/time v0.8.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d06eb41 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg= +golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=