added an wellknown middleware
Dieser Commit ist enthalten in:
Ursprung
487a8b4c64
Commit
93c1b7a8b0
|
@ -0,0 +1,2 @@
|
||||||
|
// Package wellknown provides an middleware that lets sites to register themselfs to wellknown uris
|
||||||
|
package wellknown
|
|
@ -0,0 +1,15 @@
|
||||||
|
package wellknown
|
||||||
|
|
||||||
|
import "go.sebtobie.de/httpserver"
|
||||||
|
|
||||||
|
// Finger is an Simple Type for site to transport the information about the webfinger to the middleware
|
||||||
|
type Finger struct {
|
||||||
|
Webfinger Webfinger
|
||||||
|
Protocol string
|
||||||
|
}
|
||||||
|
|
||||||
|
// FingerSite is an type of site that provide content and want to publish it with webfinger
|
||||||
|
type FingerSite interface {
|
||||||
|
httpserver.Site
|
||||||
|
RegisterFingers() []*Finger
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
package wellknown
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
|
"go.sebtobie.de/httpserver"
|
||||||
|
"go.sebtobie.de/httpserver/middleware"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ middleware.Middleware = &Middleware{}
|
||||||
|
var _ httpserver.Site = &Middleware{}
|
||||||
|
|
||||||
|
type (
|
||||||
|
|
||||||
|
// Link is the reference where the application can find the object
|
||||||
|
Link struct {
|
||||||
|
Rel string
|
||||||
|
Type string
|
||||||
|
Href *url.URL
|
||||||
|
}
|
||||||
|
|
||||||
|
// Middleware is an middleware for sites to register themselfs to provide wellknown urls
|
||||||
|
Middleware struct {
|
||||||
|
// webfinger is an map consisting of protocol as key and an array of WebfingerAccount as value
|
||||||
|
webfinger map[string][]Webfinger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Webfinger is an function that accepts the account part(after ?resource=<protocol>:) and returns the aliases and the links.
|
||||||
|
// The bool value if for faster detection if the account was found.
|
||||||
|
Webfinger func(resource string) ([]string, []*Link, bool)
|
||||||
|
)
|
||||||
|
|
||||||
|
// New creates a new initialized Middleware
|
||||||
|
func New() *Middleware {
|
||||||
|
return &Middleware{
|
||||||
|
webfinger: map[string][]Webfinger{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defaults returns the default config values for the middleware
|
||||||
|
func (*Middleware) Defaults() middleware.Config {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gin does nothing.
|
||||||
|
func (*Middleware) Gin(c *gin.Context) {
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup does nothing
|
||||||
|
func (*Middleware) Setup(middleware.Config) {}
|
||||||
|
|
||||||
|
// Teardown does nothing
|
||||||
|
func (*Middleware) Teardown() {}
|
||||||
|
|
||||||
|
// Sites goes through all sites and collects all registrations for wellknown uris
|
||||||
|
func (m *Middleware) Sites(s []any) error {
|
||||||
|
for _, site := range s {
|
||||||
|
if wfs, ok := site.(FingerSite); ok {
|
||||||
|
for _, finger := range wfs.RegisterFingers() {
|
||||||
|
if _, ok := m.webfinger[finger.Protocol]; !ok {
|
||||||
|
m.webfinger[finger.Protocol] = []Webfinger{}
|
||||||
|
}
|
||||||
|
m.webfinger[finger.Protocol] = append(m.webfinger[finger.Protocol], finger.Webfinger)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Init initializes the routergroup. It must always run on /
|
||||||
|
func (m *Middleware) Init(rg *gin.RouterGroup) {
|
||||||
|
if len(m.webfinger) > 0 {
|
||||||
|
rg.GET(".well-known/webfinger", m.webfingerhf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Middleware) webfingerhf(c *gin.Context) {
|
||||||
|
resource := c.Query("resource")
|
||||||
|
if resource == "" {
|
||||||
|
c.AbortWithStatus(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
uri, err := url.Parse(resource)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Str("uri", resource).Msg("Failed to parse uri")
|
||||||
|
c.AbortWithStatus(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var wf []Webfinger
|
||||||
|
var found bool
|
||||||
|
if wf, found = m.webfinger[uri.Scheme]; !found {
|
||||||
|
c.AbortWithStatus(404)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var output = struct {
|
||||||
|
Subject string `json:"subject,omitempty"`
|
||||||
|
Aliases []string `json:"aliases,omitempty"`
|
||||||
|
Links []*Link `json:"links,omitempty"`
|
||||||
|
}{Subject: resource, Aliases: []string{}, Links: []*Link{}}
|
||||||
|
var aliases = []string{}
|
||||||
|
var links = []*Link{}
|
||||||
|
var input = uri.Opaque
|
||||||
|
if uri.Opaque == "" {
|
||||||
|
input = resource
|
||||||
|
}
|
||||||
|
outputok := false
|
||||||
|
for _, finger := range wf {
|
||||||
|
aliases, links, found = finger(input)
|
||||||
|
if !found {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
output.Aliases = append(output.Aliases, aliases...)
|
||||||
|
output.Links = append(output.Links, links...)
|
||||||
|
outputok = true
|
||||||
|
}
|
||||||
|
if outputok {
|
||||||
|
c.Header("Access-Control-Allow-Origin", "*")
|
||||||
|
json, err := json.Marshal(output)
|
||||||
|
if err != nil {
|
||||||
|
c.AbortWithStatus(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.Data(200, "application/jrd+json", json)
|
||||||
|
}
|
||||||
|
c.AbortWithStatus(404)
|
||||||
|
}
|
Laden…
In neuem Issue referenzieren