From 68f8e931e746d8c01b7e82f273169ca1ee8797b3 Mon Sep 17 00:00:00 2001 From: Bel LaPointe <153096461+breel-render@users.noreply.github.com> Date: Sat, 14 Dec 2024 20:03:09 -0700 Subject: [PATCH] breakout server/main.go --- cmd/server/config.go | 22 +++++++++ cmd/server/main.go | 101 +++-------------------------------------- cmd/server/server.go | 105 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 132 insertions(+), 96 deletions(-) create mode 100644 cmd/server/config.go create mode 100644 cmd/server/server.go diff --git a/cmd/server/config.go b/cmd/server/config.go new file mode 100644 index 0000000..1c6c5dc --- /dev/null +++ b/cmd/server/config.go @@ -0,0 +1,22 @@ +package main + +import ( + "flag" + "os" +) + +type Config struct { + Port int + Root string +} + +func NewConfig() (Config, error) { + var c Config + fs := flag.NewFlagSet(os.Args[0], flag.ContinueOnError) + + fs.IntVar(&c.Port, "p", 8080, "port") + fs.StringVar(&c.Root, "r", "/tmp/", "static file root") + + err := fs.Parse(os.Args[1:]) + return c, err +} diff --git a/cmd/server/main.go b/cmd/server/main.go index 3bb5cc7..36fafa2 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -2,18 +2,13 @@ package main import ( "context" - "flag" "fmt" - "io" "log" "net/http" - "os" "os/signal" - "strings" "syscall" "time" - "github.com/coder/websocket" "golang.org/x/time/rate" ) @@ -27,19 +22,19 @@ func main() { } 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 { + config, err := NewConfig() + if err != nil { return err } S := &S{ ctx: ctx, limiter: rate.NewLimiter(10, 10), + config: config, } s := &http.Server{ - Addr: fmt.Sprintf(":%d", *port), + Addr: fmt.Sprintf(":%d", config.Port), Handler: S, } @@ -50,96 +45,10 @@ func run(ctx context.Context) error { s.Shutdown(ctx) }() - log.Println("listening on", *port) + log.Println("listening on", config.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 { - log.Println(r.URL.Path, "//", err.Error(), r.Header) - http.Error(w, err.Error(), http.StatusInternalServerError) - } -} - -func (s *S) serveHTTP(w http.ResponseWriter, r *http.Request) error { - if isV1(r) || isWS(r) { - return s.serveAPI(w, r) - } - return s.serveStatic(w, r) -} - -func isV1(r *http.Request) bool { - return strings.HasPrefix(r.URL.Path, "/v1/") -} - -func isWS(r *http.Request) bool { - return r.URL.Path == "/ws" || strings.HasPrefix(r.URL.Path, "/ws/") -} - -func (s *S) serveStatic(w http.ResponseWriter, r *http.Request) error { - return fmt.Errorf("not impl static") -} - -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 - } - - if isWS(r) { - return s.serveWS(w, r) - } else if isV1(r) { - 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(httpw http.ResponseWriter, httpr *http.Request) error { - ctx := httpr.Context() - - c, err := websocket.Accept(httpw, httpr, nil) - if err != nil { - return err - } - defer c.CloseNow() - - if err := c.Write(ctx, 1, []byte("hello world")); err != nil { - return err - } - - return fmt.Errorf("not impl") -} - -func (s *S) serveV1(w http.ResponseWriter, r *http.Request) error { - return fmt.Errorf("not impl: v1") -} diff --git a/cmd/server/server.go b/cmd/server/server.go new file mode 100644 index 0000000..ff93358 --- /dev/null +++ b/cmd/server/server.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "fmt" + "io" + "log" + "net/http" + "strings" + + "github.com/coder/websocket" + "golang.org/x/time/rate" +) + +type S struct { + ctx context.Context + limiter *rate.Limiter + config Config +} + +func (s *S) ServeHTTP(w http.ResponseWriter, r *http.Request) { + if err := s.serveHTTP(w, r); err != nil { + log.Println(s.Session(r.Context()), "//", r.URL.Path, "//", err.Error()) + http.Error(w, err.Error(), http.StatusInternalServerError) + } +} + +func (s *S) serveHTTP(w http.ResponseWriter, r *http.Request) error { + if isV1(r) || isWS(r) { + return s.serveAPI(w, r) + } + return s.serveStatic(w, r) +} + +func isV1(r *http.Request) bool { + return strings.HasPrefix(r.URL.Path, "/v1/") +} + +func isWS(r *http.Request) bool { + return r.URL.Path == "/ws" || strings.HasPrefix(r.URL.Path, "/ws/") +} + +func (s *S) serveStatic(w http.ResponseWriter, r *http.Request) error { + return fmt.Errorf("not impl static") +} + +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 + } + + if isWS(r) { + return s.serveWS(w, r) + } else if isV1(r) { + 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) Session(ctx context.Context) Session { + v, _ := ctx.Value("session").(Session) + return v +} + +func (s *S) serveWS(httpw http.ResponseWriter, httpr *http.Request) error { + ctx := httpr.Context() + + c, err := websocket.Accept(httpw, httpr, nil) + if err != nil { + return err + } + defer c.CloseNow() + + if err := c.Write(ctx, 1, []byte("hello world")); err != nil { + return err + } + + return fmt.Errorf("not impl") +} + +func (s *S) serveV1(w http.ResponseWriter, r *http.Request) error { + return fmt.Errorf("not impl: v1") +}