             }
             
             file.marker = range.lowerBound
-            
-            return self.sendFile(remainingBytes: rangeCount, response: response, file: file) {
-                ok in
-                
-                file.close()
-                response.completed()
-            }
+			// send out headers
+			response.push { ok in
+				guard ok else {
+					file.close()
+					return response.completed()
+				}
+				return self.sendFile(remainingBytes: rangeCount, response: response, file: file) {
+					ok in
+					
+					file.close()
+					response.completed()
+				}
+			}
         } else if ranges.count > 0 {
             // !FIX! support multiple ranges
             response.status = .internalServerError

		}
        do {
            try file.open(.read)
            self.sendFile(request: req, response: response, file: file)
        } catch {
            return fnf(msg: "The file \(path) could not be opened \(error).")
        }
	}
	
	func sendFile(request req: HTTPRequest, response resp: HTTPResponse, file: File) {
		
		resp.addHeader(.acceptRanges, value: "bytes")

		if let rangeRequest = req.header(.range) {
            return self.performRangeRequest(rangeRequest: rangeRequest, request: req, response: resp, file: file)
        } else if let ifNoneMatch = req.header(.ifNoneMatch) {
            let eTag = self.getETag(file: file)
            if ifNoneMatch == eTag {
                resp.status = .notModified
                return resp.completed()
            }
        }
        
        let size = file.size
        let contentType = MimeType.forExtension(file.path.pathExtension)
        
		resp.status = .ok
		resp.addHeader(.contentType, value: contentType)
		resp.addHeader(.contentLength, value: "\(size)")
        
        self.addETag(response: resp, file: file)
        
		if case .head = req.method {
			return resp.completed()
		}
		
		self.sendFile(remainingBytes: size, response: resp, file: file) {
			ok in
			file.close()
			resp.completed()
		}
	}
	

        }
    }
    
    func getETag(file: File) -> String {
        let eTagStr = file.path + "\(file.modificationTime)"
        let eTag = eTagStr.utf8.sha1
        let eTagReStr = eTag.map { $0.hexString }.joined(separator: "")
        
        return eTagReStr
    }
    
    func addETag(response: HTTPResponse, file: File) {
        let eTag = self.getETag(file: file)
        response.addHeader(.eTag, value: eTag)
    }
    
	func sendFile(remainingBytes remaining: Int, response: HTTPResponse, file: File, completion: @escaping (Bool) -> ()) {
		if self.allowResponseFilters {
			let thisRead = min(chunkedBufferSize, remaining)
			do {
				let bytes = try file.readSomeBytes(count: thisRead)
				response.appendBody(bytes: bytes)
				response.push {
					ok in
					
					if !ok || thisRead == remaining {
						// done
						completion(ok)
					} else {
						self.sendFile(remainingBytes: remaining - bytes.count, response: response, file: file, completion: completion)
					}
				}
			} catch {
				completion(false)
			}
		} else {
			let outFd = response.request.connection.fd.fd
			let inFd = file.fd
			let offset = off_t(file.marker)
			var toSend = off_t(remaining)
			let result = sendfile(Int32(inFd), outFd, offset, &toSend, nil, 0)
			
			if result == 0 {
				completion(true)
			} else if result == -1 && errno == EAGAIN {
				
				file.marker = Int(offset) + Int(toSend)
				let newRemaining = remaining - Int(toSend)
				
				NetEvent.add(socket: outFd, what: .write, timeoutSeconds: 5.0) {
					socket, what in
					if case .write = what {
						self.sendFile(remainingBytes: newRemaining, response: response, file: file, completion: completion)
					} else {
						completion(false)
					}
				}
			} else {
				completion(false)
			}
		}
	}
	
