๐Ÿ’พ Archived View for source.community โ€บ ckaznocha โ€บ gemini โ€บ blob โ€บ main โ€บ mux.go captured on 2024-02-05 at 09:52:45. Gemini links have been rewritten to link to archived content

View Raw

More Information

โฌ…๏ธ Previous capture (2023-01-29)

๐Ÿšง View Differences

-=-=-=-=-=-=-

                                                         .
,-. ,-. . . ,-. ,-. ,-.    ,-. ,-. ,-,-. ,-,-. . . ,-. . |- . .
`-. | | | | |   |   |-'    |   | | | | | | | | | | | | | |  | |
`-' `-' `-^ '   `-' `-' :: `-' `-' ' ' ' ' ' ' `-^ ' ' ' `' `-|
                                                             /|
                                                            `-'

Profile for ckaznocha

ckaznocha / gemini

git clone https://source.community/ckaznocha/gemini.git

Branches

Log

Tree

/mux.go (main)

โ†‘ /

blob

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โ”‚ }
โ”€โ”€โ”€โ”€โ•ฏ

ยท ยท ยท

๐Ÿก Home

FAQs

Privacy Policy

Terms & Conditions

Official Gemlog

info@source.community

ยฉ 2024 source.community