Skip to content
Snippets Groups Projects

Buffer git-receive-pack responses

Closed username-removed-5302 requested to merge buffer-git-push into master

This allows us to respond with HTTP 500 instead of 200 when a 'git push' is rejected by the server.

Follow-up to https://gitlab.com/gitlab-org/gitlab-workhorse/merge_requests/38

Merge request reports

Loading
Loading

Activity

Filter activity
  • Approvals
  • Assignees & reviewers
  • Comments (from bots)
  • Comments (from users)
  • Commits & branches
  • Edits
  • Labels
  • Lock status
  • Mentions
  • Merge request status
  • Tracking
150 // the error response from gitlab-workhorse will always be HTTP 500
151 // (Internal Server Error).
152 bodyWriter := &bytes.Buffer{} // buffer the entire response in memory
153 defer flushBuffer(w, bodyWriter)
154 }
155
142 156 // Start writing the response
143 157 w.Header().Add("Content-Type", fmt.Sprintf("application/x-%s-result", action))
144 158 w.Header().Add("Cache-Control", "no-cache")
145 w.WriteHeader(200) // Don't bother with HTTP 500 from this point on, just return
146 159
147 160 // This io.Copy may take a long time, both for Git push and pull.
148 if _, err := io.Copy(w, stdout); err != nil {
149 helper.LogError(fmt.Errorf("handlePostRPC copy output of %v: %v", cmd.Args, err))
161 if _, err := io.Copy(bodyWriter, stdout); err != nil {
162 helper.Fail500(w, fmt.Errorf("handlePostRPC copy output of %v: %v", cmd.Args, err))
  • This might be a problem. During a (succesful) long push there is a risk of timeouts already, because it can take a long time before git receive-pack prints any output to stdout. That creates a long 'silence' in the HTTP response which can cause intermediate proxies like HAProxy and NGINX to terminate the request.

    If we buffer the entire response we may be increasing the delay even more.

  • On the other hand I am not sure if this is where we should be solving the 'long silence' problem.

  • Another thing we could do is buffer e.g. the first 8192 bytes of output, regardless of whether it is 'git push' or 'git pull'. Then if the buffer contains less than 8192 bytes, assume the Git command is done already and call Cmd.Wait() so we can still set the HTTP status code to 500 (or some other more appropriate value). If the buffer contains 8192 bytes, assume success (write HTTP 200) and start sending the buffer and the rest of the data.

  • username-removed-5302 mentioned in merge request !42 (merged)

    mentioned in merge request !42 (merged)

  • Closing in favor of !42 (merged) where we buffer the first 8192 bytes; it is more complicated but also more predictable in terms of memory use.

  • mentioned in commit 285f47a7

  • username-removed-5302 Status changed to closed

    Status changed to closed

  • Please register or sign in to reply
    Loading