 	
 	let chunkedBufferSize = 1024*200
 	let documentRoot: String
+	let allowResponseFilters: Bool
 	
 	/// Public initializer given a document root.
-	public init(documentRoot: String) {
+	/// If allowResponseFilters is false (which is the default) then the file will be sent in 
+	/// the most effecient way possible and output filters will be bypassed.
+	public init(documentRoot: String, allowResponseFilters: Bool = false) {
 		self.documentRoot = documentRoot
+		self.allowResponseFilters = allowResponseFilters
 	}
 	
     /// Main entry point. A registered URL handler should call this and pass the request and response objects.
     /// After calling this, the StaticFileHandler owns the request and will handle it until completion.
-	public func handleRequest(request req: HTTPRequest, response: HTTPResponse) {
-        var path = req.path
+	public func handleRequest(request: HTTPRequest, response: HTTPResponse) {
+        var path = request.path
 		if path[path.index(before: path.endIndex)] == "/" {
 			path.append("index.html") // !FIX! needs to be configurable
 		}

        }
    }
    
    func getETag(file f: File) -> String {
        let eTagStr = f.path + "\(f.modificationTime)"
        let eTag = eTagStr.utf8.sha1
        let eTagReStr = eTag.map { $0.hexString }.joined(separator: "")
        
        return eTagReStr
    }
    
    func addETag(response resp: HTTPResponse, file: File) {
        let eTag = self.getETag(file: file)
        resp.addHeader(.eTag, value: eTag)
    }
    
	func sendFile(remainingBytes remaining: Int, response: HTTPResponse, file: File, completion: @escaping (Bool) -> ()) {
		
		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)
		}
	}
	

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

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