115 lines
4.9 KiB
Objective-C
115 lines
4.9 KiB
Objective-C
//
|
|
// AVPlayerProxy.m
|
|
// AVPlayerHTTPHeaders
|
|
//
|
|
// Created by Kevin Hunt on 2017-01-16.
|
|
// Copyright © 2017 Prophet Studios. All rights reserved.
|
|
//
|
|
|
|
#import "AVPlayerReverseProxy.h"
|
|
#import "GCDWebServer.h"
|
|
#import "GCDWebServerDataResponse.h"
|
|
|
|
NSString * __nonnull const AVPlayerProxyLocalHost = @"localhost:8080";
|
|
|
|
NSString *const AVPlayerReverseProxyDidReceiveHeadersNotification = @"AVPlayerReverseProxyDidReceiveHeadersNotification";
|
|
|
|
NSString *const AVPlayerReverseProxyNotificationRequestURLKey = @"AVPlayerReverseProxyNotificationRequestURLKey";
|
|
NSString *const AVPlayerReverseProxyNotificationHeadersKey = @"AVPlayerReverseProxyNotificationHeadersKey";
|
|
|
|
@implementation AVPlayerReverseProxy {
|
|
NSDictionary *_httpHeaders;
|
|
GCDWebServer *_webServer;
|
|
}
|
|
|
|
- (instancetype)init {
|
|
if (self = [super init]) {
|
|
_httpHeaders = [[NSDictionary alloc] init];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)startPlayerProxyWithReverseProxyHost:(nonnull NSString *)reverseProxyHost {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
|
|
_webServer = [[GCDWebServer alloc] init];
|
|
|
|
__weak NSDictionary *weakHeaders = _httpHeaders;
|
|
__weak typeof(self) weakSelf = self;
|
|
// Add a handler to respond to GET requests on any local URL
|
|
[_webServer addDefaultHandlerForMethod:@"GET"
|
|
requestClass:[GCDWebServerRequest class]
|
|
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
|
|
|
|
// Process the request by sending it using the reverse proxy URL
|
|
GCDWebServerResponse *response = [weakSelf sendRequest:request toHost:reverseProxyHost withHeaders:weakHeaders];
|
|
return response;
|
|
}];
|
|
|
|
// Start server on port 8080
|
|
[_webServer startWithPort:8080 bonjourName:nil];
|
|
});
|
|
}
|
|
- (void)stopPlayerProxy {
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
[_webServer stop];
|
|
});
|
|
}
|
|
|
|
- (void)addHttpHeaders:(NSDictionary*)httpHeaders {
|
|
if (httpHeaders && [httpHeaders count] > 0) {
|
|
NSMutableDictionary *mergeDict = [NSMutableDictionary dictionaryWithDictionary:_httpHeaders];
|
|
[mergeDict addEntriesFromDictionary:httpHeaders];
|
|
_httpHeaders = [NSDictionary dictionaryWithDictionary:mergeDict];
|
|
}
|
|
}
|
|
|
|
- (void)removeHttpHeaders:(NSDictionary*)httpHeaders {
|
|
if (httpHeaders && [httpHeaders count] > 0) {
|
|
NSMutableDictionary *removeDict = [NSMutableDictionary dictionaryWithDictionary:_httpHeaders];
|
|
[removeDict removeObjectsForKeys:[httpHeaders allKeys]];
|
|
_httpHeaders = [NSDictionary dictionaryWithDictionary:removeDict];
|
|
}
|
|
}
|
|
|
|
- (GCDWebServerResponse *)sendRequest:(GCDWebServerRequest *)request toHost:(NSString *)reverseProxyHost withHeaders:(NSDictionary *)headers {
|
|
NSError *error = nil;
|
|
NSHTTPURLResponse *urlResponse = nil;
|
|
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
// Replace the local url with the reverse host to recreate the original url
|
|
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
NSString *customUrl = [request.URL.absoluteString stringByReplacingOccurrencesOfString:AVPlayerProxyLocalHost withString:reverseProxyHost];
|
|
|
|
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:customUrl]];
|
|
|
|
// Set the additional HTTP headers in the new request
|
|
for (NSString *key in [headers allKeys]) {
|
|
NSString *value = [headers valueForKey:key];
|
|
[urlRequest setValue:value forHTTPHeaderField:key];
|
|
}
|
|
|
|
// Synchronously make the request
|
|
NSData *responseData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&urlResponse error:&error];
|
|
|
|
// Capture the header info
|
|
NSDictionary *responseHeaders = urlResponse.allHeaderFields;
|
|
NSString *contentType = [responseHeaders valueForKey:@"Content-Type"];
|
|
|
|
// Post notification containing headers an corresponding URL
|
|
NSDictionary *userInfoDict = [NSDictionary dictionaryWithObjectsAndKeys:
|
|
customUrl, AVPlayerReverseProxyNotificationRequestURLKey,
|
|
responseHeaders, AVPlayerReverseProxyNotificationHeadersKey,
|
|
nil];
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:AVPlayerReverseProxyDidReceiveHeadersNotification
|
|
object:nil
|
|
userInfo:userInfoDict];
|
|
|
|
// Create the response to return back to the player
|
|
GCDWebServerDataResponse *response = [GCDWebServerDataResponse responseWithData:responseData contentType:contentType];
|
|
|
|
return response;
|
|
}
|
|
|
|
@end
|