Files

46 lines
1.1 KiB
Go
Raw Permalink Normal View History

2026-08-09 18:03:09 +01:00
package acme
import (
"net/http"
"strings"
"sync"
)
// ChallengeResponder serves HTTP-01 challenge responses at
// /.well-known/acme-challenge/{token} — mount it on the plain :80 listener
// (or wherever the CA's HTTP-01 validator will connect) before requesting
// challenge validation.
type ChallengeResponder struct {
mu sync.RWMutex
tokens map[string]string // token -> key authorization
}
func NewChallengeResponder() *ChallengeResponder {
return &ChallengeResponder{tokens: make(map[string]string)}
}
func (c *ChallengeResponder) Set(token, keyAuthorization string) {
c.mu.Lock()
defer c.mu.Unlock()
c.tokens[token] = keyAuthorization
}
func (c *ChallengeResponder) Remove(token string) {
c.mu.Lock()
defer c.mu.Unlock()
delete(c.tokens, token)
}
func (c *ChallengeResponder) ServeHTTP(w http.ResponseWriter, r *http.Request) {
token := strings.TrimPrefix(r.URL.Path, "/.well-known/acme-challenge/")
c.mu.RLock()
keyAuth, ok := c.tokens[token]
c.mu.RUnlock()
if !ok {
http.NotFound(w, r)
return
}
w.Header().Set("Content-Type", "application/octet-stream")
w.Write([]byte(keyAuth))
}