From a71cf89a47d9056860107bc1f3390871ca054a78 Mon Sep 17 00:00:00 2001 From: Aaron Sky Date: Thu, 6 Aug 2020 15:03:20 -0400 Subject: [PATCH] Updated pointer dereferences to be a little bit safer --- README.md | 8 ++++---- asc/asc.go | 34 +++++++++++++++++----------------- asc/schema_test.go | 7 ++++--- asc/upload_operation.go | 15 +++++++++++++-- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 11c44d8..2988f7f 100644 --- a/README.md +++ b/README.md @@ -49,10 +49,10 @@ func main() { // The bytes of the PKCS#8 private key created on App Store Connect. Keep this key safe as you can only download it once. privateKey = ioutil.ReadFile("path/to/key") - auth, err = asc.NewTokenConfig(keyID, issuerID, expiryDuration, privateKey) - if err != nil { - return nil, err - } + auth, err = asc.NewTokenConfig(keyID, issuerID, expiryDuration, privateKey) + if err != nil { + return nil, err + } client := asc.NewClient(auth.Client()) // list all apps with the bundle ID "com.sky.MyApp" in the authenticated user's team diff --git a/asc/asc.go b/asc/asc.go index 897c804..6bd9fec 100644 --- a/asc/asc.go +++ b/asc/asc.go @@ -99,17 +99,21 @@ type Rate struct { Remaining int `json:"remaining"` } -// ErrorResponse contains information with error details that an API returns in the response body whenever the API request is not successful. +// ErrorResponse contains information with error details that an API returns in the +// response body whenever the API request is not successful. type ErrorResponse struct { - Response *http.Response `json:"-"` - Errors *[]struct { - Code string `json:"code"` - Detail string `json:"detail"` - ID *string `json:"id,omitempty"` - Source *interface{} `json:"source,omitempty"` - Status string `json:"status"` - Title string `json:"title"` - } `json:"errors,omitempty"` + Response *http.Response `json:"-"` + Errors *[]ErrorResponseError `json:"errors,omitempty"` +} + +// ErrorResponseError is a model used in ErrorResponse to describe a single error from the API +type ErrorResponseError struct { + Code string `json:"code"` + Detail string `json:"detail"` + ID *string `json:"id,omitempty"` + Source *interface{} `json:"source,omitempty"` + Status string `json:"status"` + Title string `json:"title"` } type service struct { @@ -117,7 +121,7 @@ type service struct { } // request is a common structure for a request body sent to the API -type request struct { +type writingRequestPayload struct { Data interface{} `json:"data"` } @@ -213,7 +217,8 @@ func (c *Client) newRequest(method, path string, body interface{}, options ...re buf := new(bytes.Buffer) if body != nil { - err := json.NewEncoder(buf).Encode(wrapRequest(body)) + payload := &writingRequestPayload{Data: body} + err := json.NewEncoder(buf).Encode(payload) if err != nil { return nil, err } @@ -297,11 +302,6 @@ func (c *Client) do(req *http.Request, v interface{}) (*Response, error) { return response, err } -func wrapRequest(v interface{}) *request { - req := &request{Data: v} - return req -} - func newResponse(r *http.Response) *Response { response := &Response{Response: r} response.Rate = parseRate(r) diff --git a/asc/schema_test.go b/asc/schema_test.go index f11fd9d..e4d3f90 100644 --- a/asc/schema_test.go +++ b/asc/schema_test.go @@ -71,8 +71,9 @@ func emailContainerJSON(email string) string { } func TestEmailMarshal(t *testing.T) { - want := emailContainerJSON("my@email.com") - b := newEmailContainer("my@email.com") + email := "my@email.com" + want := emailContainerJSON(email) + b := newEmailContainer(email) got, err := json.Marshal(b) assert.NoError(t, err) assert.JSONEq(t, want, string(got)) @@ -86,7 +87,7 @@ func TestEmailMarshalInvalidEmail(t *testing.T) { func TestEmailUnmarshal(t *testing.T) { want := "my@email.com" - jsonStr := emailContainerJSON("my@email.com") + jsonStr := emailContainerJSON(want) var b emailContainer err := json.Unmarshal([]byte(jsonStr), &b) assert.NoError(t, err) diff --git a/asc/upload_operation.go b/asc/upload_operation.go index dfeba78..91231d6 100644 --- a/asc/upload_operation.go +++ b/asc/upload_operation.go @@ -62,6 +62,9 @@ func (e UploadOperationError) Error() string { // Chunk returns the bytes in the file from the given offset and with the given length func (op *UploadOperation) Chunk(f *os.File) (io.Reader, error) { + if op.Offset == nil || op.Length == nil { + return nil, errors.New("could not establish bounds of upload operation") + } _, err := f.Seek(int64(*op.Offset), 0) if err != nil { return nil, err @@ -76,12 +79,20 @@ func (op *UploadOperation) Chunk(f *os.File) (io.Reader, error) { // Request creates a new http.Request instance from the given UploadOperation and buffer func (op *UploadOperation) Request(data io.Reader) (*http.Request, error) { + if op.Method == nil || op.URL == nil { + return nil, errors.New("could not establish destination of upload operation") + } req, err := http.NewRequest(*op.Method, *op.URL, data) if err != nil { return nil, err } - for _, h := range *op.RequestHeaders { - req.Header.Add(*h.Name, *h.Value) + if op.RequestHeaders != nil { + for _, h := range *op.RequestHeaders { + if h.Name == nil || h.Value == nil { + continue + } + req.Header.Add(*h.Name, *h.Value) + } } return req, nil }