Skip to content

Commit 77030c3

Browse files
cpujsha
authored andcommitted
Make it easier to instantiate ProblemDetails (letsencrypt#1851)
Several of the `ProblemType`s had convenience functions to instantiate `ProblemDetails`s using their type and a detail message. Where these existed I did a quick scan of the codebase to convert places where callers were explicitly constructing the `ProblemDetails` to use the convenience function. For the `ProblemType`s that did not have such a function, I created one and then converted callers to use it. Solves letsencrypt#1837.
1 parent 54573b3 commit 77030c3

File tree

6 files changed

+123
-116
lines changed

6 files changed

+123
-116
lines changed

bdns/problem.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,7 @@ const detailServerFailure = "server failure at resolver"
6060
// record type and domain given.
6161
func ProblemDetailsFromDNSError(err error) *probs.ProblemDetails {
6262
if dnsErr, ok := err.(*DNSError); ok {
63-
return &probs.ProblemDetails{
64-
Type: probs.ConnectionProblem,
65-
Detail: dnsErr.Error(),
66-
}
67-
}
68-
return &probs.ProblemDetails{
69-
Type: probs.ConnectionProblem,
70-
Detail: detailServerFailure,
63+
return probs.ConnectionFailure(dnsErr.Error())
7164
}
65+
return probs.ConnectionFailure(detailServerFailure)
7266
}

core/util.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,7 @@ func ProblemDetailsForError(err error, msg string) *probs.ProblemDetails {
131131
case SignatureValidationError:
132132
return probs.Malformed(fmt.Sprintf("%s :: %s", msg, err))
133133
case RateLimitedError:
134-
return &probs.ProblemDetails{
135-
Type: probs.RateLimitedProblem,
136-
Detail: fmt.Sprintf("%s :: %s", msg, err),
137-
HTTPStatus: statusTooManyRequests,
138-
}
134+
return probs.RateLimited(fmt.Sprintf("%s :: %s", msg, err))
139135
case BadNonceError:
140136
return probs.BadNonce(fmt.Sprintf("%s :: %s", msg, err))
141137
default:

probs/probs.go

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,50 @@ func ContentLengthRequired() *ProblemDetails {
142142
HTTPStatus: http.StatusLengthRequired,
143143
}
144144
}
145+
146+
// InvalidEmail returns a ProblemDetails representing an invalid email address
147+
// error
148+
func InvalidEmail(detail string) *ProblemDetails {
149+
return &ProblemDetails{
150+
Type: InvalidEmailProblem,
151+
Detail: detail,
152+
HTTPStatus: http.StatusBadRequest,
153+
}
154+
}
155+
156+
// ConnectionFailure returns a ProblemDetails representing a ConnectionProblem
157+
// error
158+
func ConnectionFailure(detail string) *ProblemDetails {
159+
return &ProblemDetails{
160+
Type: ConnectionProblem,
161+
Detail: detail,
162+
HTTPStatus: http.StatusBadRequest,
163+
}
164+
}
165+
166+
// UnknownHost returns a ProblemDetails representing an UnknownHostProblem error
167+
func UnknownHost(detail string) *ProblemDetails {
168+
return &ProblemDetails{
169+
Type: UnknownHostProblem,
170+
Detail: detail,
171+
HTTPStatus: http.StatusBadRequest,
172+
}
173+
}
174+
175+
// RateLimited returns a ProblemDetails representing a RateLimitedProblem error
176+
func RateLimited(detail string) *ProblemDetails {
177+
return &ProblemDetails{
178+
Type: RateLimitedProblem,
179+
Detail: detail,
180+
HTTPStatus: statusTooManyRequests,
181+
}
182+
}
183+
184+
// TLSError returns a ProblemDetails representing a TLSProblem error
185+
func TLSError(detail string) *ProblemDetails {
186+
return &ProblemDetails{
187+
Type: TLSProblem,
188+
Detail: detail,
189+
HTTPStatus: http.StatusBadRequest,
190+
}
191+
}

probs/probs_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,36 @@ func TestProblemDetailsToStatusCode(t *testing.T) {
4343
}
4444
}
4545
}
46+
47+
func TestProblemDetailsConvenience(t *testing.T) {
48+
testCases := []struct {
49+
pb *ProblemDetails
50+
expectedType ProblemType
51+
statusCode int
52+
detail string
53+
}{
54+
{InvalidEmail("invalid email detail"), InvalidEmailProblem, http.StatusBadRequest, "invalid email detail"},
55+
{ConnectionFailure("connection failure detail"), ConnectionProblem, http.StatusBadRequest, "connection failure detail"},
56+
{Malformed("malformed detail"), MalformedProblem, http.StatusBadRequest, "malformed detail"},
57+
{ServerInternal("internal error detail"), ServerInternalProblem, http.StatusInternalServerError, "internal error detail"},
58+
{Unauthorized("unauthorized detail"), UnauthorizedProblem, http.StatusForbidden, "unauthorized detail"},
59+
{UnknownHost("unknown host detail"), UnknownHostProblem, http.StatusBadRequest, "unknown host detail"},
60+
{RateLimited("rate limited detail"), RateLimitedProblem, statusTooManyRequests, "rate limited detail"},
61+
{BadNonce("bad nonce detail"), BadNonceProblem, http.StatusBadRequest, "bad nonce detail"},
62+
{TLSError("TLS error detail"), TLSProblem, http.StatusBadRequest, "TLS error detail"},
63+
}
64+
65+
for _, c := range testCases {
66+
if c.pb.Type != c.expectedType {
67+
t.Errorf("Incorrect problem type. Expected %s got %s", c.expectedType, c.pb.Type)
68+
}
69+
70+
if c.pb.HTTPStatus != c.statusCode {
71+
t.Errorf("Incorrect HTTP Status. Expected %d got %d", c.statusCode, c.pb.HTTPStatus)
72+
}
73+
74+
if c.pb.Detail != c.detail {
75+
t.Errorf("Incorrect detail message. Expected %s got %s", c.detail, c.pb.Detail)
76+
}
77+
}
78+
}

ra/registration-authority.go

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -104,16 +104,10 @@ const (
104104
func validateEmail(ctx context.Context, address string, resolver bdns.DNSResolver) (prob *probs.ProblemDetails) {
105105
emails, err := mail.ParseAddressList(address)
106106
if err != nil {
107-
return &probs.ProblemDetails{
108-
Type: probs.InvalidEmailProblem,
109-
Detail: unparseableEmailDetail,
110-
}
107+
return probs.InvalidEmail(unparseableEmailDetail)
111108
}
112109
if len(emails) > 1 {
113-
return &probs.ProblemDetails{
114-
Type: probs.InvalidEmailProblem,
115-
Detail: multipleAddressDetail,
116-
}
110+
return probs.InvalidEmail(multipleAddressDetail)
117111
}
118112
splitEmail := strings.SplitN(emails[0].Address, "@", -1)
119113
domain := strings.ToLower(splitEmail[len(splitEmail)-1])
@@ -147,10 +141,7 @@ func validateEmail(ctx context.Context, address string, resolver bdns.DNSResolve
147141
return nil
148142
}
149143

150-
return &probs.ProblemDetails{
151-
Type: probs.InvalidEmailProblem,
152-
Detail: emptyDNSResponseDetail,
153-
}
144+
return probs.InvalidEmail(emptyDNSResponseDetail)
154145
}
155146

156147
type certificateRequestEvent struct {

0 commit comments

Comments
 (0)