1
0
Fork 0

added an wellknown middleware

Dieser Commit ist enthalten in:
Sebastian Tobie 2022-11-06 10:53:38 +01:00
Ursprung 487a8b4c64
Commit 93c1b7a8b0
3 geänderte Dateien mit 147 neuen und 0 gelöschten Zeilen

2
middleware/wellknown/doc.go Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
// Package wellknown provides an middleware that lets sites to register themselfs to wellknown uris
package wellknown

15
middleware/wellknown/site.go Normale Datei
Datei anzeigen

@ -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
}

Datei anzeigen

@ -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)
}