Skip to content

Commit 1c01bf5

Browse files
authored
Merge pull request #10 from foomo/feature/uploads
feat: file uploads API support
2 parents 1728e2a + fa68cfe commit 1c01bf5

17 files changed

+124
-104
lines changed

api_key.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func (service *APIKeyService) List(ctx context.Context, spaceID string) *Collect
5959
path := fmt.Sprintf("/spaces/%s%s/api_keys", spaceID, getEnvPath(service.c))
6060
method := http.MethodGet
6161

62-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
62+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
6363
if err != nil {
6464
return &Collection{}
6565
}
@@ -76,7 +76,7 @@ func (service *APIKeyService) Get(ctx context.Context, spaceID, apiKeyID string)
7676
path := fmt.Sprintf("/spaces/%s%s/api_keys/%s", spaceID, getEnvPath(service.c), apiKeyID)
7777
method := http.MethodGet
7878

79-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
79+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
8080
if err != nil {
8181
return nil, err
8282
}
@@ -107,7 +107,7 @@ func (service *APIKeyService) Upsert(ctx context.Context, spaceID string, apiKey
107107
method = "POST"
108108
}
109109

110-
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray))
110+
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray), nil)
111111
if err != nil {
112112
return err
113113
}
@@ -122,7 +122,7 @@ func (service *APIKeyService) Delete(ctx context.Context, spaceID string, apiKey
122122
path := fmt.Sprintf("/spaces/%s%s/api_keys/%s", spaceID, getEnvPath(service.c), apiKey.Sys.ID)
123123
method := http.MethodDelete
124124

125-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
125+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
126126
if err != nil {
127127
return err
128128
}

asset.go

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type File struct {
1919
ContentType string `json:"contentType,omitempty"`
2020
URL string `json:"url,omitempty"`
2121
UploadURL string `json:"upload,omitempty"`
22+
UploadFrom *Upload `json:"uploadFrom,omitempty"`
2223
Detail *FileDetail `json:"details,omitempty"`
2324
}
2425

@@ -76,7 +77,7 @@ func (service *AssetsService) List(ctx context.Context, spaceID string) *Collect
7677
path := fmt.Sprintf("/spaces/%s%s/assets", spaceID, getEnvPath(service.c))
7778
method := http.MethodGet
7879

79-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
80+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
8081
if err != nil {
8182
return &Collection{}
8283
}
@@ -98,7 +99,7 @@ func (service *AssetsService) Get(ctx context.Context, spaceID, assetID string,
9899

99100
method := http.MethodGet
100101

101-
req, err := service.c.newRequest(ctx, method, path, query, nil)
102+
req, err := service.c.newRequest(ctx, method, path, query, nil, nil)
102103
if err != nil {
103104
return nil, err
104105
}
@@ -167,7 +168,7 @@ func (service *AssetsService) Upsert(ctx context.Context, spaceID string, asset
167168
method = "POST"
168169
}
169170

170-
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray))
171+
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray), nil)
171172
if err != nil {
172173
return err
173174
}
@@ -182,7 +183,7 @@ func (service *AssetsService) Delete(ctx context.Context, spaceID string, asset
182183
path := fmt.Sprintf("/spaces/%s%s/assets/%s", spaceID, getEnvPath(service.c), asset.Sys.ID)
183184
method := http.MethodDelete
184185

185-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
186+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
186187
if err != nil {
187188
return err
188189
}
@@ -198,13 +199,10 @@ func (service *AssetsService) Process(ctx context.Context, spaceID string, asset
198199
var locale string
199200
for k := range asset.Fields.Title {
200201
locale = k
201-
if asset.Fields.File[k].UploadURL == "" {
202-
continue
203-
}
204202
path := fmt.Sprintf("/spaces/%s%s/assets/%s/files/%s/process", spaceID, getEnvPath(service.c), asset.Sys.ID, locale)
205203
method := http.MethodPut
206204

207-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
205+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
208206
if err != nil {
209207
return err
210208
}
@@ -224,7 +222,7 @@ func (service *AssetsService) Publish(ctx context.Context, spaceID string, asset
224222
path := fmt.Sprintf("/spaces/%s%s/assets/%s/published", spaceID, getEnvPath(service.c), asset.Sys.ID)
225223
method := http.MethodPut
226224

227-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
225+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
228226
if err != nil {
229227
return err
230228
}
@@ -240,7 +238,7 @@ func (service *AssetsService) Unpublish(ctx context.Context, spaceID string, ass
240238
path := fmt.Sprintf("/spaces/%s%s/assets/%s/published", spaceID, getEnvPath(service.c), asset.Sys.ID)
241239
method := http.MethodDelete
242240

243-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
241+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
244242
if err != nil {
245243
return err
246244
}

collection.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func (col *Collection) GetAll() (*Collection, error) {
114114
return nil, errNext
115115
}
116116
allItems = append(allItems, col.Items...)
117-
if uint16(len(col.Items)) < col.Limit {
117+
if len(col.Items) < int(col.Limit) {
118118
break
119119
}
120120
}

collection_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ func TestNewCollection(t *testing.T) {
6161
Filename: "error-notResolvable.json",
6262
})
6363

64-
req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil)
64+
req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil, nil)
6565
if err != nil {
6666
t.Fatal(err)
6767
}
@@ -92,7 +92,7 @@ func TestNewCollection(t *testing.T) {
9292
Filename: "error-nameUnknown.json",
9393
})
9494

95-
req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil)
95+
req, err := c.newRequest(context.TODO(), http.MethodGet, "/", url.Values{}, nil, nil)
9696
if err != nil {
9797
t.Fatal(err)
9898
}

content_type.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ func (ct *ContentType) GetVersion() int {
296296
func (service *ContentTypesService) List(ctx context.Context, spaceID string) *Collection {
297297
path := fmt.Sprintf("/spaces/%s%s/content_types", spaceID, getEnvPath(service.c))
298298

299-
req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil)
299+
req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil, nil)
300300
if err != nil {
301301
return nil
302302
}
@@ -312,7 +312,7 @@ func (service *ContentTypesService) List(ctx context.Context, spaceID string) *C
312312
func (service *ContentTypesService) Get(ctx context.Context, spaceID, contentTypeID string) (*ContentType, error) {
313313
path := fmt.Sprintf("/spaces/%s%s/content_types/%s", spaceID, getEnvPath(service.c), contentTypeID)
314314

315-
req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil)
315+
req, err := service.c.newRequest(ctx, http.MethodGet, path, nil, nil, nil)
316316
if err != nil {
317317
return nil, err
318318
}
@@ -343,7 +343,7 @@ func (service *ContentTypesService) Upsert(ctx context.Context, spaceID string,
343343
method = "POST"
344344
}
345345

346-
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray))
346+
req, err := service.c.newRequest(ctx, method, path, nil, bytes.NewReader(bytesArray), nil)
347347
if err != nil {
348348
return err
349349
}
@@ -358,7 +358,7 @@ func (service *ContentTypesService) Delete(ctx context.Context, spaceID string,
358358
path := fmt.Sprintf("/spaces/%s%s/content_types/%s", spaceID, getEnvPath(service.c), ct.Sys.ID)
359359
method := http.MethodDelete
360360

361-
req, err := service.c.newRequest(ctx, method, path, nil, nil)
361+
req, err := service.c.newRequest(ctx, method, path, nil, nil, nil)
362362
if err != nil {
363363
return err
364364
}
@@ -373,7 +373,7 @@ func (service *ContentTypesService) Delete(ctx context.Context, spaceID string,
373373
func (service *ContentTypesService) Activate(ctx context.Context, spaceID string, ct *ContentType) error {
374374
path := fmt.Sprintf("/spaces/%s%s/content_types/%s/published", spaceID, getEnvPath(service.c), ct.Sys.ID)
375375

376-
req, err := service.c.newRequest(ctx, http.MethodPut, path, nil, nil)
376+
req, err := service.c.newRequest(ctx, http.MethodPut, path, nil, nil, nil)
377377
if err != nil {
378378
return err
379379
}
@@ -388,7 +388,7 @@ func (service *ContentTypesService) Activate(ctx context.Context, spaceID string
388388
func (service *ContentTypesService) Deactivate(ctx context.Context, spaceID string, ct *ContentType) error {
389389
path := fmt.Sprintf("/spaces/%s%s/content_types/%s/published", spaceID, getEnvPath(service.c), ct.Sys.ID)
390390

391-
req, err := service.c.newRequest(ctx, http.MethodDelete, path, nil, nil)
391+
req, err := service.c.newRequest(ctx, http.MethodDelete, path, nil, nil, nil)
392392
if err != nil {
393393
return err
394394
}

content_type_field_validations.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -106,24 +106,24 @@ func (v *FieldValidationDimension) UnmarshalJSON(data []byte) error {
106106
if width, ok := dimensionData["width"].(map[string]interface{}); ok {
107107
v.Width = &MinMax{}
108108

109-
if min, ok := width["min"].(float64); ok {
110-
v.Width.Min = min
109+
if minimum, ok := width["min"].(float64); ok {
110+
v.Width.Min = minimum
111111
}
112112

113-
if max, ok := width["min"].(float64); ok {
114-
v.Width.Max = max
113+
if maximum, ok := width["min"].(float64); ok {
114+
v.Width.Max = maximum
115115
}
116116
}
117117

118118
if height, ok := dimensionData["height"].(map[string]interface{}); ok {
119119
v.Height = &MinMax{}
120120

121-
if min, ok := height["min"].(float64); ok {
122-
v.Height.Min = min
121+
if minimum, ok := height["min"].(float64); ok {
122+
v.Height.Min = minimum
123123
}
124124

125-
if max, ok := height["max"].(float64); ok {
126-
v.Height.Max = max
125+
if maximum, ok := height["max"].(float64); ok {
126+
v.Height.Max = maximum
127127
}
128128
}
129129

@@ -193,17 +193,17 @@ func (v *FieldValidationDate) UnmarshalJSON(data []byte) error {
193193

194194
v.Range = &DateMinMax{}
195195

196-
if min, ok := dateRangeData["min"].(string); ok {
197-
minDate, err := time.Parse("2006-01-02T03:04:05", min)
196+
if minimum, ok := dateRangeData["min"].(string); ok {
197+
minDate, err := time.Parse("2006-01-02T03:04:05", minimum)
198198
if err != nil {
199199
return err
200200
}
201201

202202
v.Range.Min = minDate
203203
}
204204

205-
if max, ok := dateRangeData["max"].(string); ok {
206-
maxDate, err := time.Parse("2006-01-02T03:04:05", max)
205+
if maximum, ok := dateRangeData["max"].(string); ok {
206+
maxDate, err := time.Parse("2006-01-02T03:04:05", maximum)
207207
if err != nil {
208208
return err
209209
}

content_type_field_validations_test.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,16 +131,16 @@ func TestFieldValidationDate(t *testing.T) {
131131
var err error
132132

133133
layout := "2006-01-02T03:04:05"
134-
min := time.Now()
135-
max := time.Now()
134+
minimum := time.Now()
135+
maximum := time.Now()
136136

137-
minStr := min.Format(layout)
138-
maxStr := max.Format(layout)
137+
minStr := minimum.Format(layout)
138+
maxStr := maximum.Format(layout)
139139

140140
validation := &FieldValidationDate{
141141
Range: &DateMinMax{
142-
Min: min,
143-
Max: max,
142+
Min: minimum,
143+
Max: maximum,
144144
},
145145
ErrorMessage: "error message",
146146
}

content_type_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -756,10 +756,10 @@ func TestContentTypeFieldTypeMedia(t *testing.T) {
756756
// size validation
757757
validationSize := validations[2].(map[string]interface{})
758758
sizeData := validationSize["assetFileSize"].(map[string]interface{})
759-
min := int(sizeData["min"].(float64))
760-
max := int(sizeData["max"].(float64))
761-
assert.Equal(t, 30, min)
762-
assert.Equal(t, 400, max)
759+
minimum := int(sizeData["min"].(float64))
760+
maximum := int(sizeData["max"].(float64))
761+
assert.Equal(t, 30, minimum)
762+
assert.Equal(t, 400, maximum)
763763

764764
w.WriteHeader(http.StatusCreated)
765765
_, _ = fmt.Fprintln(w, readTestData(t, "content_type.json"))

contentful.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ import (
99
"net/http"
1010
"net/http/httputil"
1111
"net/url"
12+
"path"
1213
"strconv"
14+
"strings"
1315
"time"
1416

1517
"github.com/aoliveti/curling"
@@ -24,6 +26,7 @@ type Contentful struct {
2426
QueryParams map[string]string
2527
Headers map[string]string
2628
BaseURL string
29+
UploadURL string
2730
Environment string
2831

2932
Spaces *SpacesService
@@ -33,6 +36,7 @@ type Contentful struct {
3336
Entries *EntriesService
3437
Locales *LocalesService
3538
Tags *TagsService
39+
Upload *UploadService
3640
Webhooks *WebhooksService
3741
}
3842

@@ -59,7 +63,8 @@ func NewCMA(token string) *Contentful {
5963
"Content-Type": "application/vnd.contentful.management.v1+json",
6064
"X-Contentful-User-Agent": fmt.Sprintf("sdk contentful.go/%s", Version),
6165
},
62-
BaseURL: "https://api.contentful.com",
66+
BaseURL: "https://api.contentful.com",
67+
UploadURL: "https://upload.contentful.com",
6368
}
6469

6570
c.Spaces = &SpacesService{c: c}
@@ -68,6 +73,7 @@ func NewCMA(token string) *Contentful {
6873
c.ContentTypes = &ContentTypesService{c: c}
6974
c.Entries = &EntriesService{c: c}
7075
c.Tags = &TagsService{c: c}
76+
c.Upload = &UploadService{c: c}
7177
c.Locales = &LocalesService{c: c}
7278
c.Webhooks = &WebhooksService{c: c}
7379

@@ -153,8 +159,20 @@ func (c *Contentful) SetBaseURL(baseURL string) *Contentful {
153159
return c
154160
}
155161

156-
func (c *Contentful) newRequest(ctx context.Context, method, path string, query url.Values, body io.Reader) (*http.Request, error) {
157-
u, err := url.Parse(c.BaseURL)
162+
func (c *Contentful) newRequest(ctx context.Context, method, requestPath string, query url.Values, body io.Reader, additionalHeaders map[string]string) (*http.Request, error) {
163+
if idx := strings.Index(requestPath, "?"); idx != -1 {
164+
requestPath = requestPath[:idx]
165+
}
166+
cleanUrl := path.Clean(requestPath)
167+
_, lastSegment := path.Split(cleanUrl)
168+
var u *url.URL
169+
var err error
170+
switch lastSegment {
171+
case "uploads":
172+
u, err = url.Parse(c.UploadURL)
173+
default:
174+
u, err = url.Parse(c.BaseURL)
175+
}
158176
if err != nil {
159177
return nil, err
160178
}
@@ -164,7 +182,7 @@ func (c *Contentful) newRequest(ctx context.Context, method, path string, query
164182
query.Set(key, value)
165183
}
166184

167-
u.Path = u.Path + path
185+
u.Path = u.Path + requestPath
168186
u.RawQuery = query.Encode()
169187

170188
req, err := http.NewRequestWithContext(ctx, method, u.String(), body)
@@ -176,6 +194,9 @@ func (c *Contentful) newRequest(ctx context.Context, method, path string, query
176194
for key, value := range c.Headers {
177195
req.Header.Set(key, value)
178196
}
197+
for key, value := range additionalHeaders {
198+
req.Header.Set(key, value)
199+
}
179200

180201
return req, nil
181202
}

contentful_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ func TestNewRequest(t *testing.T) {
188188
expectedURL.Path = path
189189
expectedURL.RawQuery = query.Encode()
190190

191-
req, err := c.newRequest(context.TODO(), method, path, query, nil)
191+
req, err := c.newRequest(context.TODO(), method, path, query, nil, nil)
192192
require.NoError(t, err)
193193
assert.Equal(t, "Bearer "+CMAToken, req.Header.Get("Authorization"))
194194
assert.Equal(t, "application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type"))
@@ -206,7 +206,7 @@ func TestNewRequest(t *testing.T) {
206206
}
207207
body, err := json.Marshal(bodyData)
208208
require.NoError(t, err)
209-
req, err = c.newRequest(context.TODO(), method, path, query, bytes.NewReader(body))
209+
req, err = c.newRequest(context.TODO(), method, path, query, bytes.NewReader(body), nil)
210210
require.NoError(t, err)
211211
assert.Equal(t, "Bearer "+CMAToken, req.Header.Get("Authorization"))
212212
assert.Equal(t, "application/vnd.contentful.management.v1+json", req.Header.Get("Content-Type"))
@@ -241,7 +241,7 @@ func TestHandleError(t *testing.T) {
241241
errResponseReader := bytes.NewReader(marshaled)
242242
errResponseReadCloser := io.NopCloser(errResponseReader)
243243

244-
req, err := c.newRequest(context.TODO(), method, path, query, nil)
244+
req, err := c.newRequest(context.TODO(), method, path, query, nil, nil)
245245
require.NoError(t, err)
246246
responseHeaders := http.Header{}
247247
responseHeaders.Add("X-Contentful-Request-Id", requestID)

0 commit comments

Comments
 (0)