@@ -51,6 +51,33 @@ class SpecialProtocolKvStore implements ReadableKvStore {
5151 public credentialsProvider : SpecialProtocolCredentialsProvider ,
5252 public baseUrl : string ,
5353 ) { }
54+
55+ async getObjectLength ( url : string , options : ReadOptions ) {
56+ // Use a HEAD request to get the length of an object
57+ const { cancellationToken = uncancelableToken } = options ;
58+ const headResponse = await cancellableFetchSpecialOk (
59+ this . credentialsProvider ,
60+ url ,
61+ { method : "HEAD" } ,
62+ async ( response ) => response ,
63+ cancellationToken ,
64+ ) ;
65+
66+ if ( headResponse . status !== 200 ) {
67+ throw new Error (
68+ "Failed to determine total size in order to fetch suffix" ,
69+ ) ;
70+ }
71+ const contentLength = headResponse . headers . get ( "content-length" ) ;
72+ if ( contentLength === undefined ) {
73+ throw new Error (
74+ "Failed to determine total size in order to fetch suffix" ,
75+ ) ;
76+ }
77+ const contentLengthNumber = Number ( contentLength ) ;
78+ return contentLengthNumber ;
79+ }
80+
5481 async read (
5582 key : string ,
5683 options : ReadOptions ,
@@ -83,14 +110,17 @@ class SpecialProtocolKvStore implements ReadableKvStore {
83110 if ( contentRange === null ) {
84111 if ( byteRangeRequest !== undefined ) {
85112 if ( "suffixLength" in byteRangeRequest ) {
86- throw new Error (
87- "Content-range header not provided with HTTP 206 response. Check server CORS configuration." ,
88- ) ;
113+ const objectSize = await this . getObjectLength ( url , options ) ;
114+ byteRange = {
115+ offset : objectSize - byteRangeRequest . suffixLength ,
116+ length : Number ( response . headers . get ( "content-length" ) ) ,
117+ } ;
118+ } else {
119+ byteRange = {
120+ offset : byteRangeRequest . offset ,
121+ length : data . byteLength ,
122+ } ;
89123 }
90- byteRange = {
91- offset : byteRangeRequest . offset ,
92- length : data . byteLength ,
93- } ;
94124 } else {
95125 throw new Error (
96126 "Unexpected HTTP 206 response when no byte range specified." ,
@@ -134,25 +164,7 @@ class SpecialProtocolKvStore implements ReadableKvStore {
134164 ) {
135165 // Some servers, such as the npm http-server package, do not support suffixLength
136166 // byte-range requests.
137- const headResponse = await cancellableFetchSpecialOk (
138- this . credentialsProvider ,
139- url ,
140- { method : "HEAD" } ,
141- async ( response ) => response ,
142- cancellationToken ,
143- ) ;
144- if ( headResponse . status !== 200 ) {
145- throw new Error (
146- "Failed to determine total size in order to fetch suffix" ,
147- ) ;
148- }
149- const contentLength = headResponse . headers . get ( "content-length" ) ;
150- if ( contentLength === undefined ) {
151- throw new Error (
152- "Failed to determine total size in order to fetch suffix" ,
153- ) ;
154- }
155- const contentLengthNumber = Number ( contentLength ) ;
167+ const contentLengthNumber = await this . getObjectLength ( url , options ) ;
156168 byteRangeRequest = composeByteRangeRequest (
157169 { offset : 0 , length : contentLengthNumber } ,
158170 byteRangeRequest ,
0 commit comments