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