all repos — homestead @ 802d74fc1d38b7ee64f63c2f10810b20305c828a

Code for my website

domain/identity/webfinger/service.go (view raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package webfinger

import (
	"encoding/json"
	"net/http"

	ihttp "alin.ovh/homestead/shared/http"
	"alin.ovh/x/log"

	"github.com/benpate/digit"
)

type ResourceProvider interface {
	GetResource() string
	GetIdentityResource() digit.Resource
}

type Service struct {
	log        *log.Logger
	providers  []ResourceProvider
	corsOrigin string
}

type Option func(*Service)

func WithCORSOrigin(origin string) Option {
	return func(s *Service) {
		s.corsOrigin = origin
	}
}

func New(logger *log.Logger, providers []ResourceProvider, opts ...Option) *Service {
	service := &Service{
		log:        logger,
		providers:  providers,
		corsOrigin: "*", // Default to allow all origins
	}

	for _, opt := range opts {
		opt(service)
	}

	return service
}

func (s *Service) RegisterHandlers(mux *http.ServeMux) {
	mux.HandleFunc("/.well-known/webfinger", s.handleWebFinger)
}

func (s *Service) Handler() http.HandlerFunc {
	return s.handleWebFinger
}

func (s *Service) HandleFunc(w http.ResponseWriter, r *http.Request) ihttp.Error {
	resource := r.URL.Query().Get("resource")
	if resource == "" {
		return ihttp.BadRequest("Missing resource parameter", nil)
	}

	for _, provider := range s.providers {
		if resource == provider.GetResource() {
			w.Header().Add("Content-Type", "application/jrd+json")

			if s.corsOrigin != "" {
				w.Header().Add("Access-Control-Allow-Origin", s.corsOrigin)
			}

			if err := json.NewEncoder(w).Encode(provider.GetIdentityResource()); err != nil {
				return ihttp.InternalServerError("Failed to encode webfinger response", err)
			}

			return nil
		}
	}

	return ihttp.NotFound("Resource not found")
}

func (s *Service) handleWebFinger(w http.ResponseWriter, r *http.Request) {
	if err := s.HandleFunc(w, r); err != nil {
		status := err.StatusCode()
		if status == 0 {
			status = http.StatusInternalServerError
		}
		http.Error(w, err.Error(), status)
	}
}