From 844f9a4bd8c5c35a9dab598442b4b3d58153f026 Mon Sep 17 00:00:00 2001 From: Marat Radchenko Date: Sat, 25 May 2019 00:21:00 +0300 Subject: [PATCH] Fix /verify LFS handler expecting wrong content-type (#7015) Fixes #6960 According to [spec][1], /verify requests must have `Accept: application/vnd.git-lfs+json` Previous code works because `git-lfs` also [violates spec and doesn't send any Accept header at all][2] For other clients that DO set `Accept: application/vnd.git-lfs+json`, addition of `Accept: application/vnd.git-lfs` either forces them to violate the spec or is ignored, depending on order in what they create header list. [1]: https://github.com/git-lfs/git-lfs/blob/master/docs/api/basic-transfers.md#verification [2]: https://github.com/git-lfs/git-lfs/issues/3662 --- modules/lfs/server.go | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/modules/lfs/server.go b/modules/lfs/server.go index 8ae632684..7e20aa851 100644 --- a/modules/lfs/server.go +++ b/modules/lfs/server.go @@ -22,8 +22,7 @@ import ( ) const ( - contentMediaType = "application/vnd.git-lfs" - metaMediaType = contentMediaType + "+json" + metaMediaType = "application/vnd.git-lfs+json" ) // RequestVars contain variables from the HTTP request. Variables from routing, json body decoding, and @@ -101,11 +100,10 @@ func ObjectOidHandler(ctx *context.Context) { getMetaHandler(ctx) return } - if ContentMatcher(ctx.Req) || len(ctx.Params("filename")) > 0 { - getContentHandler(ctx) - return - } - } else if ctx.Req.Method == "PUT" && ContentMatcher(ctx.Req) { + + getContentHandler(ctx) + return + } else if ctx.Req.Method == "PUT" { PutHandler(ctx) return } @@ -348,7 +346,7 @@ func VerifyHandler(ctx *context.Context) { return } - if !ContentMatcher(ctx.Req) { + if !MetaMatcher(ctx.Req) { writeStatus(ctx, 400) return } @@ -385,7 +383,6 @@ func Represent(rv *RequestVars, meta *models.LFSMetaObject, download, upload boo } header := make(map[string]string) - header["Accept"] = contentMediaType if rv.Authorization == "" { //https://github.com/github/git-lfs/issues/1088 @@ -404,20 +401,20 @@ func Represent(rv *RequestVars, meta *models.LFSMetaObject, download, upload boo if upload && !download { // Force client side verify action while gitea lacks proper server side verification - rep.Actions["verify"] = &link{Href: rv.VerifyLink(), Header: header} + verifyHeader := make(map[string]string) + for k, v := range header { + verifyHeader[k] = v + } + + // This is only needed to workaround https://github.com/git-lfs/git-lfs/issues/3662 + verifyHeader["Accept"] = metaMediaType + + rep.Actions["verify"] = &link{Href: rv.VerifyLink(), Header: verifyHeader} } return rep } -// ContentMatcher provides a mux.MatcherFunc that only allows requests that contain -// an Accept header with the contentMediaType -func ContentMatcher(r macaron.Request) bool { - mediaParts := strings.Split(r.Header.Get("Accept"), ";") - mt := mediaParts[0] - return mt == contentMediaType -} - // MetaMatcher provides a mux.MatcherFunc that only allows requests that contain // an Accept header with the metaMediaType func MetaMatcher(r macaron.Request) bool {