out/cmd/server/server.go

106 lines
2.1 KiB
Go

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")
}