๐พ Archived View for source.community โบ ckaznocha โบ gemini โบ blob โบ main โบ mux.go captured on 2024-05-10 at 11:02:27. Gemini links have been rewritten to link to archived content
โฌ ๏ธ Previous capture (2024-02-05)
-=-=-=-=-=-=-
. ,-. ,-. . . ,-. ,-. ,-. ,-. ,-. ,-,-. ,-,-. . . ,-. . |- . . `-. | | | | | | |-' | | | | | | | | | | | | | | | | | `-' `-' `-^ ' `-' `-' :: `-' `-' ' ' ' ' ' ' `-^ ' ' ' `' `-| /| `-'
git clone https://source.community/ckaznocha/gemini.git
View raw contents of /mux.go (main)
โโโโโฎ 1โ package gemini 2โ 3โ import ( 4โ "context" 5โ "strings" 6โ "sync" 7โ ) 8โ 9โ // ServeMux is a Gemini request multiplexer. It will match requests to handlers 10โ // based on the URI path. The longest match will be the one returned. Patterns 11โ // ending with `/` will be matched exactly. Patterns without a trailing `/` will 12โ // be treated as a prefix match. 13โ type ServeMux struct { 14โ nodeToPattern map[*muxNode]string 15โ nodes *muxNode 16โ mu sync.RWMutex 17โ } 18โ 19โ // NewServeMux returns a new ServeMux ready to be used. 20โ func NewServeMux() *ServeMux { 21โ return &ServeMux{ 22โ nodeToPattern: map[*muxNode]string{}, 23โ nodes: &muxNode{ 24โ handler: nil, 25โ nodes: map[string]*muxNode{}, 26โ }, 27โ } 28โ } 29โ 30โ // Handle adds a new pattern/Handler pair to the ServeMux. 31โ func (sm *ServeMux) Handle(pattern string, handler Handler) { 32โ sm.mu.Lock() 33โ defer sm.mu.Unlock() 34โ 35โ sm.nodeToPattern[sm.nodes.insert(pattern, handler)] = pattern 36โ } 37โ 38โ // HandleFunc adds a new pattern/HandleFunc pair to the ServeMux. 39โ func (sm *ServeMux) HandleFunc(pattern string, handler func(context.Context, ResponseWriter, *Request)) { 40โ sm.Handle(pattern, HandlerFunc(handler)) 41โ } 42โ 43โ // Handler looks up a matching Handler based on a Request. It returns the patter 44โ // that matched in addition to the Hander. 45โ func (sm *ServeMux) Handler(r *Request) (h Handler, pattern string) { 46โ sm.mu.RLock() 47โ defer sm.mu.RUnlock() 48โ 49โ if !strings.HasPrefix(r.URI.Path, "/") { 50โ r.URI.Path = "/" + r.URI.Path 51โ } 52โ 53โ n := sm.nodes.find(r.URI.Path) 54โ if n.handler == nil { 55โ return HandlerFunc(func(c context.Context, rw ResponseWriter, r *Request) { 56โ rw.Failure(c, StatusNotFound, StatusNotFound.Description()) 57โ }), "" 58โ } 59โ 60โ return n.handler, sm.nodeToPattern[n] 61โ } 62โ 63โ // ServeGemini implements the Handler interface. 64โ func (sm *ServeMux) ServeGemini(ctx context.Context, w ResponseWriter, r *Request) { 65โ handlr, _ := sm.Handler(r) 66โ handlr.ServeGemini(ctx, w, r) 67โ } 68โ 69โ type muxNode struct { 70โ handler Handler 71โ nodes map[string]*muxNode 72โ } 73โ 74โ func (mn *muxNode) insert(pattern string, handler Handler) *muxNode { 75โ if pattern == "" { 76โ mn.handler = handler 77โ 78โ return mn 79โ } 80โ 81โ idx := nextIndex(pattern) 82โ 83โ child, ok := mn.nodes[pattern[:idx]] 84โ if !ok { 85โ child = &muxNode{nodes: map[string]*muxNode{}} 86โ mn.nodes[pattern[:idx]] = child 87โ } 88โ 89โ return child.insert(pattern[idx:], handler) 90โ } 91โ 92โ func (mn *muxNode) find(pattern string) *muxNode { 93โ if child, ok := mn.nodes[pattern]; ok { 94โ return child 95โ } 96โ 97โ idx := nextIndex(pattern) 98โ 99โ if child, ok := mn.nodes[pattern[:idx]]; ok { 100โ return child.find(pattern[idx:]) 101โ } 102โ 103โ return mn 104โ } 105โ 106โ func nextIndex(pattern string) int { 107โ idx := strings.IndexRune(pattern[1:], '/') 108โ if idx == -1 { 109โ return len(pattern) 110โ } 111โ 112โ return idx + 1 113โ } โโโโโฏ
ยท ยท ยท
ยฉ 2024 source.community