From b738f78e6ea8bddfca989ad03d8b4394a649f03c Mon Sep 17 00:00:00 2001 From: Colin Henry Date: Fri, 6 Sep 2024 20:27:26 -0700 Subject: [PATCH] reomved now unnecessary libraries --- net/http/mux.go | 109 --------------- net/http/mux_test.go | 231 -------------------------------- net/http/params.go | 102 -------------- net/http/params_test.go | 287 ---------------------------------------- 4 files changed, 729 deletions(-) delete mode 100644 net/http/mux.go delete mode 100644 net/http/mux_test.go delete mode 100644 net/http/params.go delete mode 100644 net/http/params_test.go diff --git a/net/http/mux.go b/net/http/mux.go deleted file mode 100644 index a204c21..0000000 --- a/net/http/mux.go +++ /dev/null @@ -1,109 +0,0 @@ -// based on the "way" package by matt ryer -// Copyright (c) 2016 Mat Ryer - -package http - -import ( - "context" - "net/http" - "strings" -) - -// contextKey is the context key type for storing -// parameters in context.Context. -type contextKey string - -// Router routes HTTP requests. -type ServeMux struct { - routes []*route - // NotFound is the http.Handler to call when no routes - // match. By default uses http.NotFoundHandler(). - NotFound http.Handler -} - -// NewRouter makes a new Router. -func NewServeMux() *ServeMux { - return &ServeMux{ - NotFound: http.NotFoundHandler(), - } -} - -func (r *ServeMux) pathSegments(p string) []string { - return strings.Split(strings.Trim(p, "/"), "/") -} - -// Handle adds a handler with the specified pattern. -// Pattern can contain path segments such as: /item/:id which is -// accessible via the Param function. -// If pattern ends with trailing /, it acts as a prefix. -func (r *ServeMux) Handle(pattern string, handler http.Handler) { - route := &route{ - segs: r.pathSegments(pattern), - handler: handler, - prefix: strings.HasSuffix(pattern, "/") || strings.HasSuffix(pattern, "..."), - } - r.routes = append(r.routes, route) -} - -// HandleFunc is the http.HandlerFunc alternative to http.Handle. -func (r *ServeMux) HandleFunc(pattern string, fn http.HandlerFunc) { - r.Handle(pattern, fn) -} - -// ServeHTTP routes the incoming http.Request based on path -func (r *ServeMux) ServeHTTP(w http.ResponseWriter, req *http.Request) { - segs := r.pathSegments(req.URL.Path) - for _, route := range r.routes { - if ctx, ok := route.match(req.Context(), r, segs); ok { - route.handler.ServeHTTP(w, req.WithContext(ctx)) - return - } - } - r.NotFound.ServeHTTP(w, req) -} - -// Param gets the path parameter from the specified Context. -// Returns an empty string if the parameter was not found. -func Param(ctx context.Context, param string) string { - vStr, ok := ctx.Value(contextKey(param)).(string) - if !ok { - return "" - } - return vStr -} - -type route struct { - segs []string - handler http.Handler - prefix bool -} - -func (r *route) match(ctx context.Context, router *ServeMux, segs []string) (context.Context, bool) { - if len(segs) > len(r.segs) && !r.prefix { - return nil, false - } - for i, seg := range r.segs { - if i > len(segs)-1 { - return nil, false - } - isParam := false - if strings.HasPrefix(seg, "{") { - isParam = true - seg = strings.Trim(seg, "{}") - } - if !isParam { // verbatim check - if strings.HasSuffix(seg, "...") { - if strings.HasPrefix(segs[i], seg[:len(seg)-3]) { - return ctx, true - } - } - if seg != segs[i] { - return nil, false - } - } - if isParam { - ctx = context.WithValue(ctx, contextKey(seg), segs[i]) - } - } - return ctx, true -} diff --git a/net/http/mux_test.go b/net/http/mux_test.go deleted file mode 100644 index 9b78cae..0000000 --- a/net/http/mux_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package http - -import ( - "context" - "net/http" - "net/http/httptest" - "testing" -) - -var tests = []struct { - // RouteMethod string - RoutePattern string - - Method string - Path string - Match bool - Params map[string]string -}{ - // simple path matching - { - "/one", - "GET", "/one", true, nil, - }, - { - "/two", - "GET", "/two", true, nil, - }, - { - "/three", - "GET", "/three", true, nil, - }, - // methods - { - "/methodcase", - "GET", "/methodcase", true, nil, - }, - { - "/methodcase", - "get", "/methodcase", true, nil, - }, - { - "/methodcase", - "get", "/methodcase", true, nil, - }, - { - "/method1", - "POST", "/method1", true, nil, - }, - { - "/method2", - "GET", "/method2", true, nil, - }, - { - "/method3", - "PUT", "/method3", true, nil, - }, - // all methods - { - "/all-methods", - "GET", "/all-methods", true, nil, - }, - { - "/all-methods", - "POST", "/all-methods", true, nil, - }, - { - "/all-methods", - "PUT", "/all-methods", true, nil, - }, - // nested - { - "/parent/child/one", - "GET", "/parent/child/one", true, nil, - }, - { - "/parent/child/two", - "GET", "/parent/child/two", true, nil, - }, - { - "/parent/child/three", - "GET", "/parent/child/three", true, nil, - }, - // slashes - { - "slashes/one", - "GET", "/slashes/one", true, nil, - }, - { - "/slashes/two", - "GET", "slashes/two", true, nil, - }, - { - "slashes/three/", - "GET", "/slashes/three", true, nil, - }, - { - "/slashes/four", - "GET", "slashes/four/", true, nil, - }, - // prefix - { - "/prefix/", - "GET", "/prefix/anything/else", true, nil, - }, - { - "/not-prefix", - "GET", "/not-prefix/anything/else", false, nil, - }, - { - "/prefixdots...", - "GET", "/prefixdots/anything/else", true, nil, - }, - { - "/prefixdots...", - "GET", "/prefixdots", true, nil, - }, - // path params - { - "/path-param/{id}", - "GET", "/path-param/123", true, map[string]string{"id": "123"}, - }, - { - "/path-params/{era}/{group}/{member}", - "GET", "/path-params/60s/beatles/lennon", true, map[string]string{ - "era": "60s", - "group": "beatles", - "member": "lennon", - }, - }, - { - "/path-params-prefix/{era}/{group}/{member}/", - "GET", "/path-params-prefix/60s/beatles/lennon/yoko", true, map[string]string{ - "era": "60s", - "group": "beatles", - "member": "lennon", - }, - }, - // misc no matches - { - "/not/enough", - "GET", "/not/enough/items", false, nil, - }, - { - "/not/enough/items", - "GET", "/not/enough", false, nil, - }, -} - -func TestMux(t *testing.T) { - for _, test := range tests { - r := NewServeMux() - match := false - var ctx context.Context - r.Handle(test.RoutePattern, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - match = true - ctx = r.Context() - })) - req, err := http.NewRequest(test.Method, test.Path, nil) - if err != nil { - t.Errorf("NewRequest: %s", err) - } - w := httptest.NewRecorder() - r.ServeHTTP(w, req) - if match != test.Match { - t.Errorf("expected match %v but was %v: %s %s", test.Match, match, test.Method, test.Path) - } - if len(test.Params) > 0 { - for expK, expV := range test.Params { - // check using helper - actualValStr := Param(ctx, expK) - if actualValStr != expV { - t.Errorf("Param: context value %s expected \"%s\" but was \"%s\"", expK, expV, actualValStr) - } - } - } - } -} - -func TestMultipleRoutesDifferentMethods(t *testing.T) { - r := NewServeMux() - var match string - - r.Handle("/route", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - switch r.Method { - case http.MethodGet: - match = "GET /route" - case http.MethodDelete: - match = "DELETE /route" - case http.MethodPost: - match = "POST /route" - } - })) - - r.Handle("/route", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - match = "GET /route" - })) - r.Handle("/route", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - match = "DELETE /route" - })) - r.Handle("/route", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - match = "POST /route" - })) - - req, err := http.NewRequest(http.MethodGet, "/route", nil) - if err != nil { - t.Errorf("NewRequest: %s", err) - } - r.ServeHTTP(httptest.NewRecorder(), req) - if match != "GET /route" { - t.Errorf("unexpected: %s", match) - } - - req, err = http.NewRequest(http.MethodDelete, "/route", nil) - if err != nil { - t.Errorf("NewRequest: %s", err) - } - r.ServeHTTP(httptest.NewRecorder(), req) - if match != "DELETE /route" { - t.Errorf("unexpected: %s", match) - } - - req, err = http.NewRequest(http.MethodPost, "/route", nil) - if err != nil { - t.Errorf("NewRequest: %s", err) - } - r.ServeHTTP(httptest.NewRecorder(), req) - if match != "POST /route" { - t.Errorf("unexpected: %s", match) - } - -} diff --git a/net/http/params.go b/net/http/params.go deleted file mode 100644 index 3acbb72..0000000 --- a/net/http/params.go +++ /dev/null @@ -1,102 +0,0 @@ -package http - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "net/url" - "strconv" -) - -func PathParam(ctx context.Context, Param func(ctx context.Context, paramName string) string, p interface{}, paramName string, required bool) (err error) { - s := Param(ctx, paramName) - if s == "" && required { - switch v := p.(type) { - case *string: - p = v - p = nil - } - return errors.New("missing required parameter") - } - - switch v := p.(type) { - case *int64: - *v, err = strconv.ParseInt(s, 10, 64) - case *int32: - var x int64 - x, err = strconv.ParseInt(s, 10, 32) - *v = int32(x) - case *string: - *v = s - default: - err = fmt.Errorf("no match for pointer type %T", v) - } - - return -} - -func BodyParam(body io.ReadCloser, p any, v func(p any) error) (err error) { - d := json.NewDecoder(body) - if err = d.Decode(p); err == nil { - err = v(p) - } - return -} - -func mappedParam(m map[string][]string, paramName string, p interface{}, required bool) (err error) { - s, exists := m[paramName] - - if !exists && required { - return errors.New("missing required parameter") - } - - switch v := p.(type) { - case *int64: - *v, err = strconv.ParseInt(s[0], 10, 64) - case *int32: - var x int64 - x, err = strconv.ParseInt(s[0], 10, 32) - *v = int32(x) - case *bool: - *v, err = strconv.ParseBool(s[0]) - case *string: - *v = s[0] - case *[]int64: - for _, i := range s { - if e, err := strconv.ParseInt(i, 10, 64); err != nil { - return err - } else { - *v = append(*v, e) - } - } - case *[]int32: - for _, i := range s { - if e, err := strconv.ParseInt(i, 10, 32); err != nil { - return err - } else { - *v = append(*v, int32(e)) - } - } - case *[]string: - *v = s - default: - err = fmt.Errorf("no match for pointer type %T", v) - } - - return -} - -func QueryParam(query url.Values, paramName string, p interface{}, required bool) (err error) { - return mappedParam(query, paramName, p, required) -} - -func HeaderParam(h http.Header, paramName string, p interface{}, required bool) (err error) { - return mappedParam(h, paramName, p, required) -} - -func FormParam(form url.Values, paramName string, p interface{}, required bool) (err error) { - return mappedParam(form, paramName, p, required) -} diff --git a/net/http/params_test.go b/net/http/params_test.go deleted file mode 100644 index 78d0f59..0000000 --- a/net/http/params_test.go +++ /dev/null @@ -1,287 +0,0 @@ -package http - -import ( - "context" - "errors" - "io" - "net/url" - "reflect" - "strings" - "testing" -) - -func TestPathParam(t *testing.T) { - t.Run("test int64 parse", func(t *testing.T) { - var p int64 - err := PathParam(context.WithValue(context.Background(), contextKey("int64id"), "123"), Param, &p, "int64id", true) - if (err != nil) != false { - t.Errorf("PathParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, int64(123)) { - t.Errorf("PathParam() = %v, want %v", p, int64(123)) - } - }) - - t.Run("test int32 parse", func(t *testing.T) { - var p int32 - err := PathParam(context.WithValue(context.Background(), contextKey("int32id"), "123"), Param, &p, "int32id", true) - if (err != nil) != false { - t.Errorf("PathParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, int32(123)) { - t.Errorf("PathParam() = %v, want %v", p, int32(123)) - } - }) - - t.Run("test string parse", func(t *testing.T) { - var p string - err := PathParam( - context.WithValue( - context.Background(), - contextKey("stringid"), - "foo"), - Param, - &p, - "stringid", - true) - if (err != nil) != false { - t.Errorf("PathParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, "foo") { - t.Errorf("PathParam() = %v, want %v", p, "foo") - } - }) - - t.Run("test missing required parameter", func(t *testing.T) { - var p string - err := PathParam(context.Background(), Param, &p, "stringid", true) - if (err != nil) != true { - t.Errorf("PathParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, "") { - t.Errorf("PathParam() = %v, want %v", p, "") - } - }) - - t.Run("test unknown type parameter", func(t *testing.T) { - var p complex64 - err := PathParam(context.WithValue(context.Background(), contextKey("stringid"), "foo"), - Param, p, "stringid", true) - if (err != nil) != true { - t.Errorf("PathParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, complex64(0)) { - t.Errorf("PathParam() = %v, want %v", p, complex64(0)) - } - }) -} - -func toValues(s string) url.Values { - v, _ := url.ParseQuery(s) - return v -} - -func TestMappedParam(t *testing.T) { - t.Run("test int64 parse", func(t *testing.T) { - var p int64 - err := mappedParam(toValues("x=123"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, int64(123)) { - t.Errorf("QueryParam() = %v, want %v", p, int64(123)) - } - }) - - t.Run("test int32 parse", func(t *testing.T) { - var p int32 - err := mappedParam(toValues("x=123"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, int32(123)) { - t.Errorf("QueryParam() = %v, want %v", p, int32(123)) - } - }) - - t.Run("test bool parse", func(t *testing.T) { - var p bool - err := mappedParam(toValues("x=true"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, true) { - t.Errorf("QueryParam() = %v, want %v", p, true) - } - }) - - t.Run("test string parse", func(t *testing.T) { - var p string - err := mappedParam(toValues("x=foobar"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, "foobar") { - t.Errorf("QueryParam() = %v, want %v", p, "foobar") - } - }) - - t.Run("test []int64 parse", func(t *testing.T) { - var p []int64 - err := mappedParam(toValues("x=123&x=456"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, []int64{int64(123), int64(456)}) { - t.Errorf("QueryParam() = %v, want %v", p, []int64{int64(123), int64(456)}) - } - }) - - t.Run("test []int64 bad parse", func(t *testing.T) { - var p []int64 - err := mappedParam(toValues("x=123&x=4q56"), "x", &p, true) - if (err != nil) != true { - t.Errorf("QueryParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, []int64{123}) { - t.Errorf("QueryParam() = %v, want %v", p, []int64{}) - } - }) - - t.Run("test []int32 parse", func(t *testing.T) { - var p []int32 - err := mappedParam(toValues("x=123&x=456"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, []int32{int32(123), int32(456)}) { - t.Errorf("QueryParam() = %v, want %v", p, []int32{int32(123), int32(456)}) - } - }) - - t.Run("test []int32 bad parse", func(t *testing.T) { - var p []int32 - err := mappedParam(toValues("x=123&x=4q56"), "x", &p, true) - if (err != nil) != true { - t.Errorf("QueryParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, []int32{123}) { - t.Errorf("QueryParam() = %v, want %v", p, []int32{123}) - } - }) - - t.Run("test []string parse", func(t *testing.T) { - var p []string - err := mappedParam(toValues("x=foo&x=bar"), "x", &p, true) - if (err != nil) != false { - t.Errorf("QueryParam() error = %v, wantErr %v", err, false) - return - } - if !reflect.DeepEqual(p, []string{"foo", "bar"}) { - t.Errorf("QueryParam() = %v, want %v", p, []string{"foo", "bar"}) - } - }) - - t.Run("test missing required parameter", func(t *testing.T) { - var p string - err := mappedParam(toValues("y=hello"), "x", &p, true) - if (err != nil) != true { - t.Errorf("QueryParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, "") { - t.Errorf("QueryParam() = %v, want %v", p, "") - } - }) - - t.Run("test unknown type parameter", func(t *testing.T) { - var p complex64 - err := mappedParam(toValues("x=hello"), "x", &p, true) - if (err != nil) != true { - t.Errorf("QueryParam() error = %v, wantErr %v", err, true) - return - } - if !reflect.DeepEqual(p, complex64(0)) { - t.Errorf("QueryParam() = %v, want %v", p, complex64(0)) - } - }) -} - -func TestBodyParam(t *testing.T) { - type args struct { - body io.ReadCloser - p any - v func(p any) error - } - - type x struct{} - var y x - - tests := []struct { - name string - args args - wantErr bool - }{ - { - name: "test happy path", - args: args{ - body: io.NopCloser(strings.NewReader("{}")), - p: &y, - v: func(p any) error { - return nil - }, - }, - wantErr: false, - }, - { - name: "test bad json", - args: args{ - body: io.NopCloser(strings.NewReader("}")), - p: &y, - v: func(p any) error { - return nil - }, - }, - wantErr: true, - }, - { - name: "test validation failed", - args: args{ - body: io.NopCloser(strings.NewReader("{}")), - p: &y, - v: func(p any) error { - return errors.New("validation failed") - }, - }, - wantErr: true, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if err := BodyParam(tt.args.body, tt.args.p, tt.args.v); (err != nil) != tt.wantErr { - t.Errorf("BodyParam() error = %v, wantErr %v", err, tt.wantErr) - } - }) - } -} - -func Ptr[T any](v T) *T { - return &v -} - -func NilString() *string { - return nil -}