Index page and post pages ready
This commit is contained in:
76
vendor/github.com/a-h/gemini/mux/mux.go
generated
vendored
Normal file
76
vendor/github.com/a-h/gemini/mux/mux.go
generated
vendored
Normal file
@@ -0,0 +1,76 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/a-h/gemini"
|
||||
)
|
||||
|
||||
// Mux routes Gemini requests to the appropriate handler.
|
||||
type Mux struct {
|
||||
RouteHandlers []*RouteHandler
|
||||
NotFoundHandler gemini.Handler
|
||||
}
|
||||
|
||||
// NewMux creates a new Mux for routing requests.
|
||||
func NewMux() *Mux {
|
||||
return &Mux{
|
||||
RouteHandlers: make([]*RouteHandler, 0),
|
||||
NotFoundHandler: gemini.NotFoundHandler(),
|
||||
}
|
||||
}
|
||||
|
||||
// AddRoute to the mux.
|
||||
func (m *Mux) AddRoute(pattern string, handler gemini.Handler) {
|
||||
rh := &RouteHandler{
|
||||
Route: NewRoute(pattern),
|
||||
Handler: handler,
|
||||
}
|
||||
m.RouteHandlers = append(m.RouteHandlers, rh)
|
||||
}
|
||||
|
||||
// RouteHandler is the Handler to use for a given Route.
|
||||
type RouteHandler struct {
|
||||
Route *Route
|
||||
Handler gemini.Handler
|
||||
}
|
||||
|
||||
// contextKey used to store the route handler in the request context.
|
||||
type contextKey string
|
||||
|
||||
// matchedRouteContextKey is the key stored in the context.
|
||||
const matchedRouteContextKey = contextKey("matchedRoute")
|
||||
|
||||
// MatchedRoute is provided in the context to Gemini handlers that use the router.
|
||||
type MatchedRoute struct {
|
||||
Pattern string
|
||||
PathVars map[string]string
|
||||
}
|
||||
|
||||
func (m *Mux) ServeGemini(w gemini.ResponseWriter, r *gemini.Request) {
|
||||
s := r.URL.Path
|
||||
s = strings.TrimSuffix(s, "/")
|
||||
s = strings.TrimPrefix(s, "/")
|
||||
segments := strings.Split(s, "/")
|
||||
|
||||
for _, rh := range m.RouteHandlers {
|
||||
v, ok := rh.Route.Match(segments)
|
||||
if ok {
|
||||
mr := MatchedRoute{
|
||||
Pattern: rh.Route.Pattern,
|
||||
PathVars: v,
|
||||
}
|
||||
r.Context = context.WithValue(r.Context, matchedRouteContextKey, mr)
|
||||
rh.Handler.ServeGemini(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
m.NotFoundHandler.ServeGemini(w, r)
|
||||
}
|
||||
|
||||
// GetMatchedRoute returns the route that was matched by the router, along with any path variables extracted from the URL.
|
||||
func GetMatchedRoute(ctx context.Context) (mr MatchedRoute, ok bool) {
|
||||
mr, ok = ctx.Value(matchedRouteContextKey).(MatchedRoute)
|
||||
return mr, ok
|
||||
}
|
||||
69
vendor/github.com/a-h/gemini/mux/route.go
generated
vendored
Normal file
69
vendor/github.com/a-h/gemini/mux/route.go
generated
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Route is an array of segments.
|
||||
type Route struct {
|
||||
Pattern string
|
||||
Segments []*Segment
|
||||
}
|
||||
|
||||
// NewRoute creates a route based on a pattern, e.g /users/{userid}.
|
||||
func NewRoute(pattern string) *Route {
|
||||
var r Route
|
||||
r.Pattern = pattern
|
||||
|
||||
pattern = strings.TrimSuffix(pattern, "/")
|
||||
pattern = strings.TrimPrefix(pattern, "/")
|
||||
|
||||
for _, seg := range strings.Split(pattern, "/") {
|
||||
ps := &Segment{
|
||||
Name: seg,
|
||||
}
|
||||
if seg == "*" {
|
||||
ps.IsWildcard = true
|
||||
}
|
||||
if strings.HasPrefix(seg, "{") && strings.HasSuffix(seg, "}") {
|
||||
ps.IsVariable = true
|
||||
ps.Name = strings.TrimSuffix(strings.TrimPrefix(seg, "{"), "}")
|
||||
}
|
||||
r.Segments = append(r.Segments, ps)
|
||||
}
|
||||
|
||||
return &r
|
||||
}
|
||||
|
||||
// Match returns whether the route was matched, and extracts variables.
|
||||
func (r Route) Match(segments []string) (vars map[string]string, ok bool) {
|
||||
vars = make(map[string]string)
|
||||
var wildcard bool
|
||||
for i := 0; i < len(r.Segments); i++ {
|
||||
routeSegment := r.Segments[len(r.Segments)-1-i]
|
||||
inputSegmentIndex := len(segments) - 1 - i
|
||||
var inputSegment string
|
||||
if inputSegmentIndex > -1 {
|
||||
inputSegment = segments[inputSegmentIndex]
|
||||
}
|
||||
name, capture, wildcardMatch, matches := routeSegment.Match(inputSegment)
|
||||
if matches {
|
||||
if wildcardMatch {
|
||||
wildcard = true
|
||||
} else {
|
||||
wildcard = false
|
||||
}
|
||||
}
|
||||
if wildcard {
|
||||
matches = true
|
||||
}
|
||||
if !matches {
|
||||
return
|
||||
}
|
||||
if capture {
|
||||
vars[name] = inputSegment
|
||||
}
|
||||
}
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
40
vendor/github.com/a-h/gemini/mux/segment.go
generated
vendored
Normal file
40
vendor/github.com/a-h/gemini/mux/segment.go
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
package mux
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Segment is a path segment, e.g. in /users/{userid}/ there are two segments,
|
||||
// "users" and "{userid}". "{userid}" is a variable and will be captured.
|
||||
type Segment struct {
|
||||
Name string
|
||||
IsVariable bool
|
||||
IsWildcard bool
|
||||
}
|
||||
|
||||
// String pretty prints the segment, for debugging.
|
||||
func (ps *Segment) String() string {
|
||||
return fmt.Sprintf("{ Name: %v, IsVariable: %v, IsWildcard: %v }",
|
||||
ps.Name, ps.IsVariable, ps.IsWildcard)
|
||||
}
|
||||
|
||||
// Match on the string path segment.
|
||||
func (ps *Segment) Match(s string) (name string, capture bool, wildcard bool, matches bool) {
|
||||
if ps.IsWildcard {
|
||||
wildcard = true
|
||||
matches = true
|
||||
return
|
||||
}
|
||||
if ps.IsVariable {
|
||||
name = ps.Name
|
||||
capture = true
|
||||
matches = true
|
||||
return
|
||||
}
|
||||
if strings.EqualFold(s, ps.Name) {
|
||||
matches = true
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user