Skip to content
Snippets Groups Projects
Select Git revision
1 result Searching

parallel.go

Blame
  • http_challenge.go 1.17 KiB
    package acmeserver
    
    import (
    	"context"
    	"net/http"
    	"sync"
    
    	"golang.org/x/crypto/acme"
    )
    
    // httpValidator can validate http-01 challenges. It serves
    // validation tokens under the /.well-known/acme-challenge path when
    // used as an HTTP handler.
    type httpValidator struct {
    	mx     sync.Mutex
    	tokens map[string][]byte
    }
    
    func newHTTPValidator() *httpValidator {
    	return &httpValidator{
    		tokens: make(map[string][]byte),
    	}
    }
    
    func (h *httpValidator) Fulfill(_ context.Context, client *acme.Client, _ string, chal *acme.Challenge) (func(), error) {
    	resp, err := client.HTTP01ChallengeResponse(chal.Token)
    	if err != nil {
    		return nil, err
    	}
    	path := client.HTTP01ChallengePath(chal.Token)
    
    	h.mx.Lock()
    	h.tokens[path] = []byte(resp)
    	h.mx.Unlock()
    
    	return func() {
    		go func() {
    			h.mx.Lock()
    			delete(h.tokens, path)
    			h.mx.Unlock()
    		}()
    	}, nil
    }
    
    func (h *httpValidator) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    	// No defer because it's not polite to Write() while holding the lock.
    	h.mx.Lock()
    	data, ok := h.tokens[r.URL.Path]
    	h.mx.Unlock()
    
    	if !ok {
    		http.NotFound(w, r)
    		return
    	}
    
    	// Not interested in errors writing the response.
    	w.Write(data) // nolint
    }