@@ -45,13 +45,13 @@ func (rc *requestContext) ObjectLink(oid string) string {
45
45
}
46
46
47
47
// VerifyLink builds a URL for verifying the object.
48
- func (rc * requestContext ) VerifyLink (oid string ) string {
49
- return setting .AppURL + path .Join (rc .User , rc .Repo + ".git" , "info/lfs/verify" , oid )
48
+ func (rc * requestContext ) VerifyLink () string {
49
+ return setting .AppURL + path .Join (rc .User , rc .Repo + ".git" , "info/lfs/verify" )
50
50
}
51
51
52
52
// CheckAcceptMediaType checks if the client accepts the LFS media type.
53
53
func CheckAcceptMediaType (ctx * context.Context ) {
54
- mediaParts := strings .Split (r .Header .Get ("Accept" ), ";" )
54
+ mediaParts := strings .Split (ctx . Req .Header .Get ("Accept" ), ";" )
55
55
56
56
if mediaParts [0 ] != lfs_module .MediaType {
57
57
log .Info ("Calling a LFS method without accepting the correct media type: %s" , lfs_module .MediaType )
@@ -95,7 +95,6 @@ func DownloadHandler(ctx *context.Context) {
95
95
96
96
meta , _ := getAuthenticatedRepoAndMeta (ctx , rc , p , false )
97
97
if meta == nil {
98
- // Status already written in getAuthenticatedRepoAndMeta
99
98
return
100
99
}
101
100
@@ -130,7 +129,6 @@ func DownloadHandler(ctx *context.Context) {
130
129
contentStore := lfs_module .NewContentStore ()
131
130
content , err := contentStore .Get (meta .Pointer )
132
131
if err != nil {
133
- // Errors are logged in contentStore.Get
134
132
writeStatus (ctx , http .StatusNotFound )
135
133
return
136
134
}
@@ -163,34 +161,38 @@ func DownloadHandler(ctx *context.Context) {
163
161
if written , err := io .CopyN (ctx .Resp , content , contentLength ); err != nil {
164
162
log .Error ("Error whilst copying LFS OID[%s] to the response after %d bytes. Error: %v" , meta .Oid , written , err )
165
163
}
166
- logRequest (ctx .Req , statusCode )
167
164
}
168
165
169
166
// BatchHandler provides the batch api
170
167
func BatchHandler (ctx * context.Context ) {
171
- bv := unpackbatch (ctx )
168
+ var br lfs_module.BatchRequest
169
+ if err := decodeJSON (ctx .Req , & br ); err != nil {
170
+ log .Trace ("Unable to decode BATCH request vars: Error: %v" , err )
171
+ writeStatus (ctx , http .StatusBadRequest )
172
+ return
173
+ }
172
174
173
175
var isUpload bool
174
- if bv .Operation == "upload" {
176
+ if br .Operation == "upload" {
175
177
isUpload = true
176
- } else if bv .Operation == "download" {
178
+ } else if br .Operation == "download" {
177
179
isUpload = false
178
180
} else {
179
- log .Info ("Attempt to BATCH with invalid operation: %s" , bv .Operation )
181
+ log .Trace ("Attempt to BATCH with invalid operation: %s" , br .Operation )
180
182
writeStatus (ctx , http .StatusBadRequest )
181
183
return
182
184
}
183
185
184
- reqCtx := getRequestContext (ctx )
186
+ rc := getRequestContext (ctx )
185
187
186
- repository , err := models .GetRepositoryByOwnerAndName (reqCtx .User , reqCtx .Repo )
188
+ repository , err := models .GetRepositoryByOwnerAndName (rc .User , rc .Repo )
187
189
if err != nil {
188
- log .Error ("Unable to get repository: %s/%s Error: %v" , reqCtx .User , reqCtx .Repo , err )
190
+ log .Trace ("Unable to get repository: %s/%s Error: %v" , rc .User , rc .Repo , err )
189
191
writeStatus (ctx , http .StatusNotFound )
190
192
return
191
193
}
192
194
193
- if ! authenticate (ctx , repository , reqCtx .Authorization , isUpload ) {
195
+ if ! authenticate (ctx , repository , rc .Authorization , isUpload ) {
194
196
requireAuth (ctx )
195
197
return
196
198
}
@@ -199,30 +201,30 @@ func BatchHandler(ctx *context.Context) {
199
201
200
202
var responseObjects []* lfs_module.ObjectResponse
201
203
202
- for _ , p := range bv .Objects {
203
- if ! object .IsValid () {
204
- responseObjects = append (responseObjects , buildObjectResponse (reqCtx , p , false , false , http .StatusUnprocessableEntity ))
204
+ for _ , p := range br .Objects {
205
+ if ! p .IsValid () {
206
+ responseObjects = append (responseObjects , buildObjectResponse (rc , p , false , false , http .StatusUnprocessableEntity ))
205
207
continue
206
208
}
207
209
208
210
exists , err := contentStore .Exists (p )
209
211
if err != nil {
210
- log .Error ("Unable to check if LFS OID[%s] exist on %s/%s. Error: %v" , p .Oid , reqCtx .User , reqCtx .Repo , err )
212
+ log .Error ("Unable to check if LFS OID[%s] exist on %s/%s. Error: %v" , p .Oid , rc .User , rc .Repo , err )
211
213
writeStatus (ctx , http .StatusInternalServerError )
212
214
return
213
215
}
214
216
215
217
meta , metaErr := repository .GetLFSMetaObjectByOid (p .Oid )
216
218
if metaErr != nil && metaErr != models .ErrLFSObjectNotExist {
217
- log .Error ("Unable to get LFS MetaObject [%s] for %s/%s. Error: %v" , p .Oid , reqCtx .User , reqCtx .Repo , metaErr )
219
+ log .Error ("Unable to get LFS MetaObject [%s] for %s/%s. Error: %v" , p .Oid , rc .User , rc .Repo , metaErr )
218
220
writeStatus (ctx , http .StatusInternalServerError )
219
221
return
220
222
}
221
223
222
224
var responseObject * lfs_module.ObjectResponse
223
225
if isUpload {
224
- if ! exists && setting .LFS .MaxFileSize > 0 && object .Size > setting .LFS .MaxFileSize {
225
- log .Info ("Denied LFS OID[%s] upload of size %d to %s/%s because of LFS_MAX_FILE_SIZE=%d" , p .Oid , p .Size , reqCtx .User , reqCtx .Repo , setting .LFS .MaxFileSize )
226
+ if ! exists && setting .LFS .MaxFileSize > 0 && p .Size > setting .LFS .MaxFileSize {
227
+ log .Info ("Denied LFS OID[%s] upload of size %d to %s/%s because of LFS_MAX_FILE_SIZE=%d" , p .Oid , p .Size , rc .User , rc .Repo , setting .LFS .MaxFileSize )
226
228
writeStatus (ctx , http .StatusRequestEntityTooLarge )
227
229
return
228
230
}
@@ -231,14 +233,14 @@ func BatchHandler(ctx *context.Context) {
231
233
if meta == nil {
232
234
_ , err := models .NewLFSMetaObject (& models.LFSMetaObject {Pointer : p , RepositoryID : repository .ID })
233
235
if err != nil {
234
- log .Error ("Unable to create LFS MetaObject [%s] for %s/%s. Error: %v" , p .Oid , reqCtx .User , reqCtx .Repo , metaErr )
236
+ log .Error ("Unable to create LFS MetaObject [%s] for %s/%s. Error: %v" , p .Oid , rc .User , rc .Repo , metaErr )
235
237
writeStatus (ctx , http .StatusInternalServerError )
236
238
return
237
239
}
238
240
}
239
241
}
240
242
241
- responseObject = buildObjectResponse (reqCtx , p , false , ! exists , 0 )
243
+ responseObject = buildObjectResponse (rc , p , false , ! exists , 0 )
242
244
} else {
243
245
errorCode := 0
244
246
if ! exists || meta == nil {
@@ -247,7 +249,7 @@ func BatchHandler(ctx *context.Context) {
247
249
errorCode = http .StatusUnprocessableEntity
248
250
}
249
251
250
- responseObject = buildObjectResponse (reqCtx , p , true , false , errorCode )
252
+ responseObject = buildObjectResponse (rc , p , true , false , errorCode )
251
253
}
252
254
responseObjects = append (responseObjects , responseObject )
253
255
}
@@ -261,7 +263,6 @@ func BatchHandler(ctx *context.Context) {
261
263
if err := enc .Encode (respobj ); err != nil {
262
264
log .Error ("Failed to encode representation as json. Error: %v" , err )
263
265
}
264
- logRequest (ctx .Req , http .StatusOK )
265
266
}
266
267
267
268
// UploadHandler receives data from the client and puts it into the content store
@@ -270,32 +271,33 @@ func UploadHandler(ctx *context.Context) {
270
271
271
272
meta , repository := getAuthenticatedRepoAndMeta (ctx , rc , p , true )
272
273
if meta == nil {
273
- // Status already written in getAuthenticatedRepoAndMeta
274
274
return
275
275
}
276
276
277
277
contentStore := lfs_module .NewContentStore ()
278
278
defer ctx .Req .Body .Close ()
279
279
if err := contentStore .Put (meta .Pointer , ctx .Req .Body ); err != nil {
280
- // Put will log the error itself
281
- ctx .Resp .WriteHeader (http .StatusInternalServerError )
282
280
if err == lfs_module .ErrSizeMismatch || err == lfs_module .ErrHashMismatch {
283
- fmt . Fprintf (ctx . Resp , `{"message":"%s"}` , err )
281
+ writeStatusMessage (ctx , http . StatusInternalServerError , err )
284
282
} else {
285
- fmt . Fprintf (ctx . Resp , `{"message":"Internal Server Error"}` )
283
+ writeStatus (ctx , http . StatusInternalServerError )
286
284
}
287
285
if _ , err = repository .RemoveLFSMetaObjectByOid (p .Oid ); err != nil {
288
- log .Error ("Whilst removing metaobject for LFS OID[%s] due to preceding error there was another Error : %v" , p .Oid , err )
286
+ log .Error ("Error whilst removing metaobject for LFS OID[%s]: %v" , p .Oid , err )
289
287
}
290
288
return
291
289
}
292
-
293
- logRequest (ctx .Req , http .StatusOK )
294
290
}
295
291
296
292
// VerifyHandler verify oid and its size from the content store
297
293
func VerifyHandler (ctx * context.Context ) {
298
- rc , p := unpack (ctx )
294
+ var p lfs_module.Pointer
295
+ if err := decodeJSON (ctx .Req , & p ); err != nil {
296
+ writeStatus (ctx , http .StatusUnprocessableEntity )
297
+ return
298
+ }
299
+
300
+ rc := getRequestContext (ctx )
299
301
300
302
meta , _ := getAuthenticatedRepoAndMeta (ctx , rc , p , true )
301
303
if meta == nil {
@@ -304,20 +306,25 @@ func VerifyHandler(ctx *context.Context) {
304
306
305
307
contentStore := lfs_module .NewContentStore ()
306
308
ok , err := contentStore .Verify (meta .Pointer )
307
- if err != nil {
308
- // Error will be logged in Verify
309
- ctx .Resp .WriteHeader (http .StatusInternalServerError )
310
- fmt .Fprintf (ctx .Resp , `{"message":"Internal Server Error"}` )
311
- return
312
- }
313
309
314
310
status := http .StatusOK
315
- if ! ok {
311
+ if err != nil {
312
+ status = http .StatusInternalServerError
313
+ } else if ! ok {
316
314
status = http .StatusUnprocessableEntity
317
315
}
318
316
writeStatus (ctx , status )
319
317
}
320
318
319
+ func decodeJSON (req * http.Request , v interface {}) error {
320
+ json := jsoniter .ConfigCompatibleWithStandardLibrary
321
+
322
+ defer req .Body .Close ()
323
+
324
+ dec := json .NewDecoder (req .Body )
325
+ return dec .Decode (v )
326
+ }
327
+
321
328
func getRequestContext (ctx * context.Context ) * requestContext {
322
329
return & requestContext {
323
330
User : ctx .Params ("username" ),
@@ -349,7 +356,7 @@ func buildObjectResponse(rc *requestContext, pointer lfs_module.Pointer, downloa
349
356
}
350
357
if upload {
351
358
rep .Actions ["upload" ] = & lfs_module.Link {Href : rc .ObjectLink (pointer .Oid ), Header : header }
352
- rep .Actions ["verify" ] = & lfs_module.Link {Href : rc .VerifyLink (pointer . Oid ), Header : verifyHeader }
359
+ rep .Actions ["verify" ] = & lfs_module.Link {Href : rc .VerifyLink (), Header : verifyHeader }
353
360
}
354
361
}
355
362
return rep
@@ -359,62 +366,16 @@ func unpack(ctx *context.Context) (*requestContext, lfs_module.Pointer) {
359
366
rc := getRequestContext (ctx )
360
367
p := lfs_module.Pointer {Oid : ctx .Params ("oid" )}
361
368
362
- if ctx .Req .Method == "POST" { // Maybe also check if +json
363
- var p2 lfs_module.Pointer
364
- bodyReader := ctx .Req .Body
365
- defer bodyReader .Close ()
366
- json := jsoniter .ConfigCompatibleWithStandardLibrary
367
- dec := json .NewDecoder (bodyReader )
368
- err := dec .Decode (& p2 )
369
- if err != nil {
370
- // The error is logged as a WARN here because this may represent misbehaviour rather than a true error
371
- log .Warn ("Unable to decode POST request vars for LFS OID[%s] in %s/%s: Error: %v" , p .Oid , rc .User , rc .Repo , err )
372
- return rc , p
373
- }
374
-
375
- p .Oid = p2 .Oid
376
- p .Size = p2 .Size
377
- }
378
-
379
369
return rc , p
380
370
}
381
371
382
- // TODO cheap hack, unify with unpack
383
- func unpackbatch (ctx * context.Context ) * lfs_module.BatchRequest {
384
-
385
- r := ctx .Req
386
- var bv lfs_module.BatchRequest
387
-
388
- bodyReader := r .Body
389
- defer bodyReader .Close ()
390
- json := jsoniter .ConfigCompatibleWithStandardLibrary
391
- dec := json .NewDecoder (bodyReader )
392
- err := dec .Decode (& bv )
393
- if err != nil {
394
- // The error is logged as a WARN here because this may represent misbehaviour rather than a true error
395
- log .Warn ("Unable to decode BATCH request vars in %s/%s: Error: %v" , ctx .Params ("username" ), strings .TrimSuffix (ctx .Params ("reponame" ), ".git" ), err )
396
- return & bv
397
- }
398
-
399
- return & bv
400
- }
401
-
402
372
func writeStatus (ctx * context.Context , status int ) {
403
- message := http .StatusText (status )
404
-
405
- mediaParts := strings .Split (ctx .Req .Header .Get ("Accept" ), ";" )
406
- mt := mediaParts [0 ]
407
- if strings .HasSuffix (mt , "+json" ) {
408
- message = `{"message":"` + message + `"}`
409
- }
410
-
411
- ctx .Resp .WriteHeader (status )
412
- fmt .Fprint (ctx .Resp , message )
413
- logRequest (ctx .Req , status )
373
+ writeStatusMessage (ctx , status , http .StatusText (status ))
414
374
}
415
375
416
- func logRequest (r * http.Request , status int ) {
417
- log .Debug ("LFS request - Method: %s, URL: %s, Status %d" , r .Method , r .URL , status )
376
+ func writeStatusMessage (ctx * context.Context , status int , message interface {}) {
377
+ ctx .Resp .WriteHeader (status )
378
+ fmt .Fprintf (ctx .Resp , `{"message":"%v"}` , message )
418
379
}
419
380
420
381
// authenticate uses the authorization string to determine whether
0 commit comments