@@ -14,36 +14,21 @@ import (
14
14
"net/http"
15
15
"os"
16
16
"path/filepath"
17
+ "strings"
17
18
)
18
19
19
20
const (
20
- gitMediaType = "application/vnd.git-media"
21
- gitMediaMetaType = gitMediaType + "+json; charset=utf-8"
22
- )
23
-
24
- type linkMeta struct {
25
- Links map [string ]* link `json:"_links,omitempty"`
26
- }
27
-
28
- func (l * linkMeta ) Rel (name string ) (* link , bool ) {
29
- if l .Links == nil {
30
- return nil , false
31
- }
21
+ // Legacy type
22
+ gitMediaType = "application/vnd.git-media"
32
23
33
- lnk , ok := l .Links [name ]
34
- return lnk , ok
35
- }
36
-
37
- type link struct {
38
- Href string `json:"href"`
39
- Header map [string ]string `json:"header,omitempty"`
40
- }
24
+ // The main type, sub type, and suffix. Use this when ensuring the type from
25
+ // an HTTP response is correct.
26
+ gitMediaMetaTypePrefix = gitMediaType + "+json"
41
27
42
- type UploadRequest struct {
43
- OidPath string
44
- Filename string
45
- CopyCallback CopyCallback
46
- }
28
+ // Adds the extra mime params. Use this when sending the type in an HTTP
29
+ // request.
30
+ gitMediaMetaType = gitMediaMetaTypePrefix + "; charset=utf-8"
31
+ )
47
32
48
33
func Download (oidPath string ) (io.ReadCloser , int64 , * WrappedError ) {
49
34
oid := filepath .Base (oidPath )
@@ -66,6 +51,47 @@ func Download(oidPath string) (io.ReadCloser, int64, *WrappedError) {
66
51
return nil , 0 , wErr
67
52
}
68
53
54
+ if strings .HasPrefix (contentType , gitMediaMetaTypePrefix ) {
55
+ obj := & objectResource {}
56
+ err := json .NewDecoder (res .Body ).Decode (obj )
57
+ res .Body .Close ()
58
+ if err != nil {
59
+ wErr := Error (err )
60
+ setErrorResponseContext (wErr , res )
61
+ return nil , 0 , wErr
62
+ }
63
+
64
+ dlReq , err := obj .NewRequest ("download" , "GET" )
65
+ if err != nil {
66
+ wErr := Error (err )
67
+ setErrorResponseContext (wErr , res )
68
+ return nil , 0 , wErr
69
+ }
70
+
71
+ dlCreds , err := setRequestHeaders (dlReq )
72
+ if err != nil {
73
+ return nil , 0 , Errorf (err , "Error attempting to GET %s" , oidPath )
74
+ }
75
+
76
+ dlRes , err := DoHTTP (Config , dlReq )
77
+ if err != nil {
78
+ wErr := Error (err )
79
+ setErrorResponseContext (wErr , res )
80
+ return nil , 0 , wErr
81
+ }
82
+
83
+ saveCredentials (dlCreds , dlRes )
84
+
85
+ contentType := dlRes .Header .Get ("Content-Type" )
86
+ if contentType == "" {
87
+ wErr = Error (errors .New ("Empty Content-Type" ))
88
+ setErrorResponseContext (wErr , res )
89
+ return nil , 0 , wErr
90
+ }
91
+
92
+ res = dlRes
93
+ }
94
+
69
95
ok , headerSize , wErr := validateMediaHeader (contentType , res .Body )
70
96
if ! ok {
71
97
setErrorResponseContext (wErr , res )
@@ -111,6 +137,46 @@ func Upload(oidPath, filename string, cb CopyCallback) *WrappedError {
111
137
return nil
112
138
}
113
139
140
+ type objectResource struct {
141
+ Oid string `json:"oid,omitempty"`
142
+ Size int64 `json:"size,omitempty"`
143
+ Links map [string ]* linkRelation `json:"_links,omitempty"`
144
+ }
145
+
146
+ var objectRelationDoesNotExist = errors .New ("relation does not exist" )
147
+
148
+ func (o * objectResource ) NewRequest (relation , method string ) (* http.Request , error ) {
149
+ rel , ok := o .Rel (relation )
150
+ if ! ok {
151
+ return nil , objectRelationDoesNotExist
152
+ }
153
+
154
+ req , err := http .NewRequest (method , rel .Href , nil )
155
+ if err != nil {
156
+ return nil , err
157
+ }
158
+
159
+ for h , v := range rel .Header {
160
+ req .Header .Set (h , v )
161
+ }
162
+
163
+ return req , nil
164
+ }
165
+
166
+ func (o * objectResource ) Rel (name string ) (* linkRelation , bool ) {
167
+ if o .Links == nil {
168
+ return nil , false
169
+ }
170
+
171
+ rel , ok := o .Links [name ]
172
+ return rel , ok
173
+ }
174
+
175
+ type linkRelation struct {
176
+ Href string `json:"href"`
177
+ Header map [string ]string `json:"header,omitempty"`
178
+ }
179
+
114
180
func callOptions (filehash string ) (int , * WrappedError ) {
115
181
oid := filepath .Base (filehash )
116
182
_ , err := os .Stat (filehash )
@@ -180,18 +246,22 @@ func callPut(filehash, filename string, cb CopyCallback) *WrappedError {
180
246
return wErr
181
247
}
182
248
183
- func callExternalPut (filehash , filename string , lm * linkMeta , cb CopyCallback ) * WrappedError {
184
- if lm == nil {
249
+ func callExternalPut (filehash , filename string , obj * objectResource , cb CopyCallback ) * WrappedError {
250
+ if obj == nil {
185
251
return Errorf (errors .New ("No hypermedia links provided" ),
186
252
"Error attempting to PUT %s" , filename )
187
253
}
188
254
189
- link , ok := lm . Rel ("upload" )
190
- if ! ok {
255
+ req , err := obj . NewRequest ("upload" , "PUT " )
256
+ if err == objectRelationDoesNotExist {
191
257
return Errorf (errors .New ("No upload link provided" ),
192
258
"Error attempting to PUT %s" , filename )
193
259
}
194
260
261
+ if err != nil {
262
+ return Errorf (err , "Error attempting to PUT %s" , filename )
263
+ }
264
+
195
265
file , err := os .Open (filehash )
196
266
if err != nil {
197
267
return Errorf (err , "Error attempting to PUT %s" , filename )
@@ -209,14 +279,6 @@ func callExternalPut(filehash, filename string, lm *linkMeta, cb CopyCallback) *
209
279
Reader : file ,
210
280
}
211
281
212
- req , err := http .NewRequest ("PUT" , link .Href , nil )
213
- if err != nil {
214
- return Errorf (err , "Error attempting to PUT %s" , filename )
215
- }
216
- for h , v := range link .Header {
217
- req .Header .Set (h , v )
218
- }
219
-
220
282
creds , err := setRequestHeaders (req )
221
283
if err != nil {
222
284
return Errorf (err , "Error attempting to PUT %s" , filename )
@@ -238,39 +300,36 @@ func callExternalPut(filehash, filename string, lm *linkMeta, cb CopyCallback) *
238
300
saveCredentials (creds , res )
239
301
240
302
// Run the verify callback
241
- if cb , ok := lm .Rel ("verify" ); ok {
242
- oid := filepath .Base (filehash )
243
-
244
- verifyReq , err := http .NewRequest ("POST" , cb .Href , nil )
245
- if err != nil {
246
- return Errorf (err , "Error attempting to verify %s" , filename )
247
- }
303
+ verifyReq , err := obj .NewRequest ("verify" , "POST" )
304
+ if err == objectRelationDoesNotExist {
305
+ return nil
306
+ }
248
307
249
- for h , v := range cb . Header {
250
- verifyReq . Header . Set ( h , v )
251
- }
308
+ if err != nil {
309
+ return Errorf ( err , "Error attempting to verify %s" , filename )
310
+ }
252
311
253
- verifyCreds , err := setRequestHeaders (verifyReq )
254
- if err != nil {
255
- return Errorf (err , "Error attempting to verify %s" , filename )
256
- }
312
+ verifyCreds , err := setRequestHeaders (verifyReq )
313
+ if err != nil {
314
+ return Errorf (err , "Error attempting to verify %s" , filename )
315
+ }
257
316
258
- d := fmt .Sprintf (`{"oid":"%s", "size":%d}` , oid , fileSize )
259
- verifyReq .Body = ioutil .NopCloser (bytes .NewBufferString (d ))
317
+ oid := filepath .Base (filehash )
318
+ d := fmt .Sprintf (`{"oid":"%s", "size":%d}` , oid , fileSize )
319
+ verifyReq .Body = ioutil .NopCloser (bytes .NewBufferString (d ))
260
320
261
- tracerx .Printf ("verify: %s %s" , oid , cb .Href )
262
- verifyRes , err := DoHTTP (Config , verifyReq )
263
- if err != nil {
264
- return Errorf (err , "Error attempting to verify %s" , filename )
265
- }
266
- tracerx .Printf ("verify_status: %d" , verifyRes .StatusCode )
267
- saveCredentials (verifyCreds , verifyRes )
321
+ tracerx .Printf ("verify: %s %s" , oid , verifyReq .URL .String ())
322
+ verifyRes , err := DoHTTP (Config , verifyReq )
323
+ if err != nil {
324
+ return Errorf (err , "Error attempting to verify %s" , filename )
268
325
}
326
+ tracerx .Printf ("verify_status: %d" , verifyRes .StatusCode )
327
+ saveCredentials (verifyCreds , verifyRes )
269
328
270
329
return nil
271
330
}
272
331
273
- func callPost (filehash , filename string ) (* linkMeta , int , * WrappedError ) {
332
+ func callPost (filehash , filename string ) (* objectResource , int , * WrappedError ) {
274
333
oid := filepath .Base (filehash )
275
334
req , creds , err := request ("POST" , "" )
276
335
if err != nil {
@@ -302,14 +361,13 @@ func callPost(filehash, filename string) (*linkMeta, int, *WrappedError) {
302
361
tracerx .Printf ("api_post_status: %d" , res .StatusCode )
303
362
304
363
if res .StatusCode == 202 {
305
- lm := & linkMeta {}
306
- dec := json .NewDecoder (res .Body )
307
- err := dec .Decode (lm )
364
+ obj := & objectResource {}
365
+ err := json .NewDecoder (res .Body ).Decode (obj )
308
366
if err != nil {
309
367
return nil , res .StatusCode , Errorf (err , "Error decoding JSON from %s %s." , req .Method , req .URL )
310
368
}
311
369
312
- return lm , res .StatusCode , nil
370
+ return obj , res .StatusCode , nil
313
371
}
314
372
315
373
return nil , res .StatusCode , nil
0 commit comments