瀏覽代碼

Added support for "Last-Modified" response header

Pierre-Olivier Latour 11 年之前
父節點
當前提交
f1a79ffd11

+ 3 - 0
CGDWebServer/GCDWebServerConnection.m

@@ -408,6 +408,9 @@ static inline NSUInteger _ScanHexNumber(const void* bytes, NSUInteger size) {
   
   if (_response) {
     [self _initializeResponseHeadersWithStatusCode:_response.statusCode];
+    if (_response.lastModifiedDate) {
+      CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Last-Modified"), (ARC_BRIDGE CFStringRef)GCDWebServerFormatHTTPDate(_response.lastModifiedDate));
+    }
     if (_response.cacheControlMaxAge > 0) {
       CFHTTPMessageSetHeaderFieldValue(_responseMessage, CFSTR("Cache-Control"), (ARC_BRIDGE CFStringRef)[NSString stringWithFormat:@"max-age=%i, public", (int)_response.cacheControlMaxAge]);
     } else {

+ 5 - 0
CGDWebServer/GCDWebServerFileResponse.m

@@ -74,6 +74,10 @@ static inline NSError* _MakePosixError(int code) {
   return [self initWithFile:path byteRange:range isAttachment:NO];
 }
 
+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 {
   struct stat info;
   if (lstat([path fileSystemRepresentation], &info) || !(info.st_mode & S_IFREG)) {
@@ -121,6 +125,7 @@ static inline NSError* _MakePosixError(int code) {
     
     self.contentType = GCDWebServerGetMimeTypeForExtension([path pathExtension]);
     self.contentLength = (range.location != NSNotFound ? range.length : (NSUInteger)info.st_size);
+    self.lastModifiedDate = _NSDateFromTimeSpec(&info.st_mtimespec);
   }
   return self;
 }

+ 2 - 1
CGDWebServer/GCDWebServerResponse.h

@@ -37,7 +37,8 @@
 @property(nonatomic, copy) NSString* contentType;  // Default is nil i.e. no body (must be set if a body is present)
 @property(nonatomic) NSUInteger contentLength;  // Default is NSNotFound i.e. undefined (if a body is present but length is undefined, chunked transfer encoding will be enabled)
 @property(nonatomic) NSInteger statusCode;  // Default is 200
-@property(nonatomic) NSUInteger cacheControlMaxAge;  // Default is 0 seconds i.e. "no-cache"
+@property(nonatomic) NSUInteger cacheControlMaxAge;  // Default is 0 seconds i.e. "Cache-Control: no-cache"
+@property(nonatomic, retain) NSDate* lastModifiedDate;  // Default is nil i.e. no "Last-Modified" header
 @property(nonatomic, getter=isGZipContentEncodingEnabled) BOOL gzipContentEncodingEnabled;  // Default is disabled
 + (instancetype)response;
 - (instancetype)init;

+ 3 - 1
CGDWebServer/GCDWebServerResponse.m

@@ -156,6 +156,7 @@
   NSUInteger _length;
   NSInteger _status;
   NSUInteger _maxAge;
+  NSDate* _lastModified;
   NSMutableDictionary* _headers;
   BOOL _chunked;
   BOOL _gzipped;
@@ -168,7 +169,7 @@
 
 @implementation GCDWebServerResponse
 
-@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge,
+@synthesize contentType=_type, contentLength=_length, statusCode=_status, cacheControlMaxAge=_maxAge, lastModifiedDate=_lastModified,
             gzipContentEncodingEnabled=_gzipped, additionalHeaders=_headers;
 
 + (instancetype)response {
@@ -189,6 +190,7 @@
 
 - (void)dealloc {
   ARC_RELEASE(_type);
+  ARC_RELEASE(_lastModified);
   ARC_RELEASE(_headers);
   ARC_RELEASE(_encoders);