diff --git a/GCDWebServer/Core/GCDWebServerFunctions.h b/GCDWebServer/Core/GCDWebServerFunctions.h index 0752bce..4235ecc 100644 --- a/GCDWebServer/Core/GCDWebServerFunctions.h +++ b/GCDWebServer/Core/GCDWebServerFunctions.h @@ -36,8 +36,12 @@ extern "C" { /** * Converts a file extension to the corresponding MIME type. * If there is no match, "application/octet-stream" is returned. + * + * Overrides allow to customize the built-in mapping from extensions to MIME + * types. Keys of the dictionary must be lowercased file extensions without + * the period, and the values must be the corresponding MIME types. */ -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension); +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* _Nullable overrides); /** * Add percent-escapes to a string so it can be used in a URL. diff --git a/GCDWebServer/Core/GCDWebServerFunctions.m b/GCDWebServer/Core/GCDWebServerFunctions.m index 7c72e34..ec50086 100644 --- a/GCDWebServer/Core/GCDWebServerFunctions.m +++ b/GCDWebServer/Core/GCDWebServerFunctions.m @@ -166,12 +166,15 @@ NSString* GCDWebServerDescribeData(NSData* data, NSString* type) { return [NSString stringWithFormat:@"<%lu bytes>", (unsigned long)data.length]; } -NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension) { - NSDictionary* overrides = @{@"css": @"text/css"}; +NSString* GCDWebServerGetMimeTypeForExtension(NSString* extension, NSDictionary* overrides) { + NSDictionary* builtInOverrides = @{@"css": @"text/css"}; NSString* mimeType = nil; extension = [extension lowercaseString]; if (extension.length) { mimeType = [overrides objectForKey:extension]; + if (mimeType == nil) { + mimeType = [builtInOverrides objectForKey:extension]; + } if (mimeType == nil) { CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)extension, NULL); if (uti) { diff --git a/GCDWebServer/Responses/GCDWebServerFileResponse.h b/GCDWebServer/Responses/GCDWebServerFileResponse.h index f7dbd47..9403835 100644 --- a/GCDWebServer/Responses/GCDWebServerFileResponse.h +++ b/GCDWebServer/Responses/GCDWebServerFileResponse.h @@ -95,8 +95,13 @@ NS_ASSUME_NONNULL_BEGIN /** * This method is the designated initializer for the class. + * + * If MIME type overrides are specified, they allow to customize the built-in + * mapping from extensions to MIME types. Keys of the dictionary must be lowercased + * file extensions without the period, and the values must be the corresponding + * MIME types. */ -- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment; +- (nullable instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(nullable NSDictionary*)overrides; @end diff --git a/GCDWebServer/Responses/GCDWebServerFileResponse.m b/GCDWebServer/Responses/GCDWebServerFileResponse.m index f693e1b..bd07518 100644 --- a/GCDWebServer/Responses/GCDWebServerFileResponse.m +++ b/GCDWebServer/Responses/GCDWebServerFileResponse.m @@ -57,26 +57,26 @@ } + (instancetype)responseWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { - return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment]; + return [[[self class] alloc] initWithFile:path byteRange:range isAttachment:attachment mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO]; + return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:NO mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path isAttachment:(BOOL)attachment { - return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment]; + return [self initWithFile:path byteRange:NSMakeRange(NSUIntegerMax, 0) isAttachment:attachment mimeTypeOverrides:nil]; } - (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range { - return [self initWithFile:path byteRange:range isAttachment:NO]; + return [self initWithFile:path byteRange:range isAttachment:NO mimeTypeOverrides:nil]; } static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) { return [NSDate dateWithTimeIntervalSince1970:((NSTimeInterval)t->tv_sec + (NSTimeInterval)t->tv_nsec / 1000000000.0)]; } -- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment { +- (instancetype)initWithFile:(NSString*)path byteRange:(NSRange)range isAttachment:(BOOL)attachment mimeTypeOverrides:(NSDictionary*)overrides { struct stat info; if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) { GWS_DNOT_REACHED(); @@ -129,7 +129,7 @@ static inline NSDate* _NSDateFromTimeSpec(const struct timespec* t) { } } - self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension]); + self.contentType = GCDWebServerGetMimeTypeForExtension([_path pathExtension], overrides); self.contentLength = _size; self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec); self.eTag = [NSString stringWithFormat:@"%llu/%li/%li", info.st_ino, info.st_mtimespec.tv_sec, info.st_mtimespec.tv_nsec];