Commit 825e2afb authored by Jacob Vosmaer's avatar Jacob Vosmaer

Use only one header to send git blobs

parent 0a5bd0fe
...@@ -2,33 +2,60 @@ package git ...@@ -2,33 +2,60 @@ package git
import ( import (
"../helper" "../helper"
"encoding/base64"
"encoding/json"
"fmt" "fmt"
"io" "io"
"log" "log"
"net/http" "net/http"
"strings"
) )
func SendGitBlob(w http.ResponseWriter, r *http.Request, repoPath string, blobId string) { type blobParams struct {
log.Printf("SendGitBlob: sending %q for %q", blobId, r.URL.Path) RepoPath string
BlobId string
}
const SendBlobPrefix = "git-blob:"
func SendBlob(w http.ResponseWriter, r *http.Request, sendData string) {
params, err := unpackSendData(sendData)
if err != nil {
helper.Fail500(w, fmt.Errorf("SendBlob: unpack sendData: %v", err))
return
}
log.Printf("SendBlob: sending %q for %q", params.BlobId, r.URL.Path)
gitShowCmd := gitCommand("", "git", "--git-dir="+repoPath, "show", blobId) gitShowCmd := gitCommand("", "git", "--git-dir="+params.RepoPath, "show", params.BlobId)
stdout, err := gitShowCmd.StdoutPipe() stdout, err := gitShowCmd.StdoutPipe()
if err != nil { if err != nil {
helper.Fail500(w, fmt.Errorf("SendGitBlob: git show stdout: %v", err)) helper.Fail500(w, fmt.Errorf("SendBlob: git show stdout: %v", err))
return return
} }
if err := gitShowCmd.Start(); err != nil { if err := gitShowCmd.Start(); err != nil {
helper.Fail500(w, fmt.Errorf("SendGitBlob: start %v: %v", gitShowCmd, err)) helper.Fail500(w, fmt.Errorf("SendBlob: start %v: %v", gitShowCmd, err))
return return
} }
defer helper.CleanUpProcessGroup(gitShowCmd) defer helper.CleanUpProcessGroup(gitShowCmd)
if _, err := io.Copy(w, stdout); err != nil { if _, err := io.Copy(w, stdout); err != nil {
helper.LogError(fmt.Errorf("SendGitBlob: copy git show stdout: %v", err)) helper.LogError(fmt.Errorf("SendBlob: copy git show stdout: %v", err))
return return
} }
if err := gitShowCmd.Wait(); err != nil { if err := gitShowCmd.Wait(); err != nil {
helper.LogError(fmt.Errorf("SendGitBlob: wait for git show: %v", err)) helper.LogError(fmt.Errorf("SendBlob: wait for git show: %v", err))
return return
} }
} }
func unpackSendData(sendData string) (*blobParams, error) {
jsonBytes, err := base64.URLEncoding.DecodeString(strings.TrimPrefix(sendData, SendBlobPrefix))
if err != nil {
return nil, err
}
result := &blobParams{}
if err := json.Unmarshal([]byte(jsonBytes), result); err != nil {
return nil, err
}
return result, nil
}
...@@ -11,6 +11,7 @@ import ( ...@@ -11,6 +11,7 @@ import (
"../helper" "../helper"
"log" "log"
"net/http" "net/http"
"strings"
) )
type sendFileResponseWriter struct { type sendFileResponseWriter struct {
...@@ -44,6 +45,13 @@ func (s *sendFileResponseWriter) Write(data []byte) (n int, err error) { ...@@ -44,6 +45,13 @@ func (s *sendFileResponseWriter) Write(data []byte) (n int, err error) {
} }
func (s *sendFileResponseWriter) WriteHeader(status int) { func (s *sendFileResponseWriter) WriteHeader(status int) {
// Never pass these headers to the client
defer func() {
s.Header().Del("X-Sendfile")
s.Header().Del("Gitlab-Workhorse-Send-Data")
}()
if s.status != 0 { if s.status != 0 {
return return
} }
...@@ -55,27 +63,21 @@ func (s *sendFileResponseWriter) WriteHeader(status int) { ...@@ -55,27 +63,21 @@ func (s *sendFileResponseWriter) WriteHeader(status int) {
} }
if file := s.Header().Get("X-Sendfile"); file != "" { if file := s.Header().Get("X-Sendfile"); file != "" {
s.Header().Del("X-Sendfile")
// Mark this connection as hijacked // Mark this connection as hijacked
s.hijacked = true s.hijacked = true
// Serve the file // Serve the file
sendFileFromDisk(s.rw, s.req, file) sendFileFromDisk(s.rw, s.req, file)
return return
} else if repoPath := s.Header().Get("Gitlab-Workhorse-Repo-Path"); repoPath != "" { }
if sendData := s.Header().Get("Gitlab-Workhorse-Send-Data"); strings.HasPrefix(sendData, "git-blob:") {
s.hijacked = true s.hijacked = true
git.SendBlob(s.rw, s.req, sendData)
s.Header().Del("Gitlab-Workhorse-Repo-Path")
sendBlob := s.Header().Get("Gitlab-Workhorse-Send-Blob")
s.Header().Del("Gitlab-Workhorse-Send-Blob")
git.SendGitBlob(s.rw, s.req, repoPath, sendBlob)
return return
} else { }
s.rw.WriteHeader(s.status) s.rw.WriteHeader(s.status)
return return
}
} }
func sendFileFromDisk(w http.ResponseWriter, r *http.Request, file string) { func sendFileFromDisk(w http.ResponseWriter, r *http.Request, file string) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment