Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: common/lhttp/client.go

Issue 2984913002: Add HTTP error annotation. (Closed)
Patch Set: Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « common/errors/tags.go ('k') | common/lhttp/client_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The LUCI Authors. 1 // Copyright 2015 The LUCI Authors.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License. 4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 // Return the same error again to continue retry behaviour, or nil to pretend 47 // Return the same error again to continue retry behaviour, or nil to pretend
48 // this error was a success. 48 // this error was a success.
49 type ErrorHandler func(resp *http.Response, err error) error 49 type ErrorHandler func(resp *http.Response, err error) error
50 50
51 // RequestGen is a generator function to create a new request. It may be called 51 // RequestGen is a generator function to create a new request. It may be called
52 // multiple times if an operation needs to be retried. The HTTP server is 52 // multiple times if an operation needs to be retried. The HTTP server is
53 // responsible for closing the Request body, as per http.Request Body method 53 // responsible for closing the Request body, as per http.Request Body method
54 // documentation. 54 // documentation.
55 type RequestGen func() (*http.Request, error) 55 type RequestGen func() (*http.Request, error)
56 56
57 var httpTagKey = errors.NewTagKey("this is an HTTP error")
58
59 func applyHTTPTag(err error, status int) error {
60 return errors.TagValue{Key: httpTagKey, Value: status}.Apply(err)
61 }
62
63 func IsHTTPError(err error) (status int, ok bool) {
64 d, ok := errors.TagValueIn(httpTagKey, err)
65 if ok {
66 status = d.(int)
67 }
68 return
69 }
70
57 // NewRequest returns a retriable request. 71 // NewRequest returns a retriable request.
58 // 72 //
59 // The handler func is responsible for closing the response Body before 73 // The handler func is responsible for closing the response Body before
60 // returning. It should return retry.Error in case of retriable error, for 74 // returning. It should return retry.Error in case of retriable error, for
61 // example if a TCP connection is terminated while receiving the content. 75 // example if a TCP connection is terminated while receiving the content.
62 // 76 //
63 // If rFn is nil, NewRequest will use a default exponential backoff strategy 77 // If rFn is nil, NewRequest will use a default exponential backoff strategy
64 // only for transient errors. 78 // only for transient errors.
65 // 79 //
66 // If errorHandler is nil, the default error handler will drain and close the 80 // If errorHandler is nil, the default error handler will drain and close the
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 Tag(transient.Tag).Err() 124 Tag(transient.Tag).Err()
111 case status >= 400: 125 case status >= 400:
112 // Any other failure code is a hard failure. 126 // Any other failure code is a hard failure.
113 err = fmt.Errorf("http request failed: %s (HTTP %d)", http.StatusText(status), status) 127 err = fmt.Errorf("http request failed: %s (HTTP %d)", http.StatusText(status), status)
114 default: 128 default:
115 // The handler may still return a retry.Error to indicate that the request 129 // The handler may still return a retry.Error to indicate that the request
116 // should be retried even on successful status c ode. 130 // should be retried even on successful status c ode.
117 return handler(resp) 131 return handler(resp)
118 } 132 }
119 133
134 err = applyHTTPTag(err, status)
120 return errorHandler(resp, err) 135 return errorHandler(resp, err)
121 }, nil) 136 }, nil)
122 if err != nil { 137 if err != nil {
123 » » » err = fmt.Errorf("%v (attempts: %d)", err, attempts) 138 » » » err = errors.Annotate(err, "gave up after %d attempts", attempts).Err()
124 } 139 }
125 return status, err 140 return status, err
126 } 141 }
127 } 142 }
128 143
129 // NewRequestJSON returns a retriable request calling a JSON endpoint. 144 // NewRequestJSON returns a retriable request calling a JSON endpoint.
130 func NewRequestJSON(ctx context.Context, c *http.Client, rFn retry.Factory, url, method string, headers map[string]string, in, out interface{}) (func() (int, er ror), error) { 145 func NewRequestJSON(ctx context.Context, c *http.Client, rFn retry.Factory, url, method string, headers map[string]string, in, out interface{}) (func() (int, er ror), error) {
131 var encoded []byte 146 var encoded []byte
132 if in != nil { 147 if in != nil {
133 var err error 148 var err error
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 } 199 }
185 200
186 // PostJSON is a shorthand. It returns the HTTP status code and error if any. 201 // PostJSON is a shorthand. It returns the HTTP status code and error if any.
187 func PostJSON(ctx context.Context, rFn retry.Factory, c *http.Client, url string , headers map[string]string, in, out interface{}) (int, error) { 202 func PostJSON(ctx context.Context, rFn retry.Factory, c *http.Client, url string , headers map[string]string, in, out interface{}) (int, error) {
188 req, err := NewRequestJSON(ctx, c, rFn, url, "POST", headers, in, out) 203 req, err := NewRequestJSON(ctx, c, rFn, url, "POST", headers, in, out)
189 if err != nil { 204 if err != nil {
190 return 0, err 205 return 0, err
191 } 206 }
192 return req() 207 return req()
193 } 208 }
OLDNEW
« no previous file with comments | « common/errors/tags.go ('k') | common/lhttp/client_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698