| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package monorail | 5 package monorail |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 "encoding/json" | 9 "encoding/json" |
| 10 "fmt" | 10 "fmt" |
| 11 "io" | 11 "io" |
| 12 "io/ioutil" | 12 "io/ioutil" |
| 13 "net/http" | 13 "net/http" |
| 14 "net/url" |
| 14 "strings" | 15 "strings" |
| 15 | 16 |
| 16 "golang.org/x/net/context" | 17 "golang.org/x/net/context" |
| 17 "golang.org/x/net/context/ctxhttp" | 18 "golang.org/x/net/context/ctxhttp" |
| 18 "google.golang.org/grpc" | 19 "google.golang.org/grpc" |
| 19 | 20 |
| 20 "github.com/luci/luci-go/common/clock" | 21 "github.com/luci/luci-go/common/clock" |
| 21 "github.com/luci/luci-go/common/errors" | 22 "github.com/luci/luci-go/common/errors" |
| 22 "github.com/luci/luci-go/common/logging" | 23 "github.com/luci/luci-go/common/logging" |
| 23 ) | 24 ) |
| (...skipping 15 matching lines...) Expand all Loading... |
| 39 // | 40 // |
| 40 // Methods do not implement retries. | 41 // Methods do not implement retries. |
| 41 // Use "github.com/luci/luci-go/common/errors".IsTransient to check | 42 // Use "github.com/luci/luci-go/common/errors".IsTransient to check |
| 42 // if an error is transient. | 43 // if an error is transient. |
| 43 // | 44 // |
| 44 // Client methods return an error on any grpc.CallOption. | 45 // Client methods return an error on any grpc.CallOption. |
| 45 func NewEndpointsClient(client *http.Client, url string) MonorailClient { | 46 func NewEndpointsClient(client *http.Client, url string) MonorailClient { |
| 46 return &epClient{HTTP: client, url: strings.TrimSuffix(url, "/")} | 47 return &epClient{HTTP: client, url: strings.TrimSuffix(url, "/")} |
| 47 } | 48 } |
| 48 | 49 |
| 49 func (c *epClient) call(ctx context.Context, urlSuffix string, request, response
interface{}) error { | 50 func (c *epClient) call(ctx context.Context, method, urlSuffix string, request,
response interface{}) error { |
| 50 client := c.HTTP | 51 client := c.HTTP |
| 51 if client == nil { | 52 if client == nil { |
| 52 client = http.DefaultClient | 53 client = http.DefaultClient |
| 53 } | 54 } |
| 54 | 55 |
| 55 // Limit ctx deadline to timeout set in client. | 56 // Limit ctx deadline to timeout set in client. |
| 56 if client.Timeout > 0 { | 57 if client.Timeout > 0 { |
| 57 clientDeadline := clock.Now(ctx).Add(client.Timeout) | 58 clientDeadline := clock.Now(ctx).Add(client.Timeout) |
| 58 if deadline, ok := ctx.Deadline(); !ok || deadline.After(clientD
eadline) { | 59 if deadline, ok := ctx.Deadline(); !ok || deadline.After(clientD
eadline) { |
| 59 ctx, _ = context.WithDeadline(ctx, clientDeadline) | 60 ctx, _ = context.WithDeadline(ctx, clientDeadline) |
| 60 } | 61 } |
| 61 } | 62 } |
| 62 | 63 |
| 63 // Convert request object to JSON. | 64 // Convert request object to JSON. |
| 64 reqBuf := &bytes.Buffer{} | 65 reqBuf := &bytes.Buffer{} |
| 65 if request != nil { | 66 if request != nil { |
| 66 if err := json.NewEncoder(reqBuf).Encode(request); err != nil { | 67 if err := json.NewEncoder(reqBuf).Encode(request); err != nil { |
| 67 return err | 68 return err |
| 68 } | 69 } |
| 69 } | 70 } |
| 70 | 71 |
| 71 // Make an HTTP request. | 72 // Make an HTTP request. |
| 72 » req, err := http.NewRequest("POST", c.url + urlSuffix, reqBuf) | 73 » req, err := http.NewRequest(method, c.url+urlSuffix, reqBuf) |
| 73 if err != nil { | 74 if err != nil { |
| 74 return fmt.Errorf("could not make a request to %s: %s", req.URL,
err) | 75 return fmt.Errorf("could not make a request to %s: %s", req.URL,
err) |
| 75 } | 76 } |
| 76 req.Header.Set("Content-Type", "application/json") | 77 req.Header.Set("Content-Type", "application/json") |
| 77 req.Header.Set("Accept", "application/json") | 78 req.Header.Set("Accept", "application/json") |
| 78 | 79 |
| 79 // Send the request. | 80 // Send the request. |
| 80 » logging.Debugf(ctx, "POST %s %s", req.URL, reqBuf.Bytes()) | 81 » logging.Debugf(ctx, "%s %s %s", method, req.URL, reqBuf.Bytes()) |
| 81 res, err := ctxhttp.Do(ctx, client, req) | 82 res, err := ctxhttp.Do(ctx, client, req) |
| 82 if err != nil { | 83 if err != nil { |
| 83 return errors.WrapTransient(err) | 84 return errors.WrapTransient(err) |
| 84 } | 85 } |
| 85 defer res.Body.Close() | 86 defer res.Body.Close() |
| 86 | 87 |
| 87 // Check HTTP status code. | 88 // Check HTTP status code. |
| 88 if res.StatusCode != http.StatusOK { | 89 if res.StatusCode != http.StatusOK { |
| 89 text, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1024)) | 90 text, _ := ioutil.ReadAll(io.LimitReader(res.Body, 1024)) |
| 90 err := fmt.Errorf("unexpected status %q. Response: %s", res.Stat
us, text) | 91 err := fmt.Errorf("unexpected status %q. Response: %s", res.Stat
us, text) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 104 | 105 |
| 105 func (c *epClient) InsertIssue(ctx context.Context, req *InsertIssueRequest, opt
ions ...grpc.CallOption) (*InsertIssueResponse, error) { | 106 func (c *epClient) InsertIssue(ctx context.Context, req *InsertIssueRequest, opt
ions ...grpc.CallOption) (*InsertIssueResponse, error) { |
| 106 if err := checkOptions(options); err != nil { | 107 if err := checkOptions(options); err != nil { |
| 107 return nil, err | 108 return nil, err |
| 108 } | 109 } |
| 109 if err := req.Validate(); err != nil { | 110 if err := req.Validate(); err != nil { |
| 110 return nil, err | 111 return nil, err |
| 111 } | 112 } |
| 112 url := fmt.Sprintf("/projects/%s/issues?sendEmail=%v", req.ProjectId, re
q.SendEmail) | 113 url := fmt.Sprintf("/projects/%s/issues?sendEmail=%v", req.ProjectId, re
q.SendEmail) |
| 113 res := &InsertIssueResponse{&Issue{}} | 114 res := &InsertIssueResponse{&Issue{}} |
| 114 » return res, c.call(ctx, url, &req.Issue, res.Issue) | 115 » return res, c.call(ctx, "POST", url, &req.Issue, res.Issue) |
| 115 } | 116 } |
| 116 | 117 |
| 117 func (c *epClient) InsertComment(ctx context.Context, req *InsertCommentRequest,
options ...grpc.CallOption) (*InsertCommentResponse, error) { | 118 func (c *epClient) InsertComment(ctx context.Context, req *InsertCommentRequest,
options ...grpc.CallOption) (*InsertCommentResponse, error) { |
| 118 if err := checkOptions(options); err != nil { | 119 if err := checkOptions(options); err != nil { |
| 119 return nil, err | 120 return nil, err |
| 120 } | 121 } |
| 121 url := fmt.Sprintf("/projects/%s/issues/%d/comments", req.Issue.ProjectI
d, req.Issue.IssueId) | 122 url := fmt.Sprintf("/projects/%s/issues/%d/comments", req.Issue.ProjectI
d, req.Issue.IssueId) |
| 122 » return &InsertCommentResponse{}, c.call(ctx, url, req.Comment, nil) | 123 » return &InsertCommentResponse{}, c.call(ctx, "POST", url, req.Comment, n
il) |
| 124 } |
| 125 |
| 126 func (c *epClient) IssuesList(ctx context.Context, req *IssuesListRequest, optio
ns ...grpc.CallOption) (*IssuesListResponse, error) { |
| 127 » if err := checkOptions(options); err != nil { |
| 128 » » return nil, err |
| 129 » } |
| 130 |
| 131 » args := url.Values{} |
| 132 » args.Set("can", strings.ToLower(req.Can.String())) |
| 133 » args.Set("q", req.Q) |
| 134 » args.Set("label", req.Label) |
| 135 » args.Set("maxResults", fmt.Sprintf("%d", req.MaxResults)) |
| 136 » args.Set("owner", req.Owner) |
| 137 » args.Set("publishedMax", fmt.Sprintf("%d", req.PublishedMax)) |
| 138 » args.Set("publishedMin", fmt.Sprintf("%d", req.PublishedMin)) |
| 139 » args.Set("sort", req.Sort) |
| 140 » args.Set("startIndex", fmt.Sprintf("%d", req.StartIndex)) |
| 141 » args.Set("status", req.Status) |
| 142 » args.Set("updatedMax", fmt.Sprintf("%d", req.UpdatedMax)) |
| 143 » args.Set("updatedMin", fmt.Sprintf("%d", req.UpdatedMin)) |
| 144 |
| 145 » url := fmt.Sprintf("/projects/%s/issues?%s", req.ProjectId, args.Encode(
)) |
| 146 » res := &IssuesListResponse{} |
| 147 » err := c.call(ctx, "GET", url, nil, res) |
| 148 » if err != nil { |
| 149 » » return nil, err |
| 150 » } |
| 151 » return res, nil |
| 123 } | 152 } |
| 124 | 153 |
| 125 func checkOptions(options []grpc.CallOption) error { | 154 func checkOptions(options []grpc.CallOption) error { |
| 126 if len(options) > 0 { | 155 if len(options) > 0 { |
| 127 return errGrpcOptions | 156 return errGrpcOptions |
| 128 } | 157 } |
| 129 return nil | 158 return nil |
| 130 } | 159 } |
| OLD | NEW |