A container registry that uses the AT Protocol for manifest storage and S3 for blob storage. atcr.io
docker container atproto go

more s3 fixes

evan.jarrett.net 0d723cb7 f307d6ea

verified
+38
+33
pkg/hold/pds/xrpc_test.go
··· 220 return &header, &commit 221 } 222 223 // assertCARResponse validates CAR file response 224 func assertCARResponse(t *testing.T, w *httptest.ResponseRecorder, expectedCode int) []byte { 225 t.Helper() ··· 2851 } 2852 defer conn.Close() 2853 2854 // Should receive the 3 historical events 2855 for i := 0; i < 3; i++ { 2856 messageType, message, err := conn.ReadMessage() ··· 2889 t.Fatalf("Failed to connect to WebSocket: %v", err) 2890 } 2891 defer conn.Close() 2892 2893 // Should only receive event 3 (after cursor=2) 2894 messageType, message, err := conn.ReadMessage() ··· 2926 } 2927 defer conn.Close() 2928 2929 // Verify no historical events by broadcasting immediately and checking 2930 // that we only receive the new event (not historical ones) 2931 // Give subscriber time to register first ··· 2977 t.Fatalf("Failed to connect to WebSocket: %v", err) 2978 } 2979 defer conn.Close() 2980 2981 // Read and discard the 4 historical events (seq 1-4) 2982 for i := 0; i < 4; i++ {
··· 220 return &header, &commit 221 } 222 223 + // skipAccountEvent reads and discards the initial #account event that the 224 + // EventBroadcaster sends to every new subscriber. 225 + func skipAccountEvent(t *testing.T, conn *websocket.Conn) { 226 + t.Helper() 227 + msgType, message, err := conn.ReadMessage() 228 + if err != nil { 229 + t.Fatalf("Failed to read account event: %v", err) 230 + } 231 + if msgType != websocket.BinaryMessage { 232 + t.Fatalf("Expected binary message for account event, got type %d", msgType) 233 + } 234 + reader := bytes.NewReader(message) 235 + var header events.EventHeader 236 + if err := header.UnmarshalCBOR(reader); err != nil { 237 + t.Fatalf("Failed to decode account event header: %v", err) 238 + } 239 + if header.MsgType != "#account" { 240 + t.Fatalf("Expected #account event, got %s", header.MsgType) 241 + } 242 + } 243 + 244 // assertCARResponse validates CAR file response 245 func assertCARResponse(t *testing.T, w *httptest.ResponseRecorder, expectedCode int) []byte { 246 t.Helper() ··· 2872 } 2873 defer conn.Close() 2874 2875 + // Skip the initial #account event 2876 + skipAccountEvent(t, conn) 2877 + 2878 // Should receive the 3 historical events 2879 for i := 0; i < 3; i++ { 2880 messageType, message, err := conn.ReadMessage() ··· 2913 t.Fatalf("Failed to connect to WebSocket: %v", err) 2914 } 2915 defer conn.Close() 2916 + 2917 + // Skip the initial #account event 2918 + skipAccountEvent(t, conn) 2919 2920 // Should only receive event 3 (after cursor=2) 2921 messageType, message, err := conn.ReadMessage() ··· 2953 } 2954 defer conn.Close() 2955 2956 + // Skip the initial #account event 2957 + skipAccountEvent(t, conn) 2958 + 2959 // Verify no historical events by broadcasting immediately and checking 2960 // that we only receive the new event (not historical ones) 2961 // Give subscriber time to register first ··· 3007 t.Fatalf("Failed to connect to WebSocket: %v", err) 3008 } 3009 defer conn.Close() 3010 + 3011 + // Skip the initial #account event 3012 + skipAccountEvent(t, conn) 3013 3014 // Read and discard the 4 historical events (seq 1-4) 3015 for i := 0; i < 4; i++ {
+5
pkg/s3/types.go
··· 192 o.BaseEndpoint = aws.String(endpoint) 193 o.UsePathStyle = true 194 } 195 }) 196 197 var s3PathPrefix string
··· 192 o.BaseEndpoint = aws.String(endpoint) 193 o.UsePathStyle = true 194 } 195 + // Disable automatic CRC32 checksum calculation on uploads. 196 + // SDK v2 v1.71.0+ adds checksums by default using chunked encoding 197 + // with trailers, which causes XAmzContentSHA256Mismatch errors on 198 + // S3-compatible services that don't support this. 199 + o.RequestChecksumCalculation = aws.RequestChecksumCalculationWhenRequired 200 }) 201 202 var s3PathPrefix string