frostfs-http-gw/router/router.go
Denis Kirillov cf1a1a80f7 [#XX] Support virtual-hosted-style access to container
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
2023-04-21 13:11:12 +03:00

69 lines
1.5 KiB
Go

package router
import (
"strings"
"github.com/fasthttp/router"
"github.com/valyala/fasthttp"
)
type HostBucketRouter struct {
routes map[string]*router.Router
bktParam string
defaultRouter *router.Router
}
func NewHostBucketRouter(bktParam string) HostBucketRouter {
return HostBucketRouter{
routes: make(map[string]*router.Router),
bktParam: bktParam,
}
}
func (hr *HostBucketRouter) Default(router *router.Router) {
hr.defaultRouter = router
}
func (hr HostBucketRouter) Map(host string, h *router.Router) {
hr.routes[strings.ToLower(host)] = h
}
func (hr HostBucketRouter) Handler(ctx *fasthttp.RequestCtx) {
bucket, domain := getBucketDomain(getHost(ctx))
_ = bucket
domainRouter, ok := hr.routes[strings.ToLower(domain)]
if !ok {
domainRouter = hr.defaultRouter
if domainRouter == nil {
ctx.Error(fasthttp.StatusMessage(fasthttp.StatusNotFound), fasthttp.StatusNotFound)
return
}
}
if bucket != "" {
ctx.SetUserValue(hr.bktParam, bucket)
}
domainRouter.Handler(ctx)
}
func getBucketDomain(host string) (bucket string, domain string) {
parts := strings.Split(host, ".")
if len(parts) > 1 {
return parts[0], strings.Join(parts[1:], ".")
}
return "", host
}
// getHost tries its best to return the request host.
// According to section 14.23 of RFC 2616 the Host header
// can include the port number if the default value of 80 is not used.
func getHost(r *fasthttp.RequestCtx) string {
host := string(r.Host())
if i := strings.Index(host, ":"); i != -1 {
host = host[:i]
}
return host
}