github.com/letsencrypt/boulder@v0.20251208.0/test/chall-test-srv/history.go (about)

     1  package main
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	"github.com/letsencrypt/challtestsrv"
    10  )
    11  
    12  // clearHistory handles an HTTP POST request to clear the challenge server
    13  // request history for a specific hostname and type of event.
    14  //
    15  // The POST body is expected to have two parameters:
    16  // "host" - the hostname to clear history for.
    17  // "type" - the type of event to clear. May be "http", "dns", or "tlsalpn".
    18  //
    19  // A successful POST will write http.StatusOK to the client.
    20  func (srv *managementServer) clearHistory(w http.ResponseWriter, r *http.Request) {
    21  	var request struct {
    22  		Host string
    23  		Type string `json:"type"`
    24  	}
    25  	if err := mustParsePOST(&request, r); err != nil {
    26  		http.Error(w, err.Error(), http.StatusBadRequest)
    27  		return
    28  	}
    29  	typeMap := map[string]challtestsrv.RequestEventType{
    30  		"http":    challtestsrv.HTTPRequestEventType,
    31  		"dns":     challtestsrv.DNSRequestEventType,
    32  		"tlsalpn": challtestsrv.TLSALPNRequestEventType,
    33  	}
    34  	if request.Host == "" {
    35  		http.Error(w, "host parameter must not be empty", http.StatusBadRequest)
    36  		return
    37  	}
    38  	if code, ok := typeMap[request.Type]; ok {
    39  		srv.challSrv.ClearRequestHistory(request.Host, code)
    40  		srv.log.Printf("Cleared challenge server request history for %q %q events\n",
    41  			request.Host, request.Type)
    42  		w.WriteHeader(http.StatusOK)
    43  		return
    44  	}
    45  
    46  	http.Error(w, fmt.Sprintf("%q event type unknown", request.Type), http.StatusBadRequest)
    47  }
    48  
    49  // getHTTPHistory returns only the HTTPRequestEvents for the given hostname
    50  // from the challenge server's request history in JSON form.
    51  func (srv *managementServer) getHTTPHistory(w http.ResponseWriter, r *http.Request) {
    52  	host, err := requestHost(r)
    53  	if err != nil {
    54  		http.Error(w, err.Error(), http.StatusBadRequest)
    55  		return
    56  	}
    57  	srv.writeHistory(
    58  		srv.challSrv.RequestHistory(host, challtestsrv.HTTPRequestEventType),
    59  		w)
    60  }
    61  
    62  // getDNSHistory returns only the DNSRequestEvents from the challenge
    63  // server's request history in JSON form.
    64  func (srv *managementServer) getDNSHistory(w http.ResponseWriter, r *http.Request) {
    65  	host, err := requestHost(r)
    66  	if err != nil {
    67  		http.Error(w, err.Error(), http.StatusBadRequest)
    68  		return
    69  	}
    70  	srv.writeHistory(
    71  		srv.challSrv.RequestHistory(host, challtestsrv.DNSRequestEventType),
    72  		w)
    73  }
    74  
    75  // getTLSALPNHistory returns only the TLSALPNRequestEvents from the challenge
    76  // server's request history in JSON form.
    77  func (srv *managementServer) getTLSALPNHistory(w http.ResponseWriter, r *http.Request) {
    78  	host, err := requestHost(r)
    79  	if err != nil {
    80  		http.Error(w, err.Error(), http.StatusBadRequest)
    81  		return
    82  	}
    83  	srv.writeHistory(
    84  		srv.challSrv.RequestHistory(host, challtestsrv.TLSALPNRequestEventType),
    85  		w)
    86  }
    87  
    88  // requestHost extracts the Host parameter of a JSON POST body in the provided
    89  // request, or returns an error.
    90  func requestHost(r *http.Request) (string, error) {
    91  	var request struct {
    92  		Host string
    93  	}
    94  	if err := mustParsePOST(&request, r); err != nil {
    95  		return "", err
    96  	}
    97  	if request.Host == "" {
    98  		return "", errors.New("host parameter of POST body must not be empty")
    99  	}
   100  	return request.Host, nil
   101  }
   102  
   103  // writeHistory writes the provided list of challtestsrv.RequestEvents to the
   104  // provided http.ResponseWriter in JSON form.
   105  func (srv *managementServer) writeHistory(
   106  	history []challtestsrv.RequestEvent, w http.ResponseWriter,
   107  ) {
   108  	// Always write an empty JSON list instead of `null`
   109  	if history == nil {
   110  		history = []challtestsrv.RequestEvent{}
   111  	}
   112  	jsonHistory, err := json.MarshalIndent(history, "", "   ")
   113  	if err != nil {
   114  		srv.log.Printf("Error marshaling history: %v\n", err)
   115  		w.WriteHeader(http.StatusInternalServerError)
   116  		return
   117  	}
   118  
   119  	w.Header().Set("Content-Type", "application/json; charset=utf-8")
   120  	w.WriteHeader(http.StatusOK)
   121  	_, _ = w.Write(jsonHistory)
   122  }