swisspol/GCDWebServer

How to close the connection automatically?

Closed this issue · 0 comments

Hello,

When a data task is cancelled, can its corresponding connection be automatically closed or aborted?

I found in use that a connection must get a response before calling its close method.

Below is my code:

#import <GCDWebServer/GCDWebServer.h>
#import <GCDWebServer/GCDWebServerStreamedResponse.h>
#import <GCDWebServer/GCDWebServerConnection.h>

@interface TestConnection : GCDWebServerConnection

@end

@implementation TestConnection

- (void)close {
    [super close];
#ifdef DEBUG
    NSLog(@"---- [TestConnection close] -----!!!");
#endif
}

@end

@interface TestViewController ()
@property (nonatomic, strong) NSURLSessionDataTask *task;
@property (nonatomic, strong) GCDWebServer *server;
@end

@implementation TestViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // test
    NSString *filePath = [NSBundle.mainBundle pathForResource:@"video" ofType:@"mp4"];
    NSFileHandle *fileHandler = [NSFileHandle fileHandleForReadingAtPath:filePath];
    unsigned long fileSize = [[NSFileManager.defaultManager attributesOfItemAtPath:filePath error:nil][NSFileSize] unsignedLongLongValue];

    // server
    _server = GCDWebServer.alloc.init;
    [_server addHandlerWithMatchBlock:^GCDWebServerRequest * _Nullable(NSString * _Nonnull requestMethod, NSURL * _Nonnull requestURL, NSDictionary<NSString *,NSString *> * _Nonnull requestHeaders, NSString * _Nonnull urlPath, NSDictionary<NSString *,NSString *> * _Nonnull urlQuery) {
        return [GCDWebServerRequest.alloc initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
    } asyncProcessBlock:^(__kindof GCDWebServerRequest * _Nonnull request, GCDWebServerCompletionBlock  _Nonnull completionBlock) {
        [fileHandler seekToFileOffset:request.byteRange.location];
        NSData *data = [fileHandler readDataOfLength:request.byteRange.length];
        
        // response
        GCDWebServerStreamedResponse *response = [GCDWebServerStreamedResponse.alloc initWithContentType:@"video/mpeg4" asyncStreamBlock:^(GCDWebServerBodyReaderCompletionBlock  _Nonnull completionBlock) {
            // delay
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                completionBlock(data, nil);
            });
        }];

        response.contentLength = data.length;
        response.statusCode = 206;
        unsigned long start = (unsigned long)request.byteRange.location;
        unsigned long end   = (unsigned long)(start + data.length - 1);
        [response setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", start, end, fileSize] forAdditionalHeader:@"Content-Range"];

        completionBlock(response);
    }];
    
    // start
    [_server startWithOptions:@{ GCDWebServerOption_ConnectionClass : TestConnection.class } error:NULL];
}

- (IBAction)request:(id)sender {

    // request
    NSURL *URL = [NSURL URLWithString:[_server.serverURL.absoluteString stringByAppendingPathComponent:@"video.mp4"]];
    NSMutableURLRequest *request = [NSMutableURLRequest.alloc initWithURL:URL];
    [request setValue:[NSString stringWithFormat:@"bytes=%d-", 6666] forHTTPHeaderField:@"Range"];

    _task = [NSURLSession.sharedSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
    }];
    
    [_task resume];
    NSLog(@"---- [NSURLSessionDataTask resume] -----!!!");
}

- (IBAction)cancel:(id)sender {
    [_task cancel];
    NSLog(@"---- [NSURLSessionDataTask cancel] -----!!!");
}
@end