初始化提交
This commit is contained in:
142
WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m
vendored
Normal file
142
WebDriverAgentLib/Vendor/RoutingHTTPServer/RoutingConnection.m
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
#import "RoutingConnection.h"
|
||||
#import "RoutingHTTPServer.h"
|
||||
#import "HTTPMessage.h"
|
||||
#import "HTTPResponseProxy.h"
|
||||
|
||||
#pragma clang diagnostic ignored "-Wdirect-ivar-access"
|
||||
#pragma clang diagnostic ignored "-Widiomatic-parentheses"
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
|
||||
@implementation RoutingConnection {
|
||||
__unsafe_unretained RoutingHTTPServer *http;
|
||||
NSDictionary *headers;
|
||||
}
|
||||
|
||||
- (id)initWithAsyncSocket:(GCDAsyncSocket *)newSocket configuration:(HTTPConfig *)aConfig {
|
||||
if (self = [super initWithAsyncSocket:newSocket configuration:aConfig]) {
|
||||
NSAssert([config.server isKindOfClass:[RoutingHTTPServer class]],
|
||||
@"A RoutingConnection is being used with a server that is not a %@",
|
||||
NSStringFromClass([RoutingHTTPServer class]));
|
||||
|
||||
http = (RoutingHTTPServer *)config.server;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)supportsMethod:(NSString *)method atPath:(NSString *)path {
|
||||
|
||||
if ([http supportsMethod:method])
|
||||
return YES;
|
||||
|
||||
return [super supportsMethod:method atPath:path];
|
||||
}
|
||||
|
||||
- (BOOL)shouldHandleRequestForMethod:(NSString *)method atPath:(NSString *)path {
|
||||
// The default implementation is strict about the use of Content-Length. Either
|
||||
// a given method + path combination must *always* include data or *never*
|
||||
// include data. The routing connection is lenient, a POST that sometimes does
|
||||
// not include data or a GET that sometimes does is fine. It is up to the route
|
||||
// implementations to decide how to handle these situations.
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)processBodyData:(NSData *)postDataChunk {
|
||||
BOOL result = [request appendData:postDataChunk];
|
||||
if (!result) {
|
||||
// TODO: Log
|
||||
}
|
||||
}
|
||||
|
||||
- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path {
|
||||
NSURL *url = [request url];
|
||||
NSString *query = nil;
|
||||
NSDictionary *params = [NSDictionary dictionary];
|
||||
headers = nil;
|
||||
|
||||
if (url) {
|
||||
path = [url path]; // Strip the query string from the path
|
||||
query = [url query];
|
||||
if (query) {
|
||||
params = [self parseParams:query];
|
||||
}
|
||||
}
|
||||
|
||||
RouteResponse *response = [http routeMethod:method withPath:path parameters:params request:request connection:self];
|
||||
if (response != nil) {
|
||||
headers = response.headers;
|
||||
return response.proxiedResponse;
|
||||
}
|
||||
|
||||
// Set a MIME type for static files if possible
|
||||
NSObject<HTTPResponse> *staticResponse = [super httpResponseForMethod:method URI:path];
|
||||
if (staticResponse && [staticResponse respondsToSelector:@selector(filePath)]) {
|
||||
NSString *mimeType = [http mimeTypeForPath:[staticResponse performSelector:@selector(filePath)]];
|
||||
if (mimeType) {
|
||||
headers = [NSDictionary dictionaryWithObject:mimeType forKey:@"Content-Type"];
|
||||
}
|
||||
}
|
||||
return staticResponse;
|
||||
}
|
||||
|
||||
- (void)responseHasAvailableData:(NSObject<HTTPResponse> *)sender {
|
||||
HTTPResponseProxy *proxy = (HTTPResponseProxy *)httpResponse;
|
||||
if (proxy.response == sender) {
|
||||
[super responseHasAvailableData:httpResponse];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)responseDidAbort:(NSObject<HTTPResponse> *)sender {
|
||||
HTTPResponseProxy *proxy = (HTTPResponseProxy *)httpResponse;
|
||||
if (proxy.response == sender) {
|
||||
[super responseDidAbort:httpResponse];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setHeadersForResponse:(HTTPMessage *)response isError:(BOOL)isError {
|
||||
[http.defaultHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL *stop) {
|
||||
[response setHeaderField:field value:value];
|
||||
}];
|
||||
|
||||
if (headers && !isError) {
|
||||
[headers enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL *stop) {
|
||||
[response setHeaderField:field value:value];
|
||||
}];
|
||||
}
|
||||
|
||||
// Set the connection header if not already specified
|
||||
NSString *connection = [response headerField:@"Connection"];
|
||||
if (!connection) {
|
||||
connection = [self shouldDie] ? @"close" : @"keep-alive";
|
||||
[response setHeaderField:@"Connection" value:connection];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)preprocessResponse:(HTTPMessage *)response {
|
||||
[self setHeadersForResponse:response isError:NO];
|
||||
return [super preprocessResponse:response];
|
||||
}
|
||||
|
||||
- (NSData *)preprocessErrorResponse:(HTTPMessage *)response {
|
||||
[self setHeadersForResponse:response isError:YES];
|
||||
return [super preprocessErrorResponse:response];
|
||||
}
|
||||
|
||||
- (BOOL)shouldDie {
|
||||
__block BOOL shouldDie = [super shouldDie];
|
||||
|
||||
// Allow custom headers to determine if the connection should be closed
|
||||
if (!shouldDie && headers) {
|
||||
[headers enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL *stop) {
|
||||
if ([field caseInsensitiveCompare:@"connection"] == NSOrderedSame) {
|
||||
if ([value caseInsensitiveCompare:@"close"] == NSOrderedSame) {
|
||||
shouldDie = YES;
|
||||
}
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
return shouldDie;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user