aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwxiaoguang <wxiaoguang@gmail.com>2025-01-31 19:05:48 +0800
committerGitHub <noreply@github.com>2025-01-31 19:05:48 +0800
commit0e8738b4b6adf33e23d33d794550d2e20a0a0d45 (patch)
treece23be9f55d5635af75d1717a6ebc54721c43b21
parent4f3cc26b4e8dfffedd523bc18a93a04aaf458337 (diff)
downloadgitea-0e8738b4b6adf33e23d33d794550d2e20a0a0d45.tar.gz
gitea-0e8738b4b6adf33e23d33d794550d2e20a0a0d45.zip
Fix SSH LFS memory usage (#33455)
Fix #33448
-rw-r--r--modules/httplib/request.go13
-rw-r--r--modules/lfstransfer/backend/backend.go40
-rw-r--r--modules/lfstransfer/backend/lock.go6
-rw-r--r--modules/lfstransfer/backend/util.go63
-rw-r--r--modules/private/actions.go2
-rw-r--r--modules/private/hook.go10
-rw-r--r--modules/private/internal.go8
-rw-r--r--modules/private/key.go4
-rw-r--r--modules/private/mail.go2
-rw-r--r--modules/private/manager.go22
-rw-r--r--modules/private/restore_repo.go2
-rw-r--r--modules/private/serv.go4
-rw-r--r--services/lfs/server.go4
13 files changed, 77 insertions, 103 deletions
diff --git a/modules/httplib/request.go b/modules/httplib/request.go
index 880d7ad3cb..267e276df3 100644
--- a/modules/httplib/request.go
+++ b/modules/httplib/request.go
@@ -99,10 +99,10 @@ func (r *Request) Param(key, value string) *Request {
return r
}
-// Body adds request raw body.
-// it supports string and []byte.
+// Body adds request raw body. It supports string, []byte and io.Reader as body.
func (r *Request) Body(data any) *Request {
switch t := data.(type) {
+ case nil: // do nothing
case string:
bf := bytes.NewBufferString(t)
r.req.Body = io.NopCloser(bf)
@@ -111,6 +111,12 @@ func (r *Request) Body(data any) *Request {
bf := bytes.NewBuffer(t)
r.req.Body = io.NopCloser(bf)
r.req.ContentLength = int64(len(t))
+ case io.ReadCloser:
+ r.req.Body = t
+ case io.Reader:
+ r.req.Body = io.NopCloser(t)
+ default:
+ panic(fmt.Sprintf("unsupported request body type %T", t))
}
return r
}
@@ -141,7 +147,7 @@ func (r *Request) getResponse() (*http.Response, error) {
}
} else if r.req.Method == "POST" && r.req.Body == nil && len(paramBody) > 0 {
r.Header("Content-Type", "application/x-www-form-urlencoded")
- r.Body(paramBody)
+ r.Body(paramBody) // string
}
var err error
@@ -185,6 +191,7 @@ func (r *Request) getResponse() (*http.Response, error) {
}
// Response executes request client gets response manually.
+// Caller MUST close the response body if no error occurs
func (r *Request) Response() (*http.Response, error) {
return r.getResponse()
}
diff --git a/modules/lfstransfer/backend/backend.go b/modules/lfstransfer/backend/backend.go
index 2b1fe49fda..540932b930 100644
--- a/modules/lfstransfer/backend/backend.go
+++ b/modules/lfstransfer/backend/backend.go
@@ -4,7 +4,6 @@
package backend
import (
- "bytes"
"context"
"encoding/base64"
"fmt"
@@ -29,7 +28,7 @@ var Capabilities = []string{
"locking",
}
-var _ transfer.Backend = &GiteaBackend{}
+var _ transfer.Backend = (*GiteaBackend)(nil)
// GiteaBackend is an adapter between git-lfs-transfer library and Gitea's internal LFS API
type GiteaBackend struct {
@@ -78,17 +77,17 @@ func (g *GiteaBackend) Batch(_ string, pointers []transfer.BatchItem, args trans
headerAccept: mimeGitLFS,
headerContentType: mimeGitLFS,
}
- req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
resp, err := req.Response()
if err != nil {
g.logger.Log("http request error", err)
return nil, err
}
+ defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
g.logger.Log("http statuscode error", resp.StatusCode, statusCodeToErr(resp.StatusCode))
return nil, statusCodeToErr(resp.StatusCode)
}
- defer resp.Body.Close()
respBytes, err := io.ReadAll(resp.Body)
if err != nil {
g.logger.Log("http read error", err)
@@ -158,8 +157,7 @@ func (g *GiteaBackend) Batch(_ string, pointers []transfer.BatchItem, args trans
return pointers, nil
}
-// Download implements transfer.Backend. The returned reader must be closed by the
-// caller.
+// Download implements transfer.Backend. The returned reader must be closed by the caller.
func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser, int64, error) {
idMapStr, exists := args[argID]
if !exists {
@@ -187,25 +185,25 @@ func (g *GiteaBackend) Download(oid string, args transfer.Args) (io.ReadCloser,
headerGiteaInternalAuth: g.internalAuth,
headerAccept: mimeOctetStream,
}
- req := newInternalRequest(g.ctx, url, http.MethodGet, headers, nil)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodGet, headers, nil)
resp, err := req.Response()
if err != nil {
- return nil, 0, err
+ return nil, 0, fmt.Errorf("failed to get response: %w", err)
}
+ // no need to close the body here by "defer resp.Body.Close()", see below
if resp.StatusCode != http.StatusOK {
return nil, 0, statusCodeToErr(resp.StatusCode)
}
- defer resp.Body.Close()
- respBytes, err := io.ReadAll(resp.Body)
+
+ respSize, err := strconv.ParseInt(resp.Header.Get("X-Gitea-LFS-Content-Length"), 10, 64)
if err != nil {
- return nil, 0, err
+ return nil, 0, fmt.Errorf("failed to parse content length: %w", err)
}
- respSize := int64(len(respBytes))
- respBuf := io.NopCloser(bytes.NewBuffer(respBytes))
- return respBuf, respSize, nil
+ // transfer.Backend will check io.Closer interface and close this Body reader
+ return resp.Body, respSize, nil
}
-// StartUpload implements transfer.Backend.
+// Upload implements transfer.Backend.
func (g *GiteaBackend) Upload(oid string, size int64, r io.Reader, args transfer.Args) error {
idMapStr, exists := args[argID]
if !exists {
@@ -234,15 +232,14 @@ func (g *GiteaBackend) Upload(oid string, size int64, r io.Reader, args transfer
headerContentType: mimeOctetStream,
headerContentLength: strconv.FormatInt(size, 10),
}
- reqBytes, err := io.ReadAll(r)
- if err != nil {
- return err
- }
- req := newInternalRequest(g.ctx, url, http.MethodPut, headers, reqBytes)
+
+ req := newInternalRequestLFS(g.ctx, url, http.MethodPut, headers, nil)
+ req.Body(r)
resp, err := req.Response()
if err != nil {
return err
}
+ defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return statusCodeToErr(resp.StatusCode)
}
@@ -284,11 +281,12 @@ func (g *GiteaBackend) Verify(oid string, size int64, args transfer.Args) (trans
headerAccept: mimeGitLFS,
headerContentType: mimeGitLFS,
}
- req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
resp, err := req.Response()
if err != nil {
return transfer.NewStatus(transfer.StatusInternalServerError), err
}
+ defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return transfer.NewStatus(uint32(resp.StatusCode), http.StatusText(resp.StatusCode)), statusCodeToErr(resp.StatusCode)
}
diff --git a/modules/lfstransfer/backend/lock.go b/modules/lfstransfer/backend/lock.go
index f094cce1db..4b45658611 100644
--- a/modules/lfstransfer/backend/lock.go
+++ b/modules/lfstransfer/backend/lock.go
@@ -50,7 +50,7 @@ func (g *giteaLockBackend) Create(path, refname string) (transfer.Lock, error) {
headerAccept: mimeGitLFS,
headerContentType: mimeGitLFS,
}
- req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
resp, err := req.Response()
if err != nil {
g.logger.Log("http request error", err)
@@ -102,7 +102,7 @@ func (g *giteaLockBackend) Unlock(lock transfer.Lock) error {
headerAccept: mimeGitLFS,
headerContentType: mimeGitLFS,
}
- req := newInternalRequest(g.ctx, url, http.MethodPost, headers, bodyBytes)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodPost, headers, bodyBytes)
resp, err := req.Response()
if err != nil {
g.logger.Log("http request error", err)
@@ -185,7 +185,7 @@ func (g *giteaLockBackend) queryLocks(v url.Values) ([]transfer.Lock, string, er
headerAccept: mimeGitLFS,
headerContentType: mimeGitLFS,
}
- req := newInternalRequest(g.ctx, url, http.MethodGet, headers, nil)
+ req := newInternalRequestLFS(g.ctx, url, http.MethodGet, headers, nil)
resp, err := req.Response()
if err != nil {
g.logger.Log("http request error", err)
diff --git a/modules/lfstransfer/backend/util.go b/modules/lfstransfer/backend/util.go
index cffefef375..f322d54257 100644
--- a/modules/lfstransfer/backend/util.go
+++ b/modules/lfstransfer/backend/util.go
@@ -5,15 +5,12 @@ package backend
import (
"context"
- "crypto/tls"
"fmt"
- "net"
+ "io"
"net/http"
- "time"
"code.gitea.io/gitea/modules/httplib"
- "code.gitea.io/gitea/modules/proxyprotocol"
- "code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/private"
"github.com/charmbracelet/git-lfs-transfer/transfer"
)
@@ -89,53 +86,19 @@ func statusCodeToErr(code int) error {
}
}
-func newInternalRequest(ctx context.Context, url, method string, headers map[string]string, body []byte) *httplib.Request {
- req := httplib.NewRequest(url, method).
- SetContext(ctx).
- SetTimeout(10*time.Second, 60*time.Second).
- SetTLSClientConfig(&tls.Config{
- InsecureSkipVerify: true,
- })
-
- if setting.Protocol == setting.HTTPUnix {
- req.SetTransport(&http.Transport{
- DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
- var d net.Dialer
- conn, err := d.DialContext(ctx, "unix", setting.HTTPAddr)
- if err != nil {
- return conn, err
- }
- if setting.LocalUseProxyProtocol {
- if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
- _ = conn.Close()
- return nil, err
- }
- }
- return conn, err
- },
- })
- } else if setting.LocalUseProxyProtocol {
- req.SetTransport(&http.Transport{
- DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
- var d net.Dialer
- conn, err := d.DialContext(ctx, network, address)
- if err != nil {
- return conn, err
- }
- if err = proxyprotocol.WriteLocalHeader(conn); err != nil {
- _ = conn.Close()
- return nil, err
- }
- return conn, err
- },
- })
- }
-
+func newInternalRequestLFS(ctx context.Context, url, method string, headers map[string]string, body any) *httplib.Request {
+ req := private.NewInternalRequest(ctx, url, method)
for k, v := range headers {
req.Header(k, v)
}
-
- req.Body(body)
-
+ switch body := body.(type) {
+ case nil: // do nothing
+ case []byte:
+ req.Body(body) // []byte
+ case io.Reader:
+ req.Body(body) // io.Reader or io.ReadCloser
+ default:
+ panic(fmt.Sprintf("unsupported request body type %T", body))
+ }
return req
}
diff --git a/modules/private/actions.go b/modules/private/actions.go
index 311a283650..e68f2f85b0 100644
--- a/modules/private/actions.go
+++ b/modules/private/actions.go
@@ -17,7 +17,7 @@ type GenerateTokenRequest struct {
func GenerateActionsRunnerToken(ctx context.Context, scope string) (*ResponseText, ResponseExtra) {
reqURL := setting.LocalURL + "api/internal/actions/generate_actions_runner_token"
- req := newInternalRequest(ctx, reqURL, "POST", GenerateTokenRequest{
+ req := newInternalRequestAPI(ctx, reqURL, "POST", GenerateTokenRequest{
Scope: scope,
})
diff --git a/modules/private/hook.go b/modules/private/hook.go
index 745c200619..87d6549f9c 100644
--- a/modules/private/hook.go
+++ b/modules/private/hook.go
@@ -85,7 +85,7 @@ type HookProcReceiveRefResult struct {
// HookPreReceive check whether the provided commits are allowed
func HookPreReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) ResponseExtra {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/pre-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
- req := newInternalRequest(ctx, reqURL, "POST", opts)
+ req := newInternalRequestAPI(ctx, reqURL, "POST", opts)
req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
_, extra := requestJSONResp(req, &ResponseText{})
return extra
@@ -94,7 +94,7 @@ func HookPreReceive(ctx context.Context, ownerName, repoName string, opts HookOp
// HookPostReceive updates services and users
func HookPostReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookPostReceiveResult, ResponseExtra) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/post-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
- req := newInternalRequest(ctx, reqURL, "POST", opts)
+ req := newInternalRequestAPI(ctx, reqURL, "POST", opts)
req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
return requestJSONResp(req, &HookPostReceiveResult{})
}
@@ -103,7 +103,7 @@ func HookPostReceive(ctx context.Context, ownerName, repoName string, opts HookO
func HookProcReceive(ctx context.Context, ownerName, repoName string, opts HookOptions) (*HookProcReceiveResult, ResponseExtra) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/hook/proc-receive/%s/%s", url.PathEscape(ownerName), url.PathEscape(repoName))
- req := newInternalRequest(ctx, reqURL, "POST", opts)
+ req := newInternalRequestAPI(ctx, reqURL, "POST", opts)
req.SetReadWriteTimeout(time.Duration(60+len(opts.OldCommitIDs)) * time.Second)
return requestJSONResp(req, &HookProcReceiveResult{})
}
@@ -115,7 +115,7 @@ func SetDefaultBranch(ctx context.Context, ownerName, repoName, branch string) R
url.PathEscape(repoName),
url.PathEscape(branch),
)
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
_, extra := requestJSONResp(req, &ResponseText{})
return extra
}
@@ -123,7 +123,7 @@ func SetDefaultBranch(ctx context.Context, ownerName, repoName, branch string) R
// SSHLog sends ssh error log response
func SSHLog(ctx context.Context, isErr bool, msg string) error {
reqURL := setting.LocalURL + "api/internal/ssh/log"
- req := newInternalRequest(ctx, reqURL, "POST", &SSHLogOption{IsError: isErr, Message: msg})
+ req := newInternalRequestAPI(ctx, reqURL, "POST", &SSHLogOption{IsError: isErr, Message: msg})
_, extra := requestJSONResp(req, &ResponseText{})
return extra.Error
}
diff --git a/modules/private/internal.go b/modules/private/internal.go
index c7e7773524..3bd4eb06b1 100644
--- a/modules/private/internal.go
+++ b/modules/private/internal.go
@@ -34,7 +34,7 @@ func getClientIP() string {
return strings.Fields(sshConnEnv)[0]
}
-func newInternalRequest(ctx context.Context, url, method string, body ...any) *httplib.Request {
+func NewInternalRequest(ctx context.Context, url, method string) *httplib.Request {
if setting.InternalToken == "" {
log.Fatal(`The INTERNAL_TOKEN setting is missing from the configuration file: %q.
Ensure you are running in the correct environment or set the correct configuration file with -c.`, setting.CustomConf)
@@ -82,13 +82,17 @@ Ensure you are running in the correct environment or set the correct configurati
},
})
}
+ return req
+}
+func newInternalRequestAPI(ctx context.Context, url, method string, body ...any) *httplib.Request {
+ req := NewInternalRequest(ctx, url, method)
if len(body) == 1 {
req.Header("Content-Type", "application/json")
jsonBytes, _ := json.Marshal(body[0])
req.Body(jsonBytes)
} else if len(body) > 1 {
- log.Fatal("Too many arguments for newInternalRequest")
+ log.Fatal("Too many arguments for newInternalRequestAPI")
}
req.SetTimeout(10*time.Second, 60*time.Second)
diff --git a/modules/private/key.go b/modules/private/key.go
index dcd1714856..114683b343 100644
--- a/modules/private/key.go
+++ b/modules/private/key.go
@@ -14,7 +14,7 @@ import (
func UpdatePublicKeyInRepo(ctx context.Context, keyID, repoID int64) error {
// Ask for running deliver hook and test pull request tasks.
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/ssh/%d/update/%d", keyID, repoID)
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
_, extra := requestJSONResp(req, &ResponseText{})
return extra.Error
}
@@ -24,7 +24,7 @@ func UpdatePublicKeyInRepo(ctx context.Context, keyID, repoID int64) error {
func AuthorizedPublicKeyByContent(ctx context.Context, content string) (*ResponseText, ResponseExtra) {
// Ask for running deliver hook and test pull request tasks.
reqURL := setting.LocalURL + "api/internal/ssh/authorized_keys"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
req.Param("content", content)
return requestJSONResp(req, &ResponseText{})
}
diff --git a/modules/private/mail.go b/modules/private/mail.go
index 08de5b7e28..3904e37bea 100644
--- a/modules/private/mail.go
+++ b/modules/private/mail.go
@@ -23,7 +23,7 @@ type Email struct {
func SendEmail(ctx context.Context, subject, message string, to []string) (*ResponseText, ResponseExtra) {
reqURL := setting.LocalURL + "api/internal/mail/send"
- req := newInternalRequest(ctx, reqURL, "POST", Email{
+ req := newInternalRequestAPI(ctx, reqURL, "POST", Email{
Subject: subject,
Message: message,
To: to,
diff --git a/modules/private/manager.go b/modules/private/manager.go
index 6055e553bd..e3d5ad57e0 100644
--- a/modules/private/manager.go
+++ b/modules/private/manager.go
@@ -18,21 +18,21 @@ import (
// Shutdown calls the internal shutdown function
func Shutdown(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/shutdown"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Shutting down")
}
// Restart calls the internal restart function
func Restart(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/restart"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Restarting")
}
// ReloadTemplates calls the internal reload-templates function
func ReloadTemplates(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/reload-templates"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Reloaded")
}
@@ -45,7 +45,7 @@ type FlushOptions struct {
// FlushQueues calls the internal flush-queues function
func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/flush-queues"
- req := newInternalRequest(ctx, reqURL, "POST", FlushOptions{Timeout: timeout, NonBlocking: nonBlocking})
+ req := newInternalRequestAPI(ctx, reqURL, "POST", FlushOptions{Timeout: timeout, NonBlocking: nonBlocking})
if timeout > 0 {
req.SetReadWriteTimeout(timeout + 10*time.Second)
}
@@ -55,28 +55,28 @@ func FlushQueues(ctx context.Context, timeout time.Duration, nonBlocking bool) R
// PauseLogging pauses logging
func PauseLogging(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/pause-logging"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Logging Paused")
}
// ResumeLogging resumes logging
func ResumeLogging(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/resume-logging"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Logging Restarted")
}
// ReleaseReopenLogging releases and reopens logging files
func ReleaseReopenLogging(ctx context.Context) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/release-and-reopen-logging"
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Logging Restarted")
}
// SetLogSQL sets database logging
func SetLogSQL(ctx context.Context, on bool) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/set-log-sql?on=" + strconv.FormatBool(on)
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Log SQL setting set")
}
@@ -91,7 +91,7 @@ type LoggerOptions struct {
// AddLogger adds a logger
func AddLogger(ctx context.Context, logger, writer, mode string, config map[string]any) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/manager/add-logger"
- req := newInternalRequest(ctx, reqURL, "POST", LoggerOptions{
+ req := newInternalRequestAPI(ctx, reqURL, "POST", LoggerOptions{
Logger: logger,
Writer: writer,
Mode: mode,
@@ -103,7 +103,7 @@ func AddLogger(ctx context.Context, logger, writer, mode string, config map[stri
// RemoveLogger removes a logger
func RemoveLogger(ctx context.Context, logger, writer string) ResponseExtra {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/remove-logger/%s/%s", url.PathEscape(logger), url.PathEscape(writer))
- req := newInternalRequest(ctx, reqURL, "POST")
+ req := newInternalRequestAPI(ctx, reqURL, "POST")
return requestJSONClientMsg(req, "Removed")
}
@@ -111,7 +111,7 @@ func RemoveLogger(ctx context.Context, logger, writer string) ResponseExtra {
func Processes(ctx context.Context, out io.Writer, flat, noSystem, stacktraces, json bool, cancel string) ResponseExtra {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/manager/processes?flat=%t&no-system=%t&stacktraces=%t&json=%t&cancel-pid=%s", flat, noSystem, stacktraces, json, url.QueryEscape(cancel))
- req := newInternalRequest(ctx, reqURL, "GET")
+ req := newInternalRequestAPI(ctx, reqURL, "GET")
callback := func(resp *http.Response, extra *ResponseExtra) {
_, extra.Error = io.Copy(out, resp.Body)
}
diff --git a/modules/private/restore_repo.go b/modules/private/restore_repo.go
index 496209d3cb..9c3a008142 100644
--- a/modules/private/restore_repo.go
+++ b/modules/private/restore_repo.go
@@ -24,7 +24,7 @@ type RestoreParams struct {
func RestoreRepo(ctx context.Context, repoDir, ownerName, repoName string, units []string, validation bool) ResponseExtra {
reqURL := setting.LocalURL + "api/internal/restore_repo"
- req := newInternalRequest(ctx, reqURL, "POST", RestoreParams{
+ req := newInternalRequestAPI(ctx, reqURL, "POST", RestoreParams{
RepoDir: repoDir,
OwnerName: ownerName,
RepoName: repoName,
diff --git a/modules/private/serv.go b/modules/private/serv.go
index 480a446954..2ccc6c1129 100644
--- a/modules/private/serv.go
+++ b/modules/private/serv.go
@@ -23,7 +23,7 @@ type KeyAndOwner struct {
// ServNoCommand returns information about the provided key
func ServNoCommand(ctx context.Context, keyID int64) (*asymkey_model.PublicKey, *user_model.User, error) {
reqURL := setting.LocalURL + fmt.Sprintf("api/internal/serv/none/%d", keyID)
- req := newInternalRequest(ctx, reqURL, "GET")
+ req := newInternalRequestAPI(ctx, reqURL, "GET")
keyAndOwner, extra := requestJSONResp(req, &KeyAndOwner{})
if extra.HasError() {
return nil, nil, extra.Error
@@ -58,6 +58,6 @@ func ServCommand(ctx context.Context, keyID int64, ownerName, repoName string, m
reqURL += fmt.Sprintf("&verb=%s", url.QueryEscape(verb))
}
}
- req := newInternalRequest(ctx, reqURL, "GET")
+ req := newInternalRequestAPI(ctx, reqURL, "GET")
return requestJSONResp(req, &ServCommandResults{})
}
diff --git a/services/lfs/server.go b/services/lfs/server.go
index a77623fdc1..c4866edaab 100644
--- a/services/lfs/server.go
+++ b/services/lfs/server.go
@@ -134,7 +134,9 @@ func DownloadHandler(ctx *context.Context) {
}
contentLength := toByte + 1 - fromByte
- ctx.Resp.Header().Set("Content-Length", strconv.FormatInt(contentLength, 10))
+ contentLengthStr := strconv.FormatInt(contentLength, 10)
+ ctx.Resp.Header().Set("Content-Length", contentLengthStr)
+ ctx.Resp.Header().Set("X-Gitea-LFS-Content-Length", contentLengthStr) // we need this header to make sure it won't be affected by reverse proxy or compression
ctx.Resp.Header().Set("Content-Type", "application/octet-stream")
filename := ctx.PathParam("filename")