mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-02-11 00:00:07 +08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d1e2a1a12f | ||
|
|
54d5abd3a8 | ||
|
|
a9fee8d7e2 | ||
|
|
6b15bdaa4e | ||
|
|
3771cf4e92 |
@@ -7,7 +7,7 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'GCDWebServer'
|
||||
s.version = '2.5.2'
|
||||
s.version = '2.5.3'
|
||||
s.author = { 'Pierre-Olivier Latour' => 'info@pol-online.net' }
|
||||
s.license = { :type => 'BSD', :file => 'LICENSE' }
|
||||
s.homepage = 'https://github.com/swisspol/GCDWebServer'
|
||||
|
||||
@@ -147,7 +147,6 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
NSMutableArray* _handlers;
|
||||
NSInteger _activeConnections; // Accessed through _syncQueue only
|
||||
BOOL _connected; // Accessed on main thread only
|
||||
BOOL _disconnecting; // Accessed on main thread only
|
||||
CFRunLoopTimerRef _disconnectTimer; // Accessed on main thread only
|
||||
|
||||
NSDictionary* _options;
|
||||
@@ -193,23 +192,11 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
GCDWebServerInitializeFunctions();
|
||||
}
|
||||
|
||||
static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
||||
@autoreleasepool {
|
||||
[server _didDisconnect];
|
||||
}
|
||||
server->_disconnecting = NO;
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if ((self = [super init])) {
|
||||
_syncQueue = dispatch_queue_create([NSStringFromClass([self class]) UTF8String], DISPATCH_QUEUE_SERIAL);
|
||||
_sourceSemaphore = dispatch_semaphore_create(0);
|
||||
_handlers = [[NSMutableArray alloc] init];
|
||||
CFRunLoopTimerContext context = {0, (ARC_BRIDGE void*)self, NULL, NULL, NULL};
|
||||
_disconnectTimer = CFRunLoopTimerCreate(kCFAllocatorDefault, HUGE_VAL, HUGE_VAL, 0, 0, _DisconnectTimerCallBack, &context);
|
||||
CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes);
|
||||
#if TARGET_OS_IPHONE
|
||||
_backgroundTask = UIBackgroundTaskInvalid;
|
||||
#endif
|
||||
@@ -221,9 +208,8 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
||||
DCHECK(_connected == NO);
|
||||
DCHECK(_activeConnections == 0);
|
||||
DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source
|
||||
DCHECK(_disconnectTimer == NULL); // The server can never be dealloc'ed while the disconnect timer is pending because of the retain-cycle
|
||||
|
||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||
CFRelease(_disconnectTimer);
|
||||
ARC_RELEASE(_handlers);
|
||||
ARC_DISPATCH_RELEASE(_sourceSemaphore);
|
||||
ARC_DISPATCH_RELEASE(_syncQueue);
|
||||
@@ -273,9 +259,10 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
||||
DCHECK(_activeConnections >= 0);
|
||||
if (_activeConnections == 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (_disconnecting) {
|
||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, HUGE_VAL);
|
||||
_disconnecting = NO;
|
||||
if (_disconnectTimer) {
|
||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||
CFRelease(_disconnectTimer);
|
||||
_disconnectTimer = NULL;
|
||||
}
|
||||
if (_connected == NO) {
|
||||
[self _didConnect];
|
||||
@@ -329,8 +316,17 @@ static void _DisconnectTimerCallBack(CFRunLoopTimerRef timer, void* info) {
|
||||
if (_activeConnections == 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if ((_disconnectDelay > 0.0) && (_source != NULL)) {
|
||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, CFAbsoluteTimeGetCurrent() + _disconnectDelay);
|
||||
_disconnecting = YES;
|
||||
if (_disconnectTimer) {
|
||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||
CFRelease(_disconnectTimer);
|
||||
}
|
||||
_disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + _disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
[self _didDisconnect];
|
||||
CFRelease(_disconnectTimer);
|
||||
_disconnectTimer = NULL;
|
||||
});
|
||||
CFRunLoopAddTimer(CFRunLoopGetMain(), _disconnectTimer, kCFRunLoopCommonModes);
|
||||
} else {
|
||||
[self _didDisconnect];
|
||||
}
|
||||
@@ -592,9 +588,10 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
_authenticationDigestAccounts = nil;
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (_disconnecting) {
|
||||
CFRunLoopTimerSetNextFireDate(_disconnectTimer, HUGE_VAL);
|
||||
_disconnecting = NO;
|
||||
if (_disconnectTimer) {
|
||||
CFRunLoopTimerInvalidate(_disconnectTimer);
|
||||
CFRelease(_disconnectTimer);
|
||||
_disconnectTimer = NULL;
|
||||
[self _didDisconnect];
|
||||
}
|
||||
});
|
||||
@@ -793,10 +790,23 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
if (![requestMethod isEqualToString:method]) {
|
||||
return nil;
|
||||
}
|
||||
if ([expression firstMatchInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)] == nil) {
|
||||
|
||||
NSArray* matches = [expression matchesInString:urlPath options:0 range:NSMakeRange(0, urlPath.length)];
|
||||
if (matches.count == 0) {
|
||||
return nil;
|
||||
}
|
||||
return ARC_AUTORELEASE([[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery]);
|
||||
|
||||
NSMutableArray* captures = [NSMutableArray array];
|
||||
for (NSTextCheckingResult* result in matches) {
|
||||
// Start at 1; index 0 is the whole string
|
||||
for (NSUInteger i = 1; i < result.numberOfRanges; i++) {
|
||||
[captures addObject:[urlPath substringWithRange:[result rangeAtIndex:i]]];
|
||||
}
|
||||
}
|
||||
|
||||
GCDWebServerRequest* request = [[aClass alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:urlPath query:urlQuery];
|
||||
[request setAttribute:captures forKey:GCDWebServerRequestAttribute_RegexCaptures];
|
||||
return ARC_AUTORELEASE(request);
|
||||
|
||||
} processBlock:block];
|
||||
} else {
|
||||
|
||||
@@ -204,10 +204,13 @@ NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
|
||||
}
|
||||
|
||||
key = [key stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
||||
NSString* unescapedKey = key ? GCDWebServerUnescapeURLString(key) : nil;
|
||||
value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "];
|
||||
if (key && value) {
|
||||
[parameters setObject:GCDWebServerUnescapeURLString(value) forKey:GCDWebServerUnescapeURLString(key)];
|
||||
NSString* unescapedValue = value ? GCDWebServerUnescapeURLString(value) : nil;
|
||||
if (unescapedKey && unescapedValue) {
|
||||
[parameters setObject:unescapedValue forKey:unescapedKey];
|
||||
} else {
|
||||
LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value);
|
||||
DNOT_REACHED();
|
||||
}
|
||||
|
||||
|
||||
@@ -153,6 +153,7 @@ extern NSString* GCDWebServerComputeMD5Digest(NSString* format, ...) NS_FORMAT_F
|
||||
- (BOOL)performOpen:(NSError**)error;
|
||||
- (BOOL)performWriteData:(NSData*)data error:(NSError**)error;
|
||||
- (BOOL)performClose:(NSError**)error;
|
||||
- (void)setAttribute:(id)attribute forKey:(NSString*)key;
|
||||
@end
|
||||
|
||||
@interface GCDWebServerResponse ()
|
||||
|
||||
@@ -27,6 +27,15 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
/**
|
||||
* Attribute key to retrieve an NSArray containing NSStrings from a GCDWebServerRequest
|
||||
* with the contents of any regular expression captures done on the request path.
|
||||
*
|
||||
* @warning This attribute will only be set on the request if adding a handler using
|
||||
* -addHandlerForMethod:pathRegex:requestClass:processBlock:.
|
||||
*/
|
||||
extern NSString* const GCDWebServerRequestAttribute_RegexCaptures;
|
||||
|
||||
/**
|
||||
* This protocol is used by the GCDWebServerConnection to communicate with
|
||||
* the GCDWebServerRequest and write the received HTTP body data.
|
||||
@@ -163,4 +172,11 @@
|
||||
*/
|
||||
- (BOOL)hasByteRange;
|
||||
|
||||
/**
|
||||
* Retrieves an attribute associated with this request using the given key.
|
||||
*
|
||||
* @return The attribute value for the key.
|
||||
*/
|
||||
- (id)attributeForKey:(NSString*)key;
|
||||
|
||||
@end
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
|
||||
#import "GCDWebServerPrivate.h"
|
||||
|
||||
NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerRequestAttribute_RegexCaptures";
|
||||
|
||||
#define kZlibErrorDomain @"ZlibErrorDomain"
|
||||
#define kGZipInitialBufferSize (256 * 1024)
|
||||
|
||||
@@ -152,6 +154,7 @@
|
||||
|
||||
BOOL _opened;
|
||||
NSMutableArray* _decoders;
|
||||
NSMutableDictionary* _attributes;
|
||||
id<GCDWebServerBodyWriter> __unsafe_unretained _writer;
|
||||
}
|
||||
@end
|
||||
@@ -238,6 +241,7 @@
|
||||
}
|
||||
|
||||
_decoders = [[NSMutableArray alloc] init];
|
||||
_attributes = [[NSMutableDictionary alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -252,6 +256,7 @@
|
||||
ARC_RELEASE(_modifiedSince);
|
||||
ARC_RELEASE(_noneMatch);
|
||||
ARC_RELEASE(_decoders);
|
||||
ARC_RELEASE(_attributes);
|
||||
|
||||
ARC_DEALLOC(super);
|
||||
}
|
||||
@@ -264,6 +269,10 @@
|
||||
return GCDWebServerIsValidByteRange(_range);
|
||||
}
|
||||
|
||||
- (id)attributeForKey:(NSString*)key {
|
||||
return [_attributes objectForKey:key];
|
||||
}
|
||||
|
||||
- (BOOL)open:(NSError**)error {
|
||||
return YES;
|
||||
}
|
||||
@@ -307,6 +316,10 @@
|
||||
return [_writer close:error];
|
||||
}
|
||||
|
||||
- (void)setAttribute:(id)attribute forKey:(NSString*)key {
|
||||
[_attributes setValue:attribute forKey:key];
|
||||
}
|
||||
|
||||
- (NSString*)description {
|
||||
NSMutableString* description = [NSMutableString stringWithFormat:@"%@ %@", _method, _path];
|
||||
for (NSString* argument in [[_query allKeys] sortedArrayUsingSelector:@selector(compare:)]) {
|
||||
|
||||
Reference in New Issue
Block a user