Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
f4316cc13a | ||
|
19860f713c | ||
|
31cb99467c | ||
|
8a1403a35d | ||
|
07db4cf999 |
28
container/set/interface.go
Normal file
28
container/set/interface.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package set
|
||||||
|
|
||||||
|
var x = struct{}{}
|
||||||
|
|
||||||
|
type Set map[any]struct{}
|
||||||
|
|
||||||
|
func (s *Set) Init() {
|
||||||
|
for k := range *s {
|
||||||
|
delete(*s, k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) Add(e any) {
|
||||||
|
(*s)[e] = x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) Remove(e any) {
|
||||||
|
delete(*s, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Set) Contains(e any) bool {
|
||||||
|
_, c := (*s)[e]
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func New() *Set {
|
||||||
|
return new(Set)
|
||||||
|
}
|
@@ -9,7 +9,7 @@ type Func func(db *sql.DB)
|
|||||||
|
|
||||||
type Actor struct {
|
type Actor struct {
|
||||||
DB *sql.DB
|
DB *sql.DB
|
||||||
ActionChan <-chan Func
|
ActionChan chan Func
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *Actor) Run(ctx context.Context) error {
|
func (a *Actor) Run(ctx context.Context) error {
|
||||||
|
2
go.mod
2
go.mod
@@ -1,3 +1,3 @@
|
|||||||
module github.com/jchenry/x
|
module github.com/jchenry/x
|
||||||
|
|
||||||
go 1.13
|
go 1.18
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
package log
|
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 {
|
type Logger interface {
|
||||||
Print(v ...interface{})
|
Print(v ...interface{})
|
||||||
Printf(format string, v ...interface{})
|
Printf(format string, v ...interface{})
|
||||||
|
@@ -20,7 +20,7 @@ func BasicAuth(h http.Handler, htpasswd map[string]string, realm string) http.Ha
|
|||||||
user, pass, _ := r.BasicAuth()
|
user, pass, _ := r.BasicAuth()
|
||||||
if pw, ok := htpasswd[user]; !ok || !strings.EqualFold(pass, sha1(pw)) {
|
if pw, ok := htpasswd[user]; !ok || !strings.EqualFold(pass, sha1(pw)) {
|
||||||
w.Header().Set("WWW-Authenticate", rlm)
|
w.Header().Set("WWW-Authenticate", rlm)
|
||||||
http.Error(w, "Unauthorized.", 401)
|
http.Error(w, "Unauthorized", 401)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
|
@@ -30,7 +30,7 @@ func MutliHandler(h map[string]http.Handler) (http.HandlerFunc, error) {
|
|||||||
if hdlr, ok := h[r.Method]; ok {
|
if hdlr, ok := h[r.Method]; ok {
|
||||||
hdlr.ServeHTTP(w, r)
|
hdlr.ServeHTTP(w, r)
|
||||||
} else {
|
} else {
|
||||||
NotFoundHandler.ServeHTTP(w, r)
|
NotImplementedHandler.ServeHTTP(w, r)
|
||||||
}
|
}
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
95
net/http/mux.go
Normal file
95
net/http/mux.go
Normal 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 == ""
|
||||||
|
}
|
@@ -11,7 +11,7 @@ type StatusHandler int
|
|||||||
func (s StatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
func (s StatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||||
code := int(s)
|
code := int(s)
|
||||||
w.WriteHeader(code)
|
w.WriteHeader(code)
|
||||||
io.WriteString(w, http.StatusText(code))
|
_, _ = io.WriteString(w, http.StatusText(code))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
Reference in New Issue
Block a user