feat(api): 单次上传上限改为 context_max_bytes 可配,Cloudflare 边缘后默认 95Mi,新增 GET /me/submissions/limits 供面板预检
This commit is contained in:
10 files changed
+158
-2
No files matched your search
@@ -610,6 +610,7 @@ func (a *API) externalAPIRoutes() []apiRoute {
|
||||
// session is the correct gate (the admin verdict lives below, behind adminOnly).
|
||||
{Method: "POST", Pattern: "/api/v1/me/submissions", h: a.handleCreateSubmission},
|
||||
{Method: "GET", Pattern: "/api/v1/me/submissions", h: a.handleMySubmissions},
|
||||
{Method: "GET", Pattern: "/api/v1/me/submissions/limits", h: a.handleSubmissionLimits},
|
||||
// The blob upload for a submission the caller owns: the request body is the
|
||||
// raw gzip build context, streamed to the derived, id-namespaced location.
|
||||
// App-tier and owner-scoped (the id must belong to the principal), exactly
|
||||
|
||||
@@ -202,6 +202,23 @@ func (a *API) handleUploadSubmissionContext(w http.ResponseWriter, r *http.Reque
|
||||
// query to another user's uploads. Each row is enriched with its linked build's
|
||||
// outcome — this list is the only player-visible outlet for a build result, so
|
||||
// a failed build is not invisible to the person who submitted it.
|
||||
// SubmissionLimits is what one upload may carry, read before sending it.
|
||||
type SubmissionLimits struct {
|
||||
MaxContextBytes int64 `json:"max_context_bytes"`
|
||||
}
|
||||
|
||||
// handleSubmissionLimits reports the effective per-upload context cap
|
||||
// ([registry] context_max_bytes), so the panel can refuse an oversized file
|
||||
// before streaming it into the edge's own body limit.
|
||||
func (a *API) handleSubmissionLimits(w http.ResponseWriter, r *http.Request) {
|
||||
l, ok := a.Submissions.(interface{ ContextLimit() int64 })
|
||||
if !ok {
|
||||
writeError(w, r, errSubmissionsUnavailable)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, SubmissionLimits{MaxContextBytes: l.ContextLimit()})
|
||||
}
|
||||
|
||||
func (a *API) handleMySubmissions(w http.ResponseWriter, r *http.Request) {
|
||||
if a.Submissions == nil {
|
||||
writeError(w, r, errSubmissionsUnavailable)
|
||||
|
||||
@@ -934,3 +934,27 @@ func TestUploadSubmissionContextRateLimited(t *testing.T) {
|
||||
t.Fatalf("retry at the same instant after failure: code = %d, want 200 (%s)", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
|
||||
type limitedSubmissions struct {
|
||||
*fakeSubmissions
|
||||
limit int64
|
||||
}
|
||||
|
||||
func (l limitedSubmissions) ContextLimit() int64 { return l.limit }
|
||||
|
||||
// The panel reads the per-upload cap before sending a file; a lane that cannot
|
||||
// report one answers like any unwired submissions endpoint.
|
||||
func TestSubmissionLimitsReportsTheContextCap(t *testing.T) {
|
||||
api := appSubAPI(&fakeSubmissions{})
|
||||
api.Submissions = limitedSubmissions{&fakeSubmissions{}, 99614720}
|
||||
w := do(api.ExternalHandler(), "GET", "/api/v1/me/submissions/limits", "", nil)
|
||||
if w.Code != 200 || strings.TrimSpace(w.Body.String()) != `{"max_context_bytes":99614720}` {
|
||||
t.Fatalf("limits = %d %s", w.Code, w.Body.String())
|
||||
}
|
||||
|
||||
api.Submissions = nil
|
||||
w = do(api.ExternalHandler(), "GET", "/api/v1/me/submissions/limits", "", nil)
|
||||
if w.Code != 503 {
|
||||
t.Fatalf("unwired limits = %d %s", w.Code, w.Body.String())
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user