mirror of
https://github.com/swisspol/GCDWebServer.git
synced 2026-03-17 00:00:02 +08:00
Added support for third-party logging facilities
This commit is contained in:
@@ -30,21 +30,6 @@
|
||||
#import "GCDWebServerRequest.h"
|
||||
#import "GCDWebServerResponse.h"
|
||||
|
||||
/**
|
||||
* Log levels used by GCDWebServer.
|
||||
*
|
||||
* @warning kGCDWebServerLogLevel_Debug is only functional if the preprocessor
|
||||
* constant "DEBUG" is is non-zero at build time.
|
||||
*/
|
||||
typedef NS_ENUM(int, GCDWebServerLogLevel) {
|
||||
kGCDWebServerLogLevel_Debug = 0,
|
||||
kGCDWebServerLogLevel_Verbose,
|
||||
kGCDWebServerLogLevel_Info,
|
||||
kGCDWebServerLogLevel_Warning,
|
||||
kGCDWebServerLogLevel_Error,
|
||||
kGCDWebServerLogLevel_Exception,
|
||||
};
|
||||
|
||||
/**
|
||||
* The GCDWebServerMatchBlock is called for every handler added to the
|
||||
* GCDWebServer whenever a new HTTP request has started (i.e. HTTP headers have
|
||||
@@ -482,43 +467,76 @@ extern NSString* const GCDWebServerAuthenticationMethod_DigestAccess;
|
||||
|
||||
@end
|
||||
|
||||
/**
|
||||
* GCDWebServer provides its own built-in logging facility which is used by
|
||||
* default. It simply sends log messages to stderr assuming it is connected
|
||||
* to a terminal type device.
|
||||
*
|
||||
* GCDWebServer is also compatible with a limited set of third-party logging
|
||||
* facilities. If one of them is available at compile time, GCDWebServer will
|
||||
* automatically use it in place of the built-in one.
|
||||
*
|
||||
* Currently supported third-party logging facilities are:
|
||||
* - XLFacility (by the same author as GCDWebServer): https://github.com/swisspol/XLFacility
|
||||
* - CocoaLumberjack: https://github.com/CocoaLumberjack/CocoaLumberjack
|
||||
*
|
||||
* For both the built-in logging facility and CocoaLumberjack, the default
|
||||
* logging level is INFO (or DEBUG if the preprocessor constant "DEBUG"
|
||||
* evaluates to non-zero at compile time).
|
||||
*
|
||||
* It's possible to have GCDWebServer use a custom logging facility by defining
|
||||
* the "__GCDWEBSERVER_LOGGING_HEADER__" preprocessor constant in Xcode build
|
||||
* settings to the name of a custom header file (escaped like \"MyLogging.h\").
|
||||
* This header file must define the following set of macros:
|
||||
*
|
||||
* GWS_LOG_DEBUG(...)
|
||||
* GWS_LOG_VERBOSE(...)
|
||||
* GWS_LOG_INFO(...)
|
||||
* GWS_LOG_WARNING(...)
|
||||
* GWS_LOG_ERROR(...)
|
||||
* GWS_LOG_EXCEPTION(__EXCEPTION__)
|
||||
*
|
||||
* IMPORTANT: Except for GWS_LOG_EXCEPTION() which gets passed an NSException,
|
||||
* these macros must behave like NSLog(). Furthermore the GWS_LOG_DEBUG() macro
|
||||
* should not do anything unless the preprocessor constant "DEBUG" evaluates to
|
||||
* non-zero.
|
||||
*
|
||||
* The logging methods below send log messages to the same logging facility
|
||||
* used by GCDWebServer. They can be used for consistency wherever you interact
|
||||
* with GCDWebServer in your code (e.g. in the implementation of handlers).
|
||||
*/
|
||||
@interface GCDWebServer (Logging)
|
||||
|
||||
#ifndef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
|
||||
/**
|
||||
* Sets the current log level below which logged messages are discarded.
|
||||
* Sets the log level of the logging facility below which log messages are discarded.
|
||||
*
|
||||
* The default level is INFO (or DEBUG if the preprocessor constant "DEBUG"
|
||||
* is non-zero at build time).
|
||||
* It can also be set at run time with the "logLevel" environment variable.
|
||||
* @warning The interpretation of the "level" argument depends on the logging
|
||||
* facility used at compile time.
|
||||
*/
|
||||
+ (void)setLogLevel:(GCDWebServerLogLevel)level;
|
||||
|
||||
#endif
|
||||
+ (void)setLogLevel:(int)level;
|
||||
|
||||
/**
|
||||
* Logs a message with the kGCDWebServerLogLevel_Verbose level.
|
||||
* Logs a message to the logging facility at the VERBOSE level.
|
||||
*/
|
||||
- (void)logVerbose:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||
|
||||
/**
|
||||
* Logs a message with the kGCDWebServerLogLevel_Info level.
|
||||
* Logs a message to the logging facility at the INFO level.
|
||||
*/
|
||||
- (void)logInfo:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||
|
||||
/**
|
||||
* Logs a message with the kGCDWebServerLogLevel_Warning level.
|
||||
* Logs a message to the logging facility at the WARNING level.
|
||||
*/
|
||||
- (void)logWarning:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||
|
||||
/**
|
||||
* Logs a message with the kGCDWebServerLogLevel_Error level.
|
||||
* Logs a message to the logging facility at the ERROR level.
|
||||
*/
|
||||
- (void)logError:(NSString*)format, ... NS_FORMAT_FUNCTION(1,2);
|
||||
|
||||
/**
|
||||
* Logs an exception with the kGCDWebServerLogLevel_Exception level.
|
||||
* Logs an exception to the logging facility at the EXCEPTION level.
|
||||
*/
|
||||
- (void)logException:(NSException*)exception;
|
||||
|
||||
|
||||
@@ -61,11 +61,17 @@ NSString* const GCDWebServerOption_AutomaticallySuspendInBackground = @"Automati
|
||||
NSString* const GCDWebServerAuthenticationMethod_Basic = @"Basic";
|
||||
NSString* const GCDWebServerAuthenticationMethod_DigestAccess = @"DigestAccess";
|
||||
|
||||
#ifndef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
#if defined(__GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__)
|
||||
#if DEBUG
|
||||
GCDWebServerLogLevel GCDLogLevel = kGCDWebServerLogLevel_Debug;
|
||||
GCDWebServerLoggingLevel GCDWebServerLogLevel = kGCDWebServerLoggingLevel_Debug;
|
||||
#else
|
||||
GCDWebServerLogLevel GCDLogLevel = kGCDWebServerLogLevel_Info;
|
||||
GCDWebServerLoggingLevel GCDWebServerLogLevel = kGCDWebServerLoggingLevel_Info;
|
||||
#endif
|
||||
#elif defined(__GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__)
|
||||
#if DEBUG
|
||||
int GCDWebServerLogLevel = LOG_LEVEL_DEBUG;
|
||||
#else
|
||||
int GCDWebServerLogLevel = LOG_LEVEL_INFO;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -73,16 +79,22 @@ GCDWebServerLogLevel GCDLogLevel = kGCDWebServerLogLevel_Info;
|
||||
static BOOL _run;
|
||||
#endif
|
||||
|
||||
#ifndef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
#ifdef __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
|
||||
|
||||
void GCDLogMessage(GCDWebServerLogLevel level, NSString* format, ...) {
|
||||
void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) {
|
||||
static const char* levelNames[] = {"DEBUG", "VERBOSE", "INFO", "WARNING", "ERROR", "EXCEPTION"};
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||
va_end(arguments);
|
||||
fprintf(stderr, "[%s] %s\n", levelNames[level], [message UTF8String]);
|
||||
ARC_RELEASE(message);
|
||||
static int enableLogging = -1;
|
||||
if (enableLogging < 0) {
|
||||
enableLogging = (isatty(STDERR_FILENO) ? 1 : 0);
|
||||
}
|
||||
if (enableLogging) {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
NSString* message = [[NSString alloc] initWithFormat:format arguments:arguments];
|
||||
va_end(arguments);
|
||||
fprintf(stderr, "[%s] %s\n", levelNames[level], [message UTF8String]);
|
||||
ARC_RELEASE(message);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -177,17 +189,6 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
authenticationBasicAccounts=_authenticationBasicAccounts, authenticationDigestAccounts=_authenticationDigestAccounts,
|
||||
shouldAutomaticallyMapHEADToGET=_mapHEADToGET;
|
||||
|
||||
#ifndef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
|
||||
+ (void)load {
|
||||
const char* logLevel = getenv("logLevel");
|
||||
if (logLevel) {
|
||||
GCDLogLevel = atoi(logLevel);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+ (void)initialize {
|
||||
GCDWebServerInitializeFunctions();
|
||||
}
|
||||
@@ -205,10 +206,10 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
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
|
||||
GWS_DCHECK(_connected == NO);
|
||||
GWS_DCHECK(_activeConnections == 0);
|
||||
GWS_DCHECK(_options == nil); // The server can never be dealloc'ed while running because of the retain-cycle with the dispatch source
|
||||
GWS_DCHECK(_disconnectTimer == NULL); // The server can never be dealloc'ed while the disconnect timer is pending because of the retain-cycle
|
||||
|
||||
ARC_RELEASE(_handlers);
|
||||
ARC_DISPATCH_RELEASE(_sourceSemaphore);
|
||||
@@ -221,17 +222,17 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
|
||||
// Always called on main thread
|
||||
- (void)_startBackgroundTask {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
if (_backgroundTask == UIBackgroundTaskInvalid) {
|
||||
LOG_DEBUG(@"Did start background task");
|
||||
GWS_LOG_DEBUG(@"Did start background task");
|
||||
_backgroundTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
|
||||
|
||||
LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]);
|
||||
GWS_LOG_WARNING(@"Application is being suspended while %@ is still connected", [self class]);
|
||||
[self _endBackgroundTask];
|
||||
|
||||
}];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,10 +240,10 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
|
||||
// Always called on main thread
|
||||
- (void)_didConnect {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
DCHECK(_connected == NO);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK(_connected == NO);
|
||||
_connected = YES;
|
||||
LOG_DEBUG(@"Did connect");
|
||||
GWS_LOG_DEBUG(@"Did connect");
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
[self _startBackgroundTask];
|
||||
@@ -256,7 +257,7 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
- (void)willStartConnection:(GCDWebServerConnection*)connection {
|
||||
dispatch_sync(_syncQueue, ^{
|
||||
|
||||
DCHECK(_activeConnections >= 0);
|
||||
GWS_DCHECK(_activeConnections >= 0);
|
||||
if (_activeConnections == 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (_disconnectTimer) {
|
||||
@@ -278,16 +279,16 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
|
||||
// Always called on main thread
|
||||
- (void)_endBackgroundTask {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
if (_backgroundTask != UIBackgroundTaskInvalid) {
|
||||
if (_suspendInBackground && ([[UIApplication sharedApplication] applicationState] == UIApplicationStateBackground) && _source) {
|
||||
[self _stop];
|
||||
}
|
||||
[[UIApplication sharedApplication] endBackgroundTask:_backgroundTask];
|
||||
_backgroundTask = UIBackgroundTaskInvalid;
|
||||
LOG_DEBUG(@"Did end background task");
|
||||
GWS_LOG_DEBUG(@"Did end background task");
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,10 +296,10 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
|
||||
// Always called on main thread
|
||||
- (void)_didDisconnect {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
DCHECK(_connected == YES);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK(_connected == YES);
|
||||
_connected = NO;
|
||||
LOG_DEBUG(@"Did disconnect");
|
||||
GWS_LOG_DEBUG(@"Did disconnect");
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
[self _endBackgroundTask];
|
||||
@@ -311,7 +312,7 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
|
||||
- (void)didEndConnection:(GCDWebServerConnection*)connection {
|
||||
dispatch_sync(_syncQueue, ^{
|
||||
DCHECK(_activeConnections > 0);
|
||||
GWS_DCHECK(_activeConnections > 0);
|
||||
_activeConnections -= 1;
|
||||
if (_activeConnections == 0) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@@ -321,7 +322,7 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
CFRelease(_disconnectTimer);
|
||||
}
|
||||
_disconnectTimer = CFRunLoopTimerCreateWithHandler(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent() + _disconnectDelay, 0.0, 0, 0, ^(CFRunLoopTimerRef timer) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
[self _didDisconnect];
|
||||
CFRelease(_disconnectTimer);
|
||||
_disconnectTimer = NULL;
|
||||
@@ -352,40 +353,40 @@ static void _ExecuteMainThreadRunLoopSources() {
|
||||
}
|
||||
|
||||
- (void)addHandlerWithMatchBlock:(GCDWebServerMatchBlock)matchBlock asyncProcessBlock:(GCDWebServerAsyncProcessBlock)processBlock {
|
||||
DCHECK(_options == nil);
|
||||
GWS_DCHECK(_options == nil);
|
||||
GCDWebServerHandler* handler = [[GCDWebServerHandler alloc] initWithMatchBlock:matchBlock asyncProcessBlock:processBlock];
|
||||
[_handlers insertObject:handler atIndex:0];
|
||||
ARC_RELEASE(handler);
|
||||
}
|
||||
|
||||
- (void)removeAllHandlers {
|
||||
DCHECK(_options == nil);
|
||||
GWS_DCHECK(_options == nil);
|
||||
[_handlers removeAllObjects];
|
||||
}
|
||||
|
||||
static void _NetServiceRegisterCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
@autoreleasepool {
|
||||
if (error->error) {
|
||||
LOG_ERROR(@"Bonjour registration error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||
GWS_LOG_ERROR(@"Bonjour registration error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||
} else {
|
||||
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
||||
LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]);
|
||||
GWS_LOG_VERBOSE(@"Bonjour registration complete for %@", [server class]);
|
||||
CFNetServiceResolveWithTimeout(server->_resolutionService, 1.0, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _NetServiceResolveCallBack(CFNetServiceRef service, CFStreamError* error, void* info) {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
@autoreleasepool {
|
||||
if (error->error) {
|
||||
if ((error->domain != kCFStreamErrorDomainNetServices) && (error->error != kCFNetServicesErrorTimeout)) {
|
||||
LOG_ERROR(@"Bonjour resolution error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||
GWS_LOG_ERROR(@"Bonjour resolution error %i (domain %i)", (int)error->error, (int)error->domain);
|
||||
}
|
||||
} else {
|
||||
GCDWebServer* server = (ARC_BRIDGE GCDWebServer*)info;
|
||||
LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
|
||||
GWS_LOG_INFO(@"%@ now reachable at %@", [server class], server.bonjourServerURL);
|
||||
if ([server.delegate respondsToSelector:@selector(webServerDidCompleteBonjourRegistration:)]) {
|
||||
[server.delegate webServerDidCompleteBonjourRegistration:server];
|
||||
}
|
||||
@@ -409,7 +410,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
}
|
||||
|
||||
- (BOOL)_start:(NSError**)error {
|
||||
DCHECK(_source == NULL);
|
||||
GWS_DCHECK(_source == NULL);
|
||||
|
||||
NSUInteger port = [_GetOption(_options, GCDWebServerOption_Port, @0) unsignedIntegerValue];
|
||||
NSString* bonjourName = _GetOption(_options, GCDWebServerOption_BonjourName, @"");
|
||||
@@ -428,7 +429,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
addr4.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (bind(listeningSocket, (void*)&addr4, sizeof(addr4)) == 0) {
|
||||
if (listen(listeningSocket, (int)maxPendingConnections) == 0) {
|
||||
LOG_DEBUG(@"Did open listening socket %i", listeningSocket);
|
||||
GWS_LOG_DEBUG(@"Did open listening socket %i", listeningSocket);
|
||||
_serverName = [_GetOption(_options, GCDWebServerOption_ServerName, NSStringFromClass([self class])) copy];
|
||||
NSString* authenticationMethod = _GetOption(_options, GCDWebServerOption_AuthenticationMethod, nil);
|
||||
if ([authenticationMethod isEqualToString:GCDWebServerAuthenticationMethod_Basic]) {
|
||||
@@ -455,9 +456,9 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
@autoreleasepool {
|
||||
int result = close(listeningSocket);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(@"Failed closing listening socket: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed closing listening socket: %s (%i)", strerror(errno), errno);
|
||||
} else {
|
||||
LOG_DEBUG(@"Did close listening socket %i", listeningSocket);
|
||||
GWS_LOG_DEBUG(@"Did close listening socket %i", listeningSocket);
|
||||
}
|
||||
}
|
||||
dispatch_semaphore_signal(_sourceSemaphore);
|
||||
@@ -478,7 +479,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
if (getsockname(socket, &localSockAddr, &localAddrLen) == 0) {
|
||||
localAddress = [NSData dataWithBytes:&localSockAddr length:localAddrLen];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
|
||||
int noSigPipe = 1;
|
||||
@@ -491,7 +492,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
[connection release];
|
||||
#endif
|
||||
} else {
|
||||
LOG_ERROR(@"Failed accepting socket: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed accepting socket: %s (%i)", strerror(errno), errno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -504,7 +505,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
struct sockaddr_in* sockaddr = (struct sockaddr_in*)&addr;
|
||||
_port = ntohs(sockaddr->sin_port);
|
||||
} else {
|
||||
LOG_ERROR(@"Failed retrieving socket address: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed retrieving socket address: %s (%i)", strerror(errno), errno);
|
||||
}
|
||||
} else {
|
||||
_port = port;
|
||||
@@ -526,12 +527,12 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
CFNetServiceScheduleWithRunLoop(_resolutionService, CFRunLoopGetMain(), kCFRunLoopCommonModes);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Failed creating CFNetService");
|
||||
GWS_LOG_ERROR(@"Failed creating CFNetService");
|
||||
}
|
||||
}
|
||||
|
||||
dispatch_resume(_source);
|
||||
LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL);
|
||||
GWS_LOG_INFO(@"%@ started on port %i and reachable at %@", [self class], (int)_port, self.serverURL);
|
||||
if ([_delegate respondsToSelector:@selector(webServerDidStart:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_delegate webServerDidStart:self];
|
||||
@@ -541,27 +542,27 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
if (error) {
|
||||
*error = GCDWebServerMakePosixError(errno);
|
||||
}
|
||||
LOG_ERROR(@"Failed starting listening socket: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed starting listening socket: %s (%i)", strerror(errno), errno);
|
||||
close(listeningSocket);
|
||||
}
|
||||
} else {
|
||||
if (error) {
|
||||
*error = GCDWebServerMakePosixError(errno);
|
||||
}
|
||||
LOG_ERROR(@"Failed binding listening socket: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed binding listening socket: %s (%i)", strerror(errno), errno);
|
||||
close(listeningSocket);
|
||||
}
|
||||
} else {
|
||||
if (error) {
|
||||
*error = GCDWebServerMakePosixError(errno);
|
||||
}
|
||||
LOG_ERROR(@"Failed creating listening socket: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed creating listening socket: %s (%i)", strerror(errno), errno);
|
||||
}
|
||||
return (_source ? YES : NO);
|
||||
}
|
||||
|
||||
- (void)_stop {
|
||||
DCHECK(_source != NULL);
|
||||
GWS_DCHECK(_source != NULL);
|
||||
|
||||
if (_registrationService) {
|
||||
if (_resolutionService) {
|
||||
@@ -602,7 +603,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
}
|
||||
});
|
||||
|
||||
LOG_INFO(@"%@ stopped", [self class]);
|
||||
GWS_LOG_INFO(@"%@ stopped", [self class]);
|
||||
if ([_delegate respondsToSelector:@selector(webServerDidStop:)]) {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_delegate webServerDidStop:self];
|
||||
@@ -613,16 +614,16 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
#if TARGET_OS_IPHONE
|
||||
|
||||
- (void)_didEnterBackground:(NSNotification*)notification {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
LOG_DEBUG(@"Did enter background");
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
GWS_LOG_DEBUG(@"Did enter background");
|
||||
if ((_backgroundTask == UIBackgroundTaskInvalid) && _source) {
|
||||
[self _stop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_willEnterForeground:(NSNotification*)notification {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
LOG_DEBUG(@"Will enter foreground");
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
GWS_LOG_DEBUG(@"Will enter foreground");
|
||||
if (!_source) {
|
||||
[self _start:NULL]; // TODO: There's probably nothing we can do on failure
|
||||
}
|
||||
@@ -652,7 +653,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
#endif
|
||||
return YES;
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
@@ -675,7 +676,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
ARC_RELEASE(_options);
|
||||
_options = nil;
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -733,7 +734,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
}
|
||||
|
||||
- (BOOL)runWithOptions:(NSDictionary*)options error:(NSError**)error {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
BOOL success = NO;
|
||||
_run = YES;
|
||||
void (*termHandler)(int) = signal(SIGTERM, _SignalHandler);
|
||||
@@ -796,7 +797,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
|
||||
} asyncProcessBlock:block];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -834,7 +835,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
|
||||
} asyncProcessBlock:block];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -881,7 +882,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
if (![file hasPrefix:@"."]) {
|
||||
NSString* type = [[enumerator fileAttributes] objectForKey:NSFileType];
|
||||
NSString* escapedFile = [file stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
|
||||
DCHECK(escapedFile);
|
||||
GWS_DCHECK(escapedFile);
|
||||
if ([type isEqualToString:NSFileTypeRegular]) {
|
||||
[html appendFormat:@"<li><a href=\"%@\">%@</a></li>\n", escapedFile, file];
|
||||
} else if ([type isEqualToString:NSFileTypeDirectory]) {
|
||||
@@ -945,7 +946,7 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
|
||||
}];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -953,44 +954,46 @@ static inline NSString* _EncodeBase64(NSString* string) {
|
||||
|
||||
@implementation GCDWebServer (Logging)
|
||||
|
||||
#ifndef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
|
||||
+ (void)setLogLevel:(GCDWebServerLogLevel)level {
|
||||
GCDLogLevel = level;
|
||||
}
|
||||
|
||||
+ (void)setLogLevel:(int)level {
|
||||
#if defined(__GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__)
|
||||
[XLSharedFacility setMinLogLevel:level];
|
||||
#elif defined(__GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__)
|
||||
GCDWebServerLogLevel = level;
|
||||
#else
|
||||
GCDWebServerLogLevel = level;
|
||||
#endif
|
||||
}
|
||||
|
||||
- (void)logVerbose:(NSString*)format, ... {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
LOG_VERBOSE(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
GWS_LOG_VERBOSE(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
- (void)logInfo:(NSString*)format, ... {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
LOG_INFO(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
GWS_LOG_INFO(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
- (void)logWarning:(NSString*)format, ... {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
LOG_WARNING(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
GWS_LOG_WARNING(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
- (void)logError:(NSString*)format, ... {
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
LOG_ERROR(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
GWS_LOG_ERROR(@"%@", ARC_AUTORELEASE([[NSString alloc] initWithFormat:format arguments:arguments]));
|
||||
va_end(arguments);
|
||||
}
|
||||
|
||||
- (void)logException:(NSException*)exception {
|
||||
LOG_EXCEPTION(exception);
|
||||
GWS_LOG_EXCEPTION(exception);
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -1047,7 +1050,7 @@ static CFHTTPMessageRef _CreateHTTPMessageFromPerformingRequest(NSData* inData,
|
||||
outData.length = length;
|
||||
response = _CreateHTTPMessageFromData(outData, NO);
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
ARC_RELEASE(outData);
|
||||
}
|
||||
@@ -1067,7 +1070,7 @@ static void _LogResult(NSString* format, ...) {
|
||||
}
|
||||
|
||||
- (NSInteger)runTestsWithOptions:(NSDictionary*)options inDirectory:(NSString*)path {
|
||||
DCHECK([NSThread isMainThread]);
|
||||
GWS_DCHECK([NSThread isMainThread]);
|
||||
NSArray* ignoredHeaders = @[@"Date", @"Etag"]; // Dates are always different by definition and ETags depend on file system node IDs
|
||||
NSInteger result = -1;
|
||||
if ([self startWithOptions:options error:NULL]) {
|
||||
@@ -1159,7 +1162,7 @@ static void _LogResult(NSString* format, ...) {
|
||||
CFRelease(expectedResponse);
|
||||
}
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1167,7 +1170,7 @@ static void _LogResult(NSString* format, ...) {
|
||||
CFRelease(request);
|
||||
}
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
_LogResult(@"");
|
||||
if (!success) {
|
||||
|
||||
@@ -99,14 +99,14 @@ static int32_t _connectionCounter = 0;
|
||||
block(YES);
|
||||
} else {
|
||||
if (_bytesRead > 0) {
|
||||
LOG_ERROR(@"No more data available on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"No more data available on socket %i", _socket);
|
||||
} else {
|
||||
LOG_WARNING(@"No data received from socket %i", _socket);
|
||||
GWS_LOG_WARNING(@"No data received from socket %i", _socket);
|
||||
}
|
||||
block(NO);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error);
|
||||
GWS_LOG_ERROR(@"Error while reading from socket %i: %s (%i)", _socket, strerror(error), error);
|
||||
block(NO);
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ static int32_t _connectionCounter = 0;
|
||||
}
|
||||
|
||||
- (void)_readHeaders:(NSMutableData*)headersData withCompletionBlock:(ReadHeadersCompletionBlock)block {
|
||||
DCHECK(_requestMessage);
|
||||
GWS_DCHECK(_requestMessage);
|
||||
[self _readData:headersData withLength:NSUIntegerMax completionBlock:^(BOOL success) {
|
||||
|
||||
if (success) {
|
||||
@@ -128,11 +128,11 @@ static int32_t _connectionCounter = 0;
|
||||
if (CFHTTPMessageIsHeaderComplete(_requestMessage)) {
|
||||
block([headersData subdataWithRange:NSMakeRange(length, headersData.length - length)]);
|
||||
} else {
|
||||
LOG_ERROR(@"Failed parsing request headers from socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Failed parsing request headers from socket %i", _socket);
|
||||
block(nil);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Failed appending request headers data from socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Failed appending request headers data from socket %i", _socket);
|
||||
block(nil);
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ static int32_t _connectionCounter = 0;
|
||||
}
|
||||
|
||||
- (void)_readBodyWithRemainingLength:(NSUInteger)length completionBlock:(ReadBodyCompletionBlock)block {
|
||||
DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]);
|
||||
GWS_DCHECK([_request hasBody] && ![_request usesChunkedTransferEncoding]);
|
||||
NSMutableData* bodyData = [[NSMutableData alloc] initWithCapacity:kBodyReadCapacity];
|
||||
[self _readData:bodyData withLength:length completionBlock:^(BOOL success) {
|
||||
|
||||
@@ -159,13 +159,13 @@ static int32_t _connectionCounter = 0;
|
||||
block(YES);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
block(NO);
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Unexpected extra content reading request body on socket %i", _socket);
|
||||
block(NO);
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
} else {
|
||||
block(NO);
|
||||
@@ -185,7 +185,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
|
||||
- (void)_readNextBodyChunk:(NSMutableData*)chunkData completionBlock:(ReadBodyCompletionBlock)block {
|
||||
DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]);
|
||||
GWS_DCHECK([_request hasBody] && [_request usesChunkedTransferEncoding]);
|
||||
|
||||
while (1) {
|
||||
NSRange range = [chunkData rangeOfData:_CRLFData options:0 range:NSMakeRange(0, chunkData.length)];
|
||||
@@ -205,12 +205,12 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
if ([_request performWriteData:[chunkData subdataWithRange:NSMakeRange(range.location + range.length, length)] error:&error]) {
|
||||
[chunkData replaceBytesInRange:NSMakeRange(0, range.location + range.length + length + 2) withBytes:NULL length:0];
|
||||
} else {
|
||||
LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
block(NO);
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Missing terminating CRLF sequence for chunk reading request body on socket %i", _socket);
|
||||
block(NO);
|
||||
return;
|
||||
}
|
||||
@@ -222,7 +222,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Invalid chunk length reading request body on socket %i", _socket);
|
||||
block(NO);
|
||||
return;
|
||||
}
|
||||
@@ -258,11 +258,11 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
|
||||
@autoreleasepool {
|
||||
if (error == 0) {
|
||||
DCHECK(remainingData == NULL);
|
||||
GWS_DCHECK(remainingData == NULL);
|
||||
[self didWriteBytes:data.bytes length:data.length];
|
||||
block(YES);
|
||||
} else {
|
||||
LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error);
|
||||
GWS_LOG_ERROR(@"Error while writing to socket %i: %s (%i)", _socket, strerror(error), error);
|
||||
block(NO);
|
||||
}
|
||||
}
|
||||
@@ -272,14 +272,14 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
|
||||
- (void)_writeHeadersWithCompletionBlock:(WriteHeadersCompletionBlock)block {
|
||||
DCHECK(_responseMessage);
|
||||
GWS_DCHECK(_responseMessage);
|
||||
CFDataRef data = CFHTTPMessageCopySerializedMessage(_responseMessage);
|
||||
[self _writeData:(ARC_BRIDGE NSData*)data withCompletionBlock:block];
|
||||
CFRelease(data);
|
||||
}
|
||||
|
||||
- (void)_writeBodyWithCompletionBlock:(WriteBodyCompletionBlock)block {
|
||||
DCHECK([_response hasBody]);
|
||||
GWS_DCHECK([_response hasBody]);
|
||||
NSError* error = nil;
|
||||
NSData* data = [_response performReadData:&error];
|
||||
if (data) {
|
||||
@@ -289,7 +289,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
size_t hexLength = strlen(hexString);
|
||||
NSData* chunk = [NSMutableData dataWithLength:(hexLength + 2 + data.length + 2)];
|
||||
if (chunk == nil) {
|
||||
LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed allocating memory for response body chunk for socket %i: %@", _socket, error);
|
||||
block(NO);
|
||||
return;
|
||||
}
|
||||
@@ -325,7 +325,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed reading response body for socket %i: %@", _socket, error);
|
||||
block(NO);
|
||||
}
|
||||
}
|
||||
@@ -339,11 +339,11 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
+ (void)initialize {
|
||||
if (_CRLFData == nil) {
|
||||
_CRLFData = [[NSData alloc] initWithBytes:"\r\n" length:2];
|
||||
DCHECK(_CRLFData);
|
||||
GWS_DCHECK(_CRLFData);
|
||||
}
|
||||
if (_CRLFCRLFData == nil) {
|
||||
_CRLFCRLFData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
|
||||
DCHECK(_CRLFCRLFData);
|
||||
GWS_DCHECK(_CRLFCRLFData);
|
||||
}
|
||||
if (_continueData == nil) {
|
||||
CFHTTPMessageRef message = CFHTTPMessageCreateResponse(kCFAllocatorDefault, 100, NULL, kCFHTTPVersion1_1);
|
||||
@@ -353,7 +353,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
_continueData = (NSData*)CFHTTPMessageCopySerializedMessage(message);
|
||||
#endif
|
||||
CFRelease(message);
|
||||
DCHECK(_continueData);
|
||||
GWS_DCHECK(_continueData);
|
||||
}
|
||||
if (_lastChunkData == nil) {
|
||||
_lastChunkData = [[NSData alloc] initWithBytes:"0\r\n\r\n" length:5];
|
||||
@@ -374,7 +374,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
|
||||
- (void)_startProcessingRequest {
|
||||
DCHECK(_responseMessage == NULL);
|
||||
GWS_DCHECK(_responseMessage == NULL);
|
||||
|
||||
GCDWebServerResponse* preflightResponse = [self preflightRequest:_request];
|
||||
if (preflightResponse) {
|
||||
@@ -388,7 +388,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
|
||||
// http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
||||
- (void)_finishProcessingRequest:(GCDWebServerResponse*)response {
|
||||
DCHECK(_responseMessage == NULL);
|
||||
GWS_DCHECK(_responseMessage == NULL);
|
||||
BOOL hasBody = NO;
|
||||
|
||||
if (response) {
|
||||
@@ -401,7 +401,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
NSError* error = nil;
|
||||
if (hasBody && ![response performOpen:&error]) {
|
||||
LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed opening response body for socket %i: %@", _socket, error);
|
||||
} else {
|
||||
_response = ARC_RETAIN(response);
|
||||
}
|
||||
@@ -458,16 +458,16 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
- (void)_readBodyWithLength:(NSUInteger)length initialData:(NSData*)initialData {
|
||||
NSError* error = nil;
|
||||
if (![_request performOpen:&error]) {
|
||||
LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
return;
|
||||
}
|
||||
|
||||
if (initialData.length) {
|
||||
if (![_request performWriteData:initialData error:&error]) {
|
||||
LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed writing request body on socket %i: %@", _socket, error);
|
||||
if (![_request performClose:&error]) {
|
||||
LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
}
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
return;
|
||||
@@ -482,7 +482,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
if ([_request performClose:&localError]) {
|
||||
[self _startProcessingRequest];
|
||||
} else {
|
||||
LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
}
|
||||
|
||||
@@ -491,7 +491,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
if ([_request performClose:&error]) {
|
||||
[self _startProcessingRequest];
|
||||
} else {
|
||||
LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
}
|
||||
}
|
||||
@@ -500,7 +500,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
- (void)_readChunkedBodyWithInitialData:(NSData*)initialData {
|
||||
NSError* error = nil;
|
||||
if (![_request performOpen:&error]) {
|
||||
LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed opening request body for socket %i: %@", _socket, error);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
return;
|
||||
}
|
||||
@@ -512,7 +512,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
if ([_request performClose:&localError]) {
|
||||
[self _startProcessingRequest];
|
||||
} else {
|
||||
LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
GWS_LOG_ERROR(@"Failed closing request body for socket %i: %@", _socket, error);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
NSURL* requestURL = ARC_BRIDGE_RELEASE(CFHTTPMessageCopyRequestURL(_requestMessage));
|
||||
if (requestURL) {
|
||||
requestURL = [self rewriteRequestURL:requestURL withMethod:requestMethod headers:requestHeaders];
|
||||
DCHECK(requestURL);
|
||||
GWS_DCHECK(requestURL);
|
||||
}
|
||||
NSString* requestPath = requestURL ? GCDWebServerUnescapeURLString(ARC_BRIDGE_RELEASE(CFURLCopyPath((CFURLRef)requestURL))) : nil; // Don't use -[NSURL path] which strips the ending slash
|
||||
NSString* queryString = requestURL ? ARC_BRIDGE_RELEASE(CFURLCopyQueryString((CFURLRef)requestURL, NULL)) : nil; // Don't use -[NSURL query] to make sure query is not unescaped;
|
||||
@@ -566,7 +566,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
|
||||
}];
|
||||
} else {
|
||||
LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Unsupported 'Expect' / 'Content-Length' header combination on socket %i", _socket);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_ExpectationFailed];
|
||||
}
|
||||
} else {
|
||||
@@ -577,7 +577,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
|
||||
GWS_LOG_ERROR(@"Unexpected 'Content-Length' header value on socket %i", _socket);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_BadRequest];
|
||||
}
|
||||
} else {
|
||||
@@ -585,12 +585,12 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
}
|
||||
} else {
|
||||
_request = [[GCDWebServerRequest alloc] initWithMethod:requestMethod url:requestURL headers:requestHeaders path:requestPath query:requestQuery];
|
||||
DCHECK(_request);
|
||||
GWS_DCHECK(_request);
|
||||
[self abortRequest:_request withStatusCode:kGCDWebServerHTTPStatusCode_MethodNotAllowed];
|
||||
}
|
||||
} else {
|
||||
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
} else {
|
||||
[self abortRequest:nil withStatusCode:kGCDWebServerHTTPStatusCode_InternalServerError];
|
||||
@@ -606,7 +606,7 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
|
||||
_localAddress = ARC_RETAIN(localAddress);
|
||||
_remoteAddress = ARC_RETAIN(remoteAddress);
|
||||
_socket = socket;
|
||||
LOG_DEBUG(@"Did open connection on socket %i", _socket);
|
||||
GWS_LOG_DEBUG(@"Did open connection on socket %i", _socket);
|
||||
|
||||
[_server willStartConnection:self];
|
||||
|
||||
@@ -630,7 +630,7 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
if (getnameinfo(addr, addr->sa_len, hostBuffer, sizeof(hostBuffer), serviceBuffer, sizeof(serviceBuffer), NI_NUMERICHOST | NI_NUMERICSERV | NI_NOFQDN) >= 0) {
|
||||
string = [NSString stringWithFormat:@"%s:%s", hostBuffer, serviceBuffer];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
return string;
|
||||
}
|
||||
@@ -646,9 +646,9 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
- (void)dealloc {
|
||||
int result = close(_socket);
|
||||
if (result != 0) {
|
||||
LOG_ERROR(@"Failed closing socket %i for connection: %s (%i)", _socket, strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed closing socket %i for connection: %s (%i)", _socket, strerror(errno), errno);
|
||||
} else {
|
||||
LOG_DEBUG(@"Did close connection on socket %i", _socket);
|
||||
GWS_LOG_DEBUG(@"Did close connection on socket %i", _socket);
|
||||
}
|
||||
|
||||
if (_opened) {
|
||||
@@ -689,11 +689,11 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
|
||||
_requestPath = ARC_RETAIN([NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]);
|
||||
_requestFD = open([_requestPath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
DCHECK(_requestFD > 0);
|
||||
GWS_DCHECK(_requestFD > 0);
|
||||
|
||||
_responsePath = ARC_RETAIN([NSTemporaryDirectory() stringByAppendingPathComponent:[[NSProcessInfo processInfo] globallyUniqueString]]);
|
||||
_responseFD = open([_responsePath fileSystemRepresentation], O_CREAT | O_TRUNC | O_WRONLY, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
||||
DCHECK(_responseFD > 0);
|
||||
GWS_DCHECK(_responseFD > 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -701,12 +701,12 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
}
|
||||
|
||||
- (void)didReadBytes:(const void*)bytes length:(NSUInteger)length {
|
||||
LOG_DEBUG(@"Connection received %lu bytes on socket %i", (unsigned long)length, _socket);
|
||||
GWS_LOG_DEBUG(@"Connection received %lu bytes on socket %i", (unsigned long)length, _socket);
|
||||
_bytesRead += length;
|
||||
|
||||
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||
if ((_requestFD > 0) && (write(_requestFD, bytes, length) != (ssize_t)length)) {
|
||||
LOG_ERROR(@"Failed recording request data: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed recording request data: %s (%i)", strerror(errno), errno);
|
||||
close(_requestFD);
|
||||
_requestFD = 0;
|
||||
}
|
||||
@@ -714,12 +714,12 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
}
|
||||
|
||||
- (void)didWriteBytes:(const void*)bytes length:(NSUInteger)length {
|
||||
LOG_DEBUG(@"Connection sent %lu bytes on socket %i", (unsigned long)length, _socket);
|
||||
GWS_LOG_DEBUG(@"Connection sent %lu bytes on socket %i", (unsigned long)length, _socket);
|
||||
_bytesWritten += length;
|
||||
|
||||
#ifdef __GCDWEBSERVER_ENABLE_TESTING__
|
||||
if ((_responseFD > 0) && (write(_responseFD, bytes, length) != (ssize_t)length)) {
|
||||
LOG_ERROR(@"Failed recording response data: %s (%i)", strerror(errno), errno);
|
||||
GWS_LOG_ERROR(@"Failed recording response data: %s (%i)", strerror(errno), errno);
|
||||
close(_responseFD);
|
||||
_responseFD = 0;
|
||||
}
|
||||
@@ -732,7 +732,7 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
|
||||
// https://tools.ietf.org/html/rfc2617
|
||||
- (GCDWebServerResponse*)preflightRequest:(GCDWebServerRequest*)request {
|
||||
LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
|
||||
GWS_LOG_DEBUG(@"Connection on socket %i preflighting request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
|
||||
GCDWebServerResponse* response = nil;
|
||||
if (_server.authenticationBasicAccounts) {
|
||||
__block BOOL authenticated = NO;
|
||||
@@ -782,12 +782,12 @@ static NSString* _StringFromAddressData(NSData* data) {
|
||||
}
|
||||
|
||||
- (void)processRequest:(GCDWebServerRequest*)request completion:(GCDWebServerCompletionBlock)completion {
|
||||
LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
|
||||
GWS_LOG_DEBUG(@"Connection on socket %i processing request \"%@ %@\" with %lu bytes body", _socket, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead);
|
||||
@try {
|
||||
_handler.asyncProcessBlock(request, completion);
|
||||
}
|
||||
@catch (NSException* exception) {
|
||||
LOG_EXCEPTION(exception);
|
||||
GWS_LOG_EXCEPTION(exception);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -813,20 +813,20 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
|
||||
newResponse.cacheControlMaxAge = response.cacheControlMaxAge;
|
||||
newResponse.lastModifiedDate = response.lastModifiedDate;
|
||||
newResponse.eTag = response.eTag;
|
||||
DCHECK(newResponse);
|
||||
GWS_DCHECK(newResponse);
|
||||
return newResponse;
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
- (void)abortRequest:(GCDWebServerRequest*)request withStatusCode:(NSInteger)statusCode {
|
||||
DCHECK(_responseMessage == NULL);
|
||||
DCHECK((statusCode >= 400) && (statusCode < 600));
|
||||
GWS_DCHECK(_responseMessage == NULL);
|
||||
GWS_DCHECK((statusCode >= 400) && (statusCode < 600));
|
||||
[self _initializeResponseHeadersWithStatusCode:statusCode];
|
||||
[self _writeHeadersWithCompletionBlock:^(BOOL success) {
|
||||
; // Nothing more to do
|
||||
}];
|
||||
LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket);
|
||||
GWS_LOG_DEBUG(@"Connection aborted with status code %i on socket %i", (int)statusCode, _socket);
|
||||
}
|
||||
|
||||
- (void)close {
|
||||
@@ -840,8 +840,8 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
|
||||
success = [[NSFileManager defaultManager] moveItemAtPath:_requestPath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error];
|
||||
}
|
||||
if (!success) {
|
||||
LOG_ERROR(@"Failed saving recorded request: %@", error);
|
||||
DNOT_REACHED();
|
||||
GWS_LOG_ERROR(@"Failed saving recorded request: %@", error);
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
unlink([_requestPath fileSystemRepresentation]);
|
||||
}
|
||||
@@ -855,17 +855,17 @@ static inline BOOL _CompareResources(NSString* responseETag, NSString* requestET
|
||||
success = [[NSFileManager defaultManager] moveItemAtPath:_responsePath toPath:[[[NSFileManager defaultManager] currentDirectoryPath] stringByAppendingPathComponent:name] error:&error];
|
||||
}
|
||||
if (!success) {
|
||||
LOG_ERROR(@"Failed saving recorded response: %@", error);
|
||||
DNOT_REACHED();
|
||||
GWS_LOG_ERROR(@"Failed saving recorded response: %@", error);
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
unlink([_responsePath fileSystemRepresentation]);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (_request) {
|
||||
LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
|
||||
GWS_LOG_VERBOSE(@"[%@] %@ %i \"%@ %@\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, _virtualHEAD ? @"HEAD" : _request.method, _request.path, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
|
||||
} else {
|
||||
LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
|
||||
GWS_LOG_VERBOSE(@"[%@] %@ %i \"(invalid request)\" (%lu | %lu)", self.localAddressString, self.remoteAddressString, (int)_statusCode, (unsigned long)_bytesRead, (unsigned long)_bytesWritten);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -45,24 +45,24 @@ static dispatch_queue_t _dateFormatterQueue = NULL;
|
||||
|
||||
// TODO: Handle RFC 850 and ANSI C's asctime() format
|
||||
void GCDWebServerInitializeFunctions() {
|
||||
DCHECK([NSThread isMainThread]); // NSDateFormatter should be initialized on main thread
|
||||
GWS_DCHECK([NSThread isMainThread]); // NSDateFormatter should be initialized on main thread
|
||||
if (_dateFormatterRFC822 == nil) {
|
||||
_dateFormatterRFC822 = [[NSDateFormatter alloc] init];
|
||||
_dateFormatterRFC822.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
|
||||
_dateFormatterRFC822.dateFormat = @"EEE',' dd MMM yyyy HH':'mm':'ss 'GMT'";
|
||||
_dateFormatterRFC822.locale = ARC_AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]);
|
||||
DCHECK(_dateFormatterRFC822);
|
||||
GWS_DCHECK(_dateFormatterRFC822);
|
||||
}
|
||||
if (_dateFormatterISO8601 == nil) {
|
||||
_dateFormatterISO8601 = [[NSDateFormatter alloc] init];
|
||||
_dateFormatterISO8601.timeZone = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
|
||||
_dateFormatterISO8601.dateFormat = @"yyyy-MM-dd'T'HH:mm:ss'+00:00'";
|
||||
_dateFormatterISO8601.locale = ARC_AUTORELEASE([[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]);
|
||||
DCHECK(_dateFormatterISO8601);
|
||||
GWS_DCHECK(_dateFormatterISO8601);
|
||||
}
|
||||
if (_dateFormatterQueue == NULL) {
|
||||
_dateFormatterQueue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
|
||||
DCHECK(_dateFormatterQueue);
|
||||
GWS_DCHECK(_dateFormatterQueue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ NSDictionary* GCDWebServerParseURLEncodedForm(NSString* form) {
|
||||
if (unescapedKey && unescapedValue) {
|
||||
[parameters setObject:unescapedValue forKey:unescapedKey];
|
||||
} else {
|
||||
LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value);
|
||||
DNOT_REACHED();
|
||||
GWS_LOG_WARNING(@"Failed parsing URL encoded form for key \"%@\" and value \"%@\"", key, value);
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
|
||||
if ([scanner isAtEnd]) {
|
||||
|
||||
@@ -27,6 +27,10 @@
|
||||
|
||||
#import <os/object.h>
|
||||
|
||||
/**
|
||||
* ARC <-> MRC compatibility macros.
|
||||
*/
|
||||
|
||||
#if __has_feature(objc_arc)
|
||||
#define ARC_BRIDGE __bridge
|
||||
#define ARC_BRIDGE_RELEASE(__OBJECT__) CFBridgingRelease(__OBJECT__)
|
||||
@@ -52,6 +56,10 @@
|
||||
#define ARC_DISPATCH_RELEASE(__OBJECT__) dispatch_release(__OBJECT__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* All GCDWebServer headers.
|
||||
*/
|
||||
|
||||
#import "GCDWebServerHTTPStatusCodes.h"
|
||||
#import "GCDWebServerFunctions.h"
|
||||
|
||||
@@ -68,45 +76,122 @@
|
||||
#import "GCDWebServerFileResponse.h"
|
||||
#import "GCDWebServerStreamedResponse.h"
|
||||
|
||||
#ifdef __GCDWEBSERVER_LOGGING_HEADER__
|
||||
/**
|
||||
* Automatically detect if XLFacility is available and if so use it as a
|
||||
* logging facility.
|
||||
*/
|
||||
|
||||
#if defined(__has_include) && __has_include("XLFacilityMacros.h")
|
||||
|
||||
#define __GCDWEBSERVER_LOGGING_FACILITY_XLFACILITY__
|
||||
|
||||
#import "XLFacilityMacros.h"
|
||||
|
||||
#define GWS_LOG_DEBUG(...) XLOG_DEBUG(__VA_ARGS__)
|
||||
#define GWS_LOG_VERBOSE(...) XLOG_VERBOSE(__VA_ARGS__)
|
||||
#define GWS_LOG_INFO(...) XLOG_INFO(__VA_ARGS__)
|
||||
#define GWS_LOG_WARNING(...) XLOG_WARNING(__VA_ARGS__)
|
||||
#define GWS_LOG_ERROR(...) XLOG_ERROR(__VA_ARGS__)
|
||||
#define GWS_LOG_EXCEPTION(__EXCEPTION__) XLOG_EXCEPTION(__EXCEPTION__)
|
||||
|
||||
#define GWS_DCHECK(__CONDITION__) XLOG_DEBUG_CHECK(__CONDITION__)
|
||||
#define GWS_DNOT_REACHED() XLOG_DEBUG_UNREACHABLE()
|
||||
|
||||
/**
|
||||
* Automatically detect if CocoaLumberJack is available and if so use
|
||||
* it as a logging facility.
|
||||
*/
|
||||
|
||||
#elif defined(__has_include) && __has_include("DDLogMacros.h")
|
||||
|
||||
#import "DDLogMacros.h"
|
||||
|
||||
#define __GCDWEBSERVER_LOGGING_FACILITY_COCOALUMBERJACK__
|
||||
|
||||
#undef LOG_LEVEL_DEF
|
||||
#define LOG_LEVEL_DEF GCDWebServerLogLevel
|
||||
extern int GCDWebServerLogLevel;
|
||||
|
||||
#define GWS_LOG_DEBUG(...) DDLogDebug(__VA_ARGS__)
|
||||
#define GWS_LOG_VERBOSE(...) DDLogVerbose(__VA_ARGS__)
|
||||
#define GWS_LOG_INFO(...) DDLogInfo(__VA_ARGS__)
|
||||
#define GWS_LOG_WARNING(...) DDLogWarn(__VA_ARGS__)
|
||||
#define GWS_LOG_ERROR(...) DDLogError(__VA_ARGS__)
|
||||
#define GWS_LOG_EXCEPTION(__EXCEPTION__) DDLogError(@"%@", __EXCEPTION__)
|
||||
|
||||
/**
|
||||
* Check if a custom logging facility should be used instead.
|
||||
*/
|
||||
|
||||
#elif defined(__GCDWEBSERVER_LOGGING_HEADER__)
|
||||
|
||||
#define __GCDWEBSERVER_LOGGING_FACILITY_CUSTOM__
|
||||
|
||||
// Define __GCDWEBSERVER_LOGGING_HEADER__ as a preprocessor constant to redirect GCDWebServer logging to your own system
|
||||
// This can be done in Xcode build settings like this:
|
||||
// GCC_PREPROCESSOR_DEFINITIONS_NOT_USED_IN_PRECOMPS = __GCDWEBSERVER_LOGGING_HEADER__=\"MyLoggingHeader.h\"
|
||||
#import __GCDWEBSERVER_LOGGING_HEADER__
|
||||
|
||||
/**
|
||||
* If all of the above fail, then use GCDWebServer built-in
|
||||
* logging facility.
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
extern GCDWebServerLogLevel GCDLogLevel;
|
||||
extern void GCDLogMessage(GCDWebServerLogLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3);
|
||||
#define __GCDWEBSERVER_LOGGING_FACILITY_BUILTIN__
|
||||
|
||||
#define LOG_VERBOSE(...) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Verbose) GCDLogMessage(kGCDWebServerLogLevel_Verbose, __VA_ARGS__); } while (0)
|
||||
#define LOG_INFO(...) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Info) GCDLogMessage(kGCDWebServerLogLevel_Info, __VA_ARGS__); } while (0)
|
||||
#define LOG_WARNING(...) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Warning) GCDLogMessage(kGCDWebServerLogLevel_Warning, __VA_ARGS__); } while (0)
|
||||
#define LOG_ERROR(...) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Error) GCDLogMessage(kGCDWebServerLogLevel_Error, __VA_ARGS__); } while (0)
|
||||
#define LOG_EXCEPTION(__EXCEPTION__) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Exception) GCDLogMessage(kGCDWebServerLogLevel_Exception, @"%@", __EXCEPTION__); } while (0)
|
||||
typedef NS_ENUM(int, GCDWebServerLoggingLevel) {
|
||||
kGCDWebServerLoggingLevel_Debug = 0,
|
||||
kGCDWebServerLoggingLevel_Verbose,
|
||||
kGCDWebServerLoggingLevel_Info,
|
||||
kGCDWebServerLoggingLevel_Warning,
|
||||
kGCDWebServerLoggingLevel_Error,
|
||||
kGCDWebServerLoggingLevel_Exception,
|
||||
};
|
||||
|
||||
extern GCDWebServerLoggingLevel GCDWebServerLogLevel;
|
||||
extern void GCDWebServerLogMessage(GCDWebServerLoggingLevel level, NSString* format, ...) NS_FORMAT_FUNCTION(2, 3);
|
||||
|
||||
#if DEBUG
|
||||
#define GWS_LOG_DEBUG(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Debug) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Debug, __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define GWS_LOG_DEBUG(...)
|
||||
#endif
|
||||
#define GWS_LOG_VERBOSE(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Verbose) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Verbose, __VA_ARGS__); } while (0)
|
||||
#define GWS_LOG_INFO(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Info) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Info, __VA_ARGS__); } while (0)
|
||||
#define GWS_LOG_WARNING(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Warning) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Warning, __VA_ARGS__); } while (0)
|
||||
#define GWS_LOG_ERROR(...) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Error) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Error, __VA_ARGS__); } while (0)
|
||||
#define GWS_LOG_EXCEPTION(__EXCEPTION__) do { if (GCDWebServerLogLevel <= kGCDWebServerLoggingLevel_Exception) GCDWebServerLogMessage(kGCDWebServerLoggingLevel_Exception, @"%@", __EXCEPTION__); } while (0)
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Consistency check macros used when building Debug only.
|
||||
*/
|
||||
|
||||
#if !defined(GWS_DCHECK) || !defined(GWS_DNOT_REACHED)
|
||||
|
||||
#if DEBUG
|
||||
|
||||
#define DCHECK(__CONDITION__) \
|
||||
#define GWS_DCHECK(__CONDITION__) \
|
||||
do { \
|
||||
if (!(__CONDITION__)) { \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#define DNOT_REACHED() abort()
|
||||
#define LOG_DEBUG(...) do { if (GCDLogLevel <= kGCDWebServerLogLevel_Debug) GCDLogMessage(kGCDWebServerLogLevel_Debug, __VA_ARGS__); } while (0)
|
||||
#define GWS_DNOT_REACHED() abort()
|
||||
|
||||
#else
|
||||
|
||||
#define DCHECK(__CONDITION__)
|
||||
#define DNOT_REACHED()
|
||||
#define LOG_DEBUG(...)
|
||||
#define GWS_DCHECK(__CONDITION__)
|
||||
#define GWS_DNOT_REACHED()
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* GCDWebServer internal constants and APIs.
|
||||
*/
|
||||
|
||||
#define kGCDWebServerDefaultMimeType @"application/octet-stream"
|
||||
#define kGCDWebServerGCDQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
|
||||
#define kGCDWebServerErrorDomain @"GCDWebServerErrorDomain"
|
||||
|
||||
@@ -95,12 +95,12 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
}
|
||||
|
||||
- (BOOL)writeData:(NSData*)data error:(NSError**)error {
|
||||
DCHECK(!_finished);
|
||||
GWS_DCHECK(!_finished);
|
||||
_stream.next_in = (Bytef*)data.bytes;
|
||||
_stream.avail_in = (uInt)data.length;
|
||||
NSMutableData* decodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize];
|
||||
if (decodedData == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
return NO;
|
||||
}
|
||||
NSUInteger length = 0;
|
||||
@@ -130,7 +130,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
}
|
||||
|
||||
- (BOOL)close:(NSError**)error {
|
||||
DCHECK(_finished);
|
||||
GWS_DCHECK(_finished);
|
||||
inflateEnd(&_stream);
|
||||
return [super close:error];
|
||||
}
|
||||
@@ -178,7 +178,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
if (lengthHeader) {
|
||||
NSInteger length = [lengthHeader integerValue];
|
||||
if (_chunked || (length < 0)) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -193,7 +193,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
_length = NSUIntegerMax;
|
||||
} else {
|
||||
if (_type) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -232,7 +232,7 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
}
|
||||
}
|
||||
if ((_range.location == NSUIntegerMax) && (_range.length == 0)) { // Ignore "Range" header if syntactically invalid
|
||||
LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url);
|
||||
GWS_LOG_WARNING(@"Failed to parse 'Range' header \"%@\" for url: %@", rangeHeader, url);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,10 +296,10 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
}
|
||||
|
||||
- (BOOL)performOpen:(NSError**)error {
|
||||
DCHECK(_type);
|
||||
DCHECK(_writer);
|
||||
GWS_DCHECK(_type);
|
||||
GWS_DCHECK(_writer);
|
||||
if (_opened) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
return NO;
|
||||
}
|
||||
_opened = YES;
|
||||
@@ -307,12 +307,12 @@ NSString* const GCDWebServerRequestAttribute_RegexCaptures = @"GCDWebServerReque
|
||||
}
|
||||
|
||||
- (BOOL)performWriteData:(NSData*)data error:(NSError**)error {
|
||||
DCHECK(_opened);
|
||||
GWS_DCHECK(_opened);
|
||||
return [_writer writeData:data error:error];
|
||||
}
|
||||
|
||||
- (BOOL)performClose:(NSError**)error {
|
||||
DCHECK(_opened);
|
||||
GWS_DCHECK(_opened);
|
||||
return [_writer close:error];
|
||||
}
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@
|
||||
} else {
|
||||
encodedData = [[NSMutableData alloc] initWithLength:kGZipInitialBufferSize];
|
||||
if (encodedData == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
return nil;
|
||||
}
|
||||
NSUInteger length = 0;
|
||||
@@ -136,7 +136,7 @@
|
||||
}
|
||||
encodedData.length = 2 * encodedData.length; // zlib has used all the output buffer so resize it and try again in case more data is available
|
||||
}
|
||||
DCHECK(_stream.avail_in == 0);
|
||||
GWS_DCHECK(_stream.avail_in == 0);
|
||||
} while (length == 0); // Make sure we don't return an empty NSData if not in finished state
|
||||
encodedData.length = length;
|
||||
}
|
||||
@@ -234,10 +234,10 @@
|
||||
}
|
||||
|
||||
- (BOOL)performOpen:(NSError**)error {
|
||||
DCHECK(_type);
|
||||
DCHECK(_reader);
|
||||
GWS_DCHECK(_type);
|
||||
GWS_DCHECK(_reader);
|
||||
if (_opened) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
return NO;
|
||||
}
|
||||
_opened = YES;
|
||||
@@ -245,12 +245,12 @@
|
||||
}
|
||||
|
||||
- (NSData*)performReadData:(NSError**)error {
|
||||
DCHECK(_opened);
|
||||
GWS_DCHECK(_opened);
|
||||
return [_reader readData:error];
|
||||
}
|
||||
|
||||
- (void)performClose {
|
||||
DCHECK(_opened);
|
||||
GWS_DCHECK(_opened);
|
||||
[_reader close];
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset");
|
||||
_text = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
return _text;
|
||||
@@ -101,7 +101,7 @@
|
||||
if ([mimeType isEqualToString:@"application/json"] || [mimeType isEqualToString:@"text/json"] || [mimeType isEqualToString:@"text/javascript"]) {
|
||||
_jsonObject = ARC_RETAIN([NSJSONSerialization JSONObjectWithData:_data options:0 error:NULL]);
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
return _jsonObject;
|
||||
|
||||
@@ -171,22 +171,22 @@ static NSData* _dashNewlineData = nil;
|
||||
+ (void)initialize {
|
||||
if (_newlineData == nil) {
|
||||
_newlineData = [[NSData alloc] initWithBytes:"\r\n" length:2];
|
||||
DCHECK(_newlineData);
|
||||
GWS_DCHECK(_newlineData);
|
||||
}
|
||||
if (_newlinesData == nil) {
|
||||
_newlinesData = [[NSData alloc] initWithBytes:"\r\n\r\n" length:4];
|
||||
DCHECK(_newlinesData);
|
||||
GWS_DCHECK(_newlinesData);
|
||||
}
|
||||
if (_dashNewlineData == nil) {
|
||||
_dashNewlineData = [[NSData alloc] initWithBytes:"--\r\n" length:4];
|
||||
DCHECK(_dashNewlineData);
|
||||
GWS_DCHECK(_dashNewlineData);
|
||||
}
|
||||
}
|
||||
|
||||
- (id)initWithBoundary:(NSString*)boundary defaultControlName:(NSString*)name arguments:(NSMutableArray*)arguments files:(NSMutableArray*)files {
|
||||
NSData* data = boundary.length ? [[NSString stringWithFormat:@"--%@", boundary] dataUsingEncoding:NSASCIIStringEncoding] : nil;
|
||||
if (data == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -259,7 +259,7 @@ static NSData* _dashNewlineData = nil;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
if (_contentType == nil) {
|
||||
@@ -267,15 +267,15 @@ static NSData* _dashNewlineData = nil;
|
||||
}
|
||||
ARC_RELEASE(headers);
|
||||
} else {
|
||||
LOG_ERROR(@"Failed decoding headers in part of 'multipart/form-data'");
|
||||
DNOT_REACHED();
|
||||
GWS_LOG_ERROR(@"Failed decoding headers in part of 'multipart/form-data'");
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
if (_controlName) {
|
||||
if ([GCDWebServerTruncateHeaderValue(_contentType) isEqualToString:@"multipart/mixed"]) {
|
||||
NSString* boundary = GCDWebServerExtractHeaderValueParameter(_contentType, @"boundary");
|
||||
_subParser = [[GCDWebServerMIMEStreamParser alloc] initWithBoundary:boundary defaultControlName:_controlName arguments:_arguments files:_files];
|
||||
if (_subParser == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
} else if (_fileName) {
|
||||
@@ -284,12 +284,12 @@ static NSData* _dashNewlineData = nil;
|
||||
if (_tmpFile > 0) {
|
||||
_tmpPath = [path copy];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ static NSData* _dashNewlineData = nil;
|
||||
NSUInteger dataLength = range.location - 2;
|
||||
if (_subParser) {
|
||||
if (![_subParser appendBytes:dataBytes length:(dataLength + 2)] || ![_subParser isAtEnd]) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
ARC_RELEASE(_subParser);
|
||||
@@ -325,11 +325,11 @@ static NSData* _dashNewlineData = nil;
|
||||
[_files addObject:file];
|
||||
ARC_RELEASE(file);
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
ARC_RELEASE(_tmpPath);
|
||||
@@ -359,7 +359,7 @@ static NSData* _dashNewlineData = nil;
|
||||
if ([_subParser appendBytes:_data.bytes length:length]) {
|
||||
[_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
} else if (_tmpPath) {
|
||||
@@ -367,7 +367,7 @@ static NSData* _dashNewlineData = nil;
|
||||
if (result == (ssize_t)length) {
|
||||
[_data replaceBytesInRange:NSMakeRange(0, length) withBytes:NULL length:0];
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
success = NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
NSString* charset = GCDWebServerExtractHeaderValueParameter(self.contentType, @"charset");
|
||||
NSString* string = [[NSString alloc] initWithData:self.data encoding:GCDWebServerStringEncodingFromCharset(charset)];
|
||||
_arguments = ARC_RETAIN(GCDWebServerParseURLEncodedForm(string));
|
||||
DCHECK(_arguments);
|
||||
GWS_DCHECK(_arguments);
|
||||
ARC_RELEASE(string);
|
||||
|
||||
return YES;
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
- (instancetype)initWithData:(NSData*)data contentType:(NSString*)type {
|
||||
if (data == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -107,7 +107,7 @@
|
||||
- (instancetype)initWithText:(NSString*)text {
|
||||
NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding];
|
||||
if (data == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -117,7 +117,7 @@
|
||||
- (instancetype)initWithHTML:(NSString*)html {
|
||||
NSData* data = [html dataUsingEncoding:NSUTF8StringEncoding];
|
||||
if (data == nil) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
@implementation GCDWebServerErrorResponse
|
||||
|
||||
+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
GCDWebServerErrorResponse* response = ARC_AUTORELEASE([[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]);
|
||||
@@ -43,7 +43,7 @@
|
||||
}
|
||||
|
||||
+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
GCDWebServerErrorResponse* response = ARC_AUTORELEASE([[self alloc] initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments]);
|
||||
@@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
+ (instancetype)responseWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
GCDWebServerErrorResponse* response = ARC_AUTORELEASE([[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]);
|
||||
@@ -61,7 +61,7 @@
|
||||
}
|
||||
|
||||
+ (instancetype)responseWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
GCDWebServerErrorResponse* response = ARC_AUTORELEASE([[self alloc] initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments]);
|
||||
@@ -87,7 +87,7 @@ static inline NSString* _EscapeHTMLString(NSString* string) {
|
||||
}
|
||||
|
||||
- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
||||
@@ -96,7 +96,7 @@ static inline NSString* _EscapeHTMLString(NSString* string) {
|
||||
}
|
||||
|
||||
- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
self = [self initWithStatusCode:errorCode underlyingError:nil messageFormat:format arguments:arguments];
|
||||
@@ -105,7 +105,7 @@ static inline NSString* _EscapeHTMLString(NSString* string) {
|
||||
}
|
||||
|
||||
- (instancetype)initWithClientError:(GCDWebServerClientErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 400) && ((NSInteger)errorCode < 500));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
||||
@@ -114,7 +114,7 @@ static inline NSString* _EscapeHTMLString(NSString* string) {
|
||||
}
|
||||
|
||||
- (instancetype)initWithServerError:(GCDWebServerServerErrorHTTPStatusCode)errorCode underlyingError:(NSError*)underlyingError message:(NSString*)format, ... {
|
||||
DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
GWS_DCHECK(((NSInteger)errorCode >= 500) && ((NSInteger)errorCode < 600));
|
||||
va_list arguments;
|
||||
va_start(arguments, format);
|
||||
self = [self initWithStatusCode:errorCode underlyingError:underlyingError messageFormat:format arguments:arguments];
|
||||
|
||||
@@ -77,13 +77,13 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
||||
- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment {
|
||||
struct stat info;
|
||||
if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
#ifndef __LP64__
|
||||
if (info.st_size >= (off_t)4294967295) { // In 32 bit mode, we can't handle files greater than 4 GiBs (don't use "NSUIntegerMax" here to avoid potential unsigned to signed conversion issues)
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
ARC_RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
@@ -115,7 +115,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
||||
if (hasByteRange) {
|
||||
[self setStatusCode:kGCDWebServerHTTPStatusCode_PartialContent];
|
||||
[self setValue:[NSString stringWithFormat:@"bytes %lu-%lu/%lu", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), (unsigned long)fileSize] forAdditionalHeader:@"Content-Range"];
|
||||
LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path);
|
||||
GWS_LOG_DEBUG(@"Using content bytes range [%lu-%lu] for file \"%@\"", (unsigned long)_offset, (unsigned long)(_offset + _size - 1), path);
|
||||
}
|
||||
|
||||
if (attachment) {
|
||||
@@ -127,7 +127,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) {
|
||||
[self setValue:value forAdditionalHeader:@"Content-Disposition"];
|
||||
ARC_RELEASE(lossyFileName);
|
||||
} else {
|
||||
DNOT_REACHED();
|
||||
GWS_DNOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user