api/ui: Allow per-scratch TTL down to 1m
Format / gofmt (push) Successful in 26s
Format / gofmt (pull_request) Successful in 26s
CI / Build (push) Successful in 33s
CI / Build (pull_request) Successful in 33s
CI / Go Tests (push) Successful in 35s
CI / Go Tests (pull_request) Successful in 35s
Format / gofmt (push) Successful in 26s
Format / gofmt (pull_request) Successful in 26s
CI / Build (push) Successful in 33s
CI / Build (pull_request) Successful in 33s
CI / Go Tests (push) Successful in 35s
CI / Go Tests (pull_request) Successful in 35s
#4
This commit is contained in:
@@ -106,6 +106,7 @@ func (s *Server) getUIConfig(w http.ResponseWriter, r *http.Request) {
|
||||
"max_upload_size_bytes": s.cfg.Limits.MaxUploadSizeBytes,
|
||||
"upload_allowed": s.isUploadAllowedForRequest(r),
|
||||
"default_ttl": s.cfg.Limits.DefaultTTL,
|
||||
"max_ttl": config.MaxScratchTTL.String(),
|
||||
}
|
||||
writeJSON(w, http.StatusOK, payload)
|
||||
}
|
||||
@@ -184,8 +185,9 @@ func (s *Server) createScratch(w http.ResponseWriter, r *http.Request) {
|
||||
var reader io.Reader
|
||||
originalName := ""
|
||||
contentType := strings.TrimSpace(r.Header.Get("Content-Type"))
|
||||
multipart := strings.HasPrefix(contentType, "multipart/form-data")
|
||||
|
||||
if strings.HasPrefix(contentType, "multipart/form-data") {
|
||||
if multipart {
|
||||
if err := r.ParseMultipartForm(multipartMaxMemory); err != nil {
|
||||
s.writeCreateError(w, err)
|
||||
return
|
||||
@@ -228,7 +230,13 @@ func (s *Server) createScratch(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
meta, err := s.store.CreateWithOriginalName(reader, contentType, originalName, s.cfg.Limits.DefaultTTLDuration)
|
||||
ttl, err := s.resolveTTL(r, multipart)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
meta, err := s.store.CreateWithOriginalName(reader, contentType, originalName, ttl)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "request body too large") {
|
||||
http.Error(w, s.maxUploadSizeError(), http.StatusRequestEntityTooLarge)
|
||||
@@ -364,6 +372,33 @@ func (s *Server) rawScratch(w http.ResponseWriter, r *http.Request) {
|
||||
http.ServeContent(w, r, meta.ID, meta.CreatedAt, bytes.NewReader(content))
|
||||
}
|
||||
|
||||
// resolveTTL returns the per-scratch TTL for POST /api/scratch.
|
||||
// Multipart uploads read form field "ttl"; raw-body uploads read query "ttl".
|
||||
// Omitted or empty values use limits.default_ttl. Invalid or out-of-range
|
||||
// values (below 1m, above MaxScratchTTL, or non-duration) return an error.
|
||||
// Infinite TTL is not allowed.
|
||||
func (s *Server) resolveTTL(r *http.Request, multipart bool) (time.Duration, error) {
|
||||
raw := ""
|
||||
if multipart {
|
||||
raw = strings.TrimSpace(r.FormValue("ttl"))
|
||||
} else {
|
||||
raw = strings.TrimSpace(r.URL.Query().Get("ttl"))
|
||||
}
|
||||
if raw == "" {
|
||||
return s.cfg.Limits.DefaultTTLDuration, nil
|
||||
}
|
||||
parsed, err := time.ParseDuration(raw)
|
||||
if err != nil {
|
||||
return 0, errInvalidScratchTTL
|
||||
}
|
||||
if parsed < config.MinScratchTTL || parsed > config.MaxScratchTTL {
|
||||
return 0, errInvalidScratchTTL
|
||||
}
|
||||
return parsed, nil
|
||||
}
|
||||
|
||||
var errInvalidScratchTTL = fmt.Errorf("ttl must be a Go duration between %s and %s", config.MinScratchTTL, config.MaxScratchTTL)
|
||||
|
||||
func (s *Server) writeCreateError(w http.ResponseWriter, err error) {
|
||||
var maxErr *http.MaxBytesError
|
||||
if errors.As(err, &maxErr) || strings.Contains(err.Error(), "request body too large") {
|
||||
|
||||
Reference in New Issue
Block a user