errors.go raw

   1  package acme
   2  
   3  import (
   4  	"fmt"
   5  	"strings"
   6  )
   7  
   8  // Errors types.
   9  const (
  10  	errNS              = "urn:ietf:params:acme:error:"
  11  	BadNonceErr        = errNS + "badNonce"
  12  	AlreadyReplacedErr = errNS + "alreadyReplaced"
  13  	RateLimitedErr     = errNS + "rateLimited"
  14  )
  15  
  16  // ProblemDetails the problem details object.
  17  // - https://www.rfc-editor.org/rfc/rfc7807.html#section-3.1
  18  // - https://www.rfc-editor.org/rfc/rfc8555.html#section-7.3.3
  19  type ProblemDetails struct {
  20  	Type        string       `json:"type,omitempty"`
  21  	Detail      string       `json:"detail,omitempty"`
  22  	HTTPStatus  int          `json:"status,omitempty"`
  23  	Instance    string       `json:"instance,omitempty"`
  24  	SubProblems []SubProblem `json:"subproblems,omitempty"`
  25  
  26  	// additional values to have a better error message (Not defined by the RFC)
  27  	Method string `json:"method,omitempty"`
  28  	URL    string `json:"url,omitempty"`
  29  }
  30  
  31  func (p *ProblemDetails) Error() string {
  32  	var msg strings.Builder
  33  
  34  	msg.WriteString(fmt.Sprintf("acme: error: %d", p.HTTPStatus))
  35  
  36  	if p.Method != "" || p.URL != "" {
  37  		msg.WriteString(fmt.Sprintf(" :: %s :: %s", p.Method, p.URL))
  38  	}
  39  
  40  	msg.WriteString(fmt.Sprintf(" :: %s :: %s", p.Type, p.Detail))
  41  
  42  	for _, sub := range p.SubProblems {
  43  		msg.WriteString(fmt.Sprintf(", problem: %q :: %s", sub.Type, sub.Detail))
  44  	}
  45  
  46  	if p.Instance != "" {
  47  		msg.WriteString(", url: " + p.Instance)
  48  	}
  49  
  50  	return msg.String()
  51  }
  52  
  53  // SubProblem a "subproblems".
  54  // - https://www.rfc-editor.org/rfc/rfc8555.html#section-6.7.1
  55  type SubProblem struct {
  56  	Type       string     `json:"type,omitempty"`
  57  	Detail     string     `json:"detail,omitempty"`
  58  	Identifier Identifier `json:"identifier"`
  59  }
  60  
  61  // NonceError represents the error which is returned
  62  // if the nonce sent by the client was not accepted by the server.
  63  type NonceError struct {
  64  	*ProblemDetails
  65  }
  66  
  67  func (e *NonceError) Unwrap() error {
  68  	return e.ProblemDetails
  69  }
  70  
  71  // AlreadyReplacedError represents the error which is returned
  72  // if the Server rejects the request because the identified certificate has already been marked as replaced.
  73  // - https://www.rfc-editor.org/rfc/rfc9773.html#section-5
  74  type AlreadyReplacedError struct {
  75  	*ProblemDetails
  76  }
  77  
  78  func (e *AlreadyReplacedError) Unwrap() error {
  79  	return e.ProblemDetails
  80  }
  81  
  82  // RateLimitedError represents the error which is returned
  83  // if the server rejects the request because the client has exceeded the rate limit.
  84  // - https://www.rfc-editor.org/rfc/rfc8555.html#section-6.6
  85  type RateLimitedError struct {
  86  	*ProblemDetails
  87  
  88  	RetryAfter string
  89  }
  90  
  91  func (e *RateLimitedError) Unwrap() error {
  92  	return e.ProblemDetails
  93  }
  94