aboutsummaryrefslogtreecommitdiff
path: root/forged/internal
diff options
context:
space:
mode:
authorRunxi Yu <me@runxiyu.org>2025-08-10 05:43:39 +0800
committerRunxi Yu <me@runxiyu.org>2025-08-10 06:02:11 +0800
commitae860272f340125cc34d18e8adbceb379737b76d (patch)
tree1bff4619ce9a8287b6eb1f80492aac7e77e71278 /forged/internal
parenthttp upload pack: Attempt to fix deadlock (diff)
downloadforge-ae860272f340125cc34d18e8adbceb379737b76d.tar.gz
forge-ae860272f340125cc34d18e8adbceb379737b76d.tar.zst
forge-ae860272f340125cc34d18e8adbceb379737b76d.zip
http upload pack: Decode compressed bodiesHEADv0.1.55master
Diffstat (limited to 'forged/internal')
-rw-r--r--forged/internal/unsorted/http_handle_repo_upload_pack.go47
1 files changed, 42 insertions, 5 deletions
diff --git a/forged/internal/unsorted/http_handle_repo_upload_pack.go b/forged/internal/unsorted/http_handle_repo_upload_pack.go
index 62547d8..914c9cc 100644
--- a/forged/internal/unsorted/http_handle_repo_upload_pack.go
+++ b/forged/internal/unsorted/http_handle_repo_upload_pack.go
@@ -5,10 +5,15 @@ package unsorted
import (
"bytes"
+ "compress/gzip"
+ "compress/zlib"
+ "fmt"
+ "io"
"log"
"net/http"
"os"
"os/exec"
+ "strings"
"github.com/jackc/pgx/v5/pgtype"
)
@@ -16,6 +21,18 @@ import (
// httpHandleUploadPack handles incoming Git fetch/pull/clone's over the Smart
// HTTP protocol.
func (s *Server) httpHandleUploadPack(writer http.ResponseWriter, request *http.Request, params map[string]any) (err error) {
+ if ct := request.Header.Get("Content-Type"); !strings.HasPrefix(ct, "application/x-git-upload-pack-request") {
+ http.Error(writer, "bad content-type", http.StatusUnsupportedMediaType)
+ return nil
+ }
+
+ decoded, err := decodeBody(request)
+ if err != nil {
+ http.Error(writer, "cannot decode request body", http.StatusBadRequest)
+ return err
+ }
+ defer decoded.Close()
+
var groupPath []string
var repoName string
var repoPath string
@@ -61,18 +78,21 @@ func (s *Server) httpHandleUploadPack(writer http.ResponseWriter, request *http.
}
writer.Header().Set("Content-Type", "application/x-git-upload-pack-result")
- writer.Header().Set("Connection", "Keep-Alive")
- writer.Header().Set("Transfer-Encoding", "chunked")
- writer.WriteHeader(http.StatusOK)
+ // writer.Header().Set("Connection", "Keep-Alive")
+ // writer.Header().Set("Transfer-Encoding", "chunked")
- cmd = exec.Command("git", "upload-pack", "--stateless-rpc", repoPath)
+ cmd = exec.CommandContext(request.Context(), "git", "upload-pack", "--stateless-rpc", repoPath)
cmd.Env = append(os.Environ(), "LINDENII_FORGE_HOOKS_SOCKET_PATH="+s.config.Hooks.Socket)
var stderrBuf bytes.Buffer
cmd.Stderr = &stderrBuf
cmd.Stdout = writer
- cmd.Stdin = request.Body
+ cmd.Stdin = decoded
+
+ if gp := request.Header.Get("Git-Protocol"); gp != "" {
+ cmd.Env = append(cmd.Env, "GIT_PROTOCOL="+gp)
+ }
if err = cmd.Run(); err != nil {
log.Println(stderrBuf.String())
@@ -81,3 +101,20 @@ func (s *Server) httpHandleUploadPack(writer http.ResponseWriter, request *http.
return nil
}
+
+func decodeBody(r *http.Request) (io.ReadCloser, error) {
+ switch ce := strings.ToLower(strings.TrimSpace(r.Header.Get("Content-Encoding"))); ce {
+ case "", "identity":
+ return r.Body, nil
+ case "gzip":
+ zr, err := gzip.NewReader(r.Body)
+ if err != nil { return nil, err }
+ return zr, nil
+ case "deflate":
+ zr, err := zlib.NewReader(r.Body)
+ if err != nil { return nil, err }
+ return zr, nil
+ default:
+ return nil, fmt.Errorf("unsupported Content-Encoding: %q", ce)
+ }
+}