Reorganized package tree and added doc comments
This commit is contained in:
parent
c300567c0c
commit
60e5a1c729
@ -1,7 +1,9 @@
|
||||
// Config provides a configuration system for routers.
|
||||
package config
|
||||
|
||||
import "crypto/tls"
|
||||
|
||||
// Config is an interface that configuration objects must fulfill.
|
||||
type Config interface {
|
||||
User (name string) User
|
||||
OverUsers (func (name string, user User) bool)
|
||||
@ -22,6 +24,7 @@ type Config interface {
|
||||
OverAliases (func (alias, target string) bool)
|
||||
}
|
||||
|
||||
// User represents a Hnakra user.
|
||||
type User interface {
|
||||
Validate (key []byte) bool
|
||||
RconAllow () bool
|
@ -3,10 +3,12 @@ package mux
|
||||
import "net/url"
|
||||
import "net/http"
|
||||
|
||||
// HTTP is an HTTP request multiplexer.
|
||||
type HTTP struct {
|
||||
Mux[http.Handler]
|
||||
}
|
||||
|
||||
// NewHTTP creates a new HTTP request multiplexer.
|
||||
func NewHTTP (resolver Resolver) *HTTP {
|
||||
mux := &HTTP { }
|
||||
mux.Mux.Redirect = mux.newRedirect
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Package mux provides request multiplexers for all protocols Hnakra supports.
|
||||
package mux
|
||||
|
||||
import "net"
|
||||
@ -8,6 +9,8 @@ import "errors"
|
||||
import "strings"
|
||||
import "net/url"
|
||||
|
||||
// Resolver represents an object capable of transforming a hosname alias into
|
||||
// another hostname.
|
||||
type Resolver interface {
|
||||
ResolveAlias (alias string) string
|
||||
}
|
||||
@ -68,6 +71,7 @@ func stripHostPort (h string) string {
|
||||
return host
|
||||
}
|
||||
|
||||
// Handler returns the handler for a particular URL.
|
||||
func (mux *Mux[HANDLER]) Handler (where *url.URL) (h HANDLER, pattern string) {
|
||||
// All other requests have any port stripped and path cleaned
|
||||
// before passing to mux.handler.
|
||||
@ -144,6 +148,10 @@ func (mux *Mux[HANDLER]) match (path string, original *url.URL) (h HANDLER, patt
|
||||
return mux.NotFound(original), ""
|
||||
}
|
||||
|
||||
// Handle registers a handler on the specified pattern. If a pattern ends in
|
||||
// '/', all requests for URLS under the pattern will be directed to the handler,
|
||||
// as well as the pattern itself. Additionally, requests for the pattern without
|
||||
// the trailing slash will be redirected to the pattern with the trailing slash.
|
||||
func (mux *Mux[HANDLER]) Handle (pattern string, handler HANDLER) error {
|
||||
mux.mutex.Lock()
|
||||
defer mux.mutex.Unlock()
|
||||
@ -176,6 +184,7 @@ func (mux *Mux[HANDLER]) Handle (pattern string, handler HANDLER) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unhandler removes the handler that was registered on the specified pattern.
|
||||
func (mux *Mux[HANDLER]) Unhandle (pattern string) error {
|
||||
mux.mutex.Lock()
|
||||
defer mux.mutex.Unlock()
|
||||
@ -199,6 +208,7 @@ func (mux *Mux[HANDLER]) Unhandle (pattern string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// OverHandlers calls a function for each registered handler.
|
||||
func (mux *Mux[HANDLER]) OverHandlers (callback func (pattern string, handler HANDLER) bool) {
|
||||
overSorted (mux.exactEntries, func (pattern string, entry muxEntry[HANDLER]) bool {
|
||||
return callback(pattern, entry.handler)
|
||||
|
@ -8,10 +8,10 @@ import "io"
|
||||
import "fmt"
|
||||
import "net/url"
|
||||
import "net/http"
|
||||
import "hnakra/config"
|
||||
import "hnakra/router"
|
||||
import "hnakra/rotate"
|
||||
import "hnakra/protocol"
|
||||
import "hnakra/router/config"
|
||||
|
||||
const css = `
|
||||
body { background-color: #161815; color: #aea894; margin: 3em; }
|
||||
@ -200,7 +200,7 @@ func (rcon *Rcon) serveServices (res http.ResponseWriter, req *http.Request) {
|
||||
service.Name(),
|
||||
service.Name(),
|
||||
service.Description(),
|
||||
service.Pattern())))
|
||||
router.FormatPattern(service.Pattern()))))
|
||||
return true
|
||||
})
|
||||
|
@ -1,32 +1,13 @@
|
||||
// Package router provides a reusable router implementation.
|
||||
package router
|
||||
|
||||
import "log"
|
||||
import "net"
|
||||
// import "errors"
|
||||
import "net/http"
|
||||
import "hnakra/config"
|
||||
import "hnakra/protocol"
|
||||
import "hnakra/router/mux"
|
||||
|
||||
type Pattern struct {
|
||||
Scheme string
|
||||
Host string
|
||||
Path string
|
||||
}
|
||||
|
||||
func (pattern Pattern) MuxPattern () string {
|
||||
return pattern.Host + pattern.Path
|
||||
}
|
||||
|
||||
func (pattern Pattern) String () string {
|
||||
return pattern.Scheme + "://" + pattern.Host + pattern.Path
|
||||
}
|
||||
|
||||
func (pattern *Pattern) FillDefaults () {
|
||||
if pattern.Scheme == "" { pattern.Scheme = "https" }
|
||||
if pattern.Host == "" { pattern.Host = "@" }
|
||||
if pattern.Path == "" { pattern.Path = "/" }
|
||||
}
|
||||
import "hnakra/router/config"
|
||||
|
||||
type Router struct {
|
||||
config config.Config
|
||||
@ -81,13 +62,17 @@ func (router *Router) unlist (service *Service) {
|
||||
delete(router.services, service)
|
||||
}
|
||||
|
||||
func (router *Router) Validate (name string, key []byte, pattern Pattern) protocol.Status {
|
||||
func (router *Router) Validate (name string, key []byte, scheme, host, path string) protocol.Status {
|
||||
user := router.config.User(name)
|
||||
if user == nil || !user.Validate(key) {
|
||||
return protocol.StatusBadCredentials
|
||||
}
|
||||
if !user.CanMountOn(pattern.Scheme, pattern.Host, pattern.Path) {
|
||||
if !user.CanMountOn(scheme, host, path) {
|
||||
return protocol.StatusBadMount
|
||||
}
|
||||
return protocol.StatusOk
|
||||
}
|
||||
|
||||
func FormatPattern (scheme, host, path string) string {
|
||||
return scheme + "://" + host + path
|
||||
}
|
||||
|
@ -38,8 +38,7 @@ func (request *activeRequest) ensureHeader () {
|
||||
|
||||
type Service struct {
|
||||
router *Router
|
||||
validate func (user string, key []byte, pattern Pattern) protocol.Status
|
||||
pattern Pattern
|
||||
scheme, host, path string
|
||||
|
||||
user, name, description string
|
||||
|
||||
@ -57,7 +56,6 @@ func (router *Router) newService (conn net.Conn) (service *Service) {
|
||||
service = &Service {
|
||||
idFactory: protocol.NewRouterIDFactory(),
|
||||
router: router,
|
||||
validate: router.Validate,
|
||||
conn: conn,
|
||||
requests: make(map[protocol.ID] *activeRequest),
|
||||
connReadWriter: bufio.NewReadWriter (
|
||||
@ -88,8 +86,8 @@ func (service *Service) Description () string {
|
||||
return service.description
|
||||
}
|
||||
|
||||
func (service *Service) Pattern () Pattern {
|
||||
return service.pattern
|
||||
func (service *Service) Pattern () (user, name, description string) {
|
||||
return service.user, service.name, service.description
|
||||
}
|
||||
|
||||
func (service *Service) Close () error {
|
||||
@ -104,9 +102,9 @@ func (service *Service) Shutdown () error {
|
||||
func (service *Service) ServeHTTP (res http.ResponseWriter, req *http.Request) {
|
||||
// if we are only accepting https requests and we recieve an http one,
|
||||
// redirect to the https version
|
||||
if req.TLS == nil && service.pattern.Scheme == "https" {
|
||||
if req.TLS == nil && service.scheme == "https" {
|
||||
newURL := req.URL
|
||||
newURL.Scheme = service.pattern.Scheme
|
||||
newURL.Scheme = service.scheme
|
||||
http.Redirect(res, req, newURL.String(), http.StatusPermanentRedirect)
|
||||
return
|
||||
}
|
||||
@ -326,15 +324,17 @@ func (service *Service) authenticate () (func(), bool) {
|
||||
}
|
||||
|
||||
// create pattern
|
||||
service.pattern = Pattern {
|
||||
Scheme: login.Scheme,
|
||||
Host: login.Host,
|
||||
Path: login.Path,
|
||||
}
|
||||
service.pattern.FillDefaults()
|
||||
service.scheme = login.Scheme
|
||||
service.host = login.Host
|
||||
service.path = login.Path
|
||||
if service.scheme == "" { service.scheme = "https://" }
|
||||
if service.host == "" { service.host = "@" }
|
||||
if service.path == "" { service.path = "/" }
|
||||
|
||||
// validate credentials
|
||||
status := service.validate(login.User, login.Key, service.pattern)
|
||||
status := service.router.Validate (
|
||||
login.User, login.Key,
|
||||
service.scheme, service.host, service.path)
|
||||
service.send(protocol.MessageStatus { Status: status })
|
||||
if status == protocol.StatusOk {
|
||||
service.user = login.User
|
||||
@ -343,19 +343,21 @@ func (service *Service) authenticate () (func(), bool) {
|
||||
|
||||
log.Println (
|
||||
"-->", service.conn.RemoteAddr(),
|
||||
"logged in as", login.User, "on", service.pattern)
|
||||
"logged in as", login.User, "on",
|
||||
FormatPattern(service.scheme, service.host, service.path))
|
||||
} else {
|
||||
log.Println (
|
||||
"ERR", service.conn.RemoteAddr(),
|
||||
"failed login as", login.User, "on", service.pattern)
|
||||
"failed login as", login.User, "on",
|
||||
FormatPattern(service.scheme, service.host, service.path))
|
||||
service.conn.Close()
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// mount service on the mux.
|
||||
var unhandle func ()
|
||||
muxPattern := service.pattern.MuxPattern()
|
||||
switch service.pattern.Scheme {
|
||||
muxPattern := service.host + service.path
|
||||
switch service.scheme {
|
||||
case "http", "https":
|
||||
err = service.router.HTTPMux().Handle(muxPattern, service)
|
||||
unhandle = func () {
|
||||
@ -367,7 +369,8 @@ func (service *Service) authenticate () (func(), bool) {
|
||||
if err != nil {
|
||||
log.Println (
|
||||
"ERR", service.name,
|
||||
"sent bad mount pattern:", service.pattern)
|
||||
"sent bad mount pattern:",
|
||||
FormatPattern(service.scheme, service.host, service.path))
|
||||
service.send(protocol.MessageStatus {
|
||||
Status: protocol.StatusBadMount,
|
||||
})
|
||||
|
@ -1,3 +1,4 @@
|
||||
// Package service provides a toolkit for creating Hnakra services.
|
||||
package service
|
||||
|
||||
import "os"
|
||||
|
Loading…
Reference in New Issue
Block a user