Skip to content

Commit b9eab6c

Browse files
dpoguedodahoho
andcommitted
feat(schemes): Support range requests
Based on code from ionic-team/cordova-plugin-ionic-webview#692 Closes apacheGH-1033. Co-Authored-By: David Holmgren <dodahoho@users.noreply.github.com>
1 parent 9b131fc commit b9eab6c

File tree

1 file changed

+42
-7
lines changed

1 file changed

+42
-7
lines changed

CordovaLib/Classes/Private/Plugins/CDVWebViewEngine/CDVURLSchemeHandler.m

+42-7
Original file line numberDiff line numberDiff line change
@@ -89,24 +89,59 @@ - (void)webView:(WKWebView *)webView startURLSchemeTask:(id <WKURLSchemeTask>)ur
8989
return;
9090
}
9191

92+
NSInteger statusCode = 200; // Default to 200 OK status
9293
NSString *mimeType = [self getMimeType:fileURL] ?: @"application/octet-stream";
9394
NSNumber *fileLength;
9495
[fileURL getResourceValue:&fileLength forKey:NSURLFileSizeKey error:nil];
9596

9697
NSNumber *responseSize = fileLength;
98+
NSUInteger responseSent = 0;
99+
100+
NSMutableDictionary *headers = [NSMutableDictionary dictionaryWithCapacity:5];
101+
headers[@"Content-Type"] = mimeType;
102+
headers[@"Cache-Control"] = @"no-cache";
103+
headers[@"Content-Length"] = [responseSize stringValue];
104+
105+
// Check for Range header
106+
NSString *rangeHeader = [urlSchemeTask.request valueForHTTPHeaderField:@"Range"];
107+
if (rangeHeader) {
108+
NSRange range = NSMakeRange(NSNotFound, 0);
109+
110+
if ([rangeHeader hasPrefix:@"bytes="]) {
111+
NSString *byteRange = [rangeHeader substringFromIndex:6];
112+
NSArray<NSString *> *rangeParts = [byteRange componentsSeparatedByString:@"-"];
113+
NSUInteger start = (NSUInteger)[rangeParts[0] integerValue];
114+
NSUInteger end = rangeParts.count > 1 && ![rangeParts[1] isEqualToString:@""] ? (NSUInteger)[rangeParts[1] integerValue] : [fileLength unsignedIntegerValue] - 1;
115+
range = NSMakeRange(start, end - start + 1);
116+
}
117+
118+
if (range.location != NSNotFound) {
119+
// Ensure range is valid
120+
if (range.location >= [fileLength unsignedIntegerValue] && [self taskActive:urlSchemeTask]) {
121+
headers[@"Content-Range"] = [NSString stringWithFormat:@"bytes */%@", fileLength];
122+
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:req.URL statusCode:416 HTTPVersion:@"HTTP/1.1" headerFields:headers];
123+
[urlSchemeTask didReceiveResponse:response];
124+
[urlSchemeTask didFinish];
125+
126+
@synchronized(self.handlerMap) {
127+
[self.handlerMap removeObjectForKey:urlSchemeTask];
128+
}
129+
return;
130+
}
97131

98-
NSDictionary *headers = @{
99-
@"Content-Length" : [responseSize stringValue],
100-
@"Content-Type" : mimeType,
101-
@"Cache-Control": @"no-cache"
102-
};
132+
[fileHandle seekToFileOffset:range.location];
133+
responseSize = [NSNumber numberWithUnsignedInteger:range.length];
134+
statusCode = 206; // Partial Content
135+
headers[@"Content-Range"] = [NSString stringWithFormat:@"bytes %lu-%lu/%@", (unsigned long)range.location, (unsigned long)(range.location + range.length - 1), fileLength];
136+
headers[@"Content-Length"] = [NSString stringWithFormat:@"%lu", (unsigned long)range.length];
137+
}
138+
}
103139

104-
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:req.URL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:headers];
140+
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:req.URL statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headers];
105141
if ([self taskActive:urlSchemeTask]) {
106142
[urlSchemeTask didReceiveResponse:response];
107143
}
108144

109-
NSUInteger responseSent = 0;
110145
while ([self taskActive:urlSchemeTask] && responseSent < [responseSize unsignedIntegerValue]) {
111146
@autoreleasepool {
112147
NSData *data = [self readFromFileHandle:fileHandle upTo:FILE_BUFFER_SIZE error:&error];

0 commit comments

Comments
 (0)