mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2026-10-10 04:53:09 +08:00
893457cd50
* fix(aliyundrive): limit callback concurrency - Share proxy callback admission by Aliyun user identity and hold permits for complete response-body lifetimes. - Retry only verified callback-capacity rejections while preserving direct redirects and server download limiting. - Map exhausted temporary capacity to S3 SlowDown through the merged OpenListTeam gofakes3 module. - Cover shared limits, lifecycle release, cancellation, retry classification, and the S3 HTTP response. Co-authored-by: Codex <267193182+codex@users.noreply.github.com> # Conflicts: # go.mod # go.sum # server/s3/pager.go * fix(op): separate redirect and proxy link cache entries - Include redirect mode in the link cache key for all drivers. - Cover both redirect-to-proxy and proxy-to-redirect cache reuse. Co-authored-by: Codex <267193182+codex@users.noreply.github.com> * fix(proxy): close range bodies before opening next - make ServeHTTP own each range body and preserve cleanup failures - remove the aggregate range closer and pass range readers directly - replace the obsolete callback transport test with focused lifecycle coverage Co-authored-by: Codex <267193182+codex@users.noreply.github.com> --------- Co-authored-by: nostalume <nostalucent@gmail.com> Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
67 lines
2.0 KiB
Go
67 lines
2.0 KiB
Go
package s3
|
|
|
|
import (
|
|
"context"
|
|
"encoding/xml"
|
|
"errors"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
|
"github.com/OpenListTeam/gofakes3"
|
|
"github.com/OpenListTeam/gofakes3/s3mem"
|
|
)
|
|
|
|
func TestMapBackendErrorMapsOnlyTemporaryCapacity(t *testing.T) {
|
|
capacity := errs.NewErr(errs.TemporaryCapacity, "callback admission timed out")
|
|
if got := mapBackendError(capacity); got != gofakes3.ErrSlowDown {
|
|
t.Fatalf("capacity error mapped to %v, want %v", got, gofakes3.ErrSlowDown)
|
|
}
|
|
|
|
permanent := errors.New("permission denied")
|
|
if got := mapBackendError(permanent); got != permanent {
|
|
t.Fatalf("permanent error mapped to %v, want original error", got)
|
|
}
|
|
if got := mapBackendError(nil); got != nil {
|
|
t.Fatalf("nil error mapped to %v", got)
|
|
}
|
|
}
|
|
|
|
type capacityBackend struct {
|
|
gofakes3.Backend
|
|
}
|
|
|
|
func (b capacityBackend) GetObject(context.Context, string, string, *gofakes3.ObjectRangeRequest) (*gofakes3.Object, error) {
|
|
return nil, mapBackendError(errs.NewErr(errs.TemporaryCapacity, "callback admission timed out"))
|
|
}
|
|
|
|
func TestTemporaryCapacityProducesS3SlowDownResponse(t *testing.T) {
|
|
memory := s3mem.New()
|
|
if err := memory.CreateBucket(t.Context(), "bucket"); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
server := httptest.NewServer(gofakes3.New(capacityBackend{Backend: memory}).Server())
|
|
defer server.Close()
|
|
|
|
request, err := http.NewRequestWithContext(t.Context(), http.MethodGet, server.URL+"/bucket/object", nil)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
response, err := server.Client().Do(request)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
defer response.Body.Close()
|
|
if response.StatusCode != http.StatusServiceUnavailable {
|
|
t.Fatalf("status = %d, want %d", response.StatusCode, http.StatusServiceUnavailable)
|
|
}
|
|
var result gofakes3.ErrorResult
|
|
if err := xml.NewDecoder(response.Body).Decode(&result); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if result.Code != gofakes3.ErrSlowDown || result.Message != gofakes3.ErrSlowDown.Message() {
|
|
t.Fatalf("S3 error = %#v, want SlowDown with standard message", result)
|
|
}
|
|
}
|