4 Commits
v0.1.0 ... mux

Author SHA1 Message Date
Colin Henry
19860f713c WIP: http mux based on match by ben hoyt 2022-03-28 19:34:11 -07:00
Colin Henry
31cb99467c fix incorrect return code 2020-12-10 09:25:23 -08:00
Colin Henry
8a1403a35d nitpicks. 2020-10-23 21:55:48 -07:00
Colin Henry
07db4cf999 dont make it directional 2020-09-04 20:24:37 -07:00
7 changed files with 101 additions and 6 deletions

View File

@@ -9,7 +9,7 @@ type Func func(db *sql.DB)
type Actor struct {
DB *sql.DB
ActionChan <-chan Func
ActionChan chan Func
}
func (a *Actor) Run(ctx context.Context) error {

2
go.mod
View File

@@ -1,3 +1,3 @@
module github.com/jchenry/x
go 1.13
go 1.18

View File

@@ -1,6 +1,6 @@
package log
// Logger is a loggin interface with only the essentials that a function that needs to log should care about. Compatible with standard Go logger.
// Logger is a logging interface with only the essentials that a function that needs to log should care about. Compatible with standard Go logger.
type Logger interface {
Print(v ...interface{})
Printf(format string, v ...interface{})

View File

@@ -20,7 +20,7 @@ func BasicAuth(h http.Handler, htpasswd map[string]string, realm string) http.Ha
user, pass, _ := r.BasicAuth()
if pw, ok := htpasswd[user]; !ok || !strings.EqualFold(pass, sha1(pw)) {
w.Header().Set("WWW-Authenticate", rlm)
http.Error(w, "Unauthorized.", 401)
http.Error(w, "Unauthorized", 401)
return
}
h.ServeHTTP(w, r)

View File

@@ -30,7 +30,7 @@ func MutliHandler(h map[string]http.Handler) (http.HandlerFunc, error) {
if hdlr, ok := h[r.Method]; ok {
hdlr.ServeHTTP(w, r)
} else {
NotFoundHandler.ServeHTTP(w, r)
NotImplementedHandler.ServeHTTP(w, r)
}
}, nil
}

95
net/http/mux.go Normal file
View File

@@ -0,0 +1,95 @@
package http
import (
"net/http"
"strconv"
"strings"
)
type ServeMux struct {
routes []route
}
func (mux *ServeMux) Handle(pattern string, handler http.Handler, pathParams ...any) {
mux.routes = append(mux.routes, newRoute(pattern, handler, pathParams...))
}
func (mux *ServeMux) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request), pathParams ...any) {
mux.routes = append(mux.routes, newRoute(pattern, http.HandlerFunc(handler), pathParams...))
}
func (mux *ServeMux) Handler(r *http.Request) (h http.Handler, pattern string) {
for _, rte := range mux.routes {
switch {
case rte.matcher(r):
return rte.handler, rte.pattern
}
}
return http.HandlerFunc(http.NotFound), ""
}
func (mux *ServeMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.RequestURI == "*" {
if r.ProtoAtLeast(1, 1) {
w.Header().Set("Connection", "close")
}
w.WriteHeader(http.StatusBadRequest)
return
}
h, _ := mux.Handler(r)
h.ServeHTTP(w, r)
}
type route struct {
pattern string
matcher func(r *http.Request) bool
handler http.HandlerFunc
}
func newRoute(pattern string, handler http.Handler, vars ...interface{}) route {
return route{
pattern,
func(r *http.Request) bool {
return match(r.URL.Path, pattern, vars...)
},
handler.ServeHTTP,
}
}
// match reports whether path matches the given pattern, which is a
// path with '+' wildcards wherever you want to use a parameter. Path
// parameters are assigned to the pointers in vars (len(vars) must be
// the number of wildcards), which must be of type *string or *int.
func match(path, pattern string, vars ...interface{}) bool {
for ; pattern != "" && path != ""; pattern = pattern[1:] {
switch pattern[0] {
case '+':
// '+' matches till next slash in path
slash := strings.IndexByte(path, '/')
if slash < 0 {
slash = len(path)
}
segment := path[:slash]
path = path[slash:]
switch p := vars[0].(type) {
case *string:
*p = segment
case *int:
n, err := strconv.Atoi(segment)
if err != nil || n < 0 {
return false
}
*p = n
default:
panic("vars must be *string or *int")
}
vars = vars[1:]
case path[0]:
// non-'+' pattern byte must match path byte
path = path[1:]
default:
return false
}
}
return path == "" && pattern == ""
}

View File

@@ -11,7 +11,7 @@ type StatusHandler int
func (s StatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
code := int(s)
w.WriteHeader(code)
io.WriteString(w, http.StatusText(code))
_, _ = io.WriteString(w, http.StatusText(code))
}
var (