| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- //
- // Handlers.swift
- // Swifter
- // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
- //
- import Foundation
- public class HttpHandlers {
-
- private static let rangeExpression = try! NSRegularExpression(pattern: "bytes=(\\d*)-(\\d*)", options: .CaseInsensitive)
-
- private static let cache = NSCache()
-
- public class func directory(dir: String) -> ( HttpRequest -> HttpResponse ) {
- return { request in
-
- guard let localPath = request.capturedUrlGroups.first else {
- return HttpResponse.NotFound
- }
-
- let filesPath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(localPath)
-
- let cachedBody = cache.objectForKey(filesPath) as? NSData
-
- guard let fileBody = cachedBody ?? NSData(contentsOfFile: filesPath) else {
- return HttpResponse.NotFound
- }
-
- if cachedBody == nil {
- cache.setObject(fileBody, forKey: filesPath)
- }
-
- if let rangeHeader = request.headers["range"] {
-
- guard let match = rangeExpression.matchesInString(rangeHeader, options: .Anchored, range: NSRange(location: 0, length: rangeHeader.characters.count)).first where match.numberOfRanges == 3 else {
- return HttpResponse.BadRequest
- }
-
- let startStr = (rangeHeader as NSString).substringWithRange(match.rangeAtIndex(1))
- let endStr = (rangeHeader as NSString).substringWithRange(match.rangeAtIndex(2))
-
- guard let start = Int(startStr), end = Int(endStr) else {
- return HttpResponse.RAW(200, "OK", nil, fileBody)
- }
-
- let length = end - start
- let range = NSRange(location: start, length: length + 1)
-
- guard range.location + range.length <= fileBody.length else {
- return HttpResponse.RAW(416, "Requested range not satisfiable", nil, NSData())
- }
-
- let subData = fileBody.subdataWithRange(range)
-
- let headers = [
- "Content-Range" : "bytes \(startStr)-\(endStr)/\(fileBody.length)"
- ]
-
- return HttpResponse.RAW(206, "Partial Content", headers, subData)
-
- }
- else {
- return HttpResponse.RAW(200, "OK", nil, fileBody)
- }
-
- }
- }
-
- public class func directoryBrowser(dir: String) -> ( HttpRequest -> HttpResponse ) {
- return { request in
- if let pathFromUrl = request.capturedUrlGroups.first {
- let filePath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(pathFromUrl)
- let fileManager = NSFileManager.defaultManager()
- var isDir: ObjCBool = false;
- if ( fileManager.fileExistsAtPath(filePath, isDirectory: &isDir) ) {
- if ( isDir ) {
- do {
- let files = try fileManager.contentsOfDirectoryAtPath(filePath)
- var response = "<h3>\(filePath)</h3></br><table>"
- response += files.map({ "<tr><td><a href=\"\(request.url)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
- response += "</table>"
- return HttpResponse.OK(.HTML(response))
- } catch {
- return HttpResponse.NotFound
- }
- } else {
- if let fileBody = NSData(contentsOfFile: filePath) {
- return HttpResponse.RAW(200, "OK", nil, fileBody)
- }
- }
- }
- }
- return HttpResponse.NotFound
- }
- }
- }
- private extension String {
- var stringByExpandingTildeInPath: String {
- return (self as NSString).stringByExpandingTildeInPath
- }
-
- func stringByAppendingPathComponent(str: String) -> String {
- return (self as NSString).stringByAppendingPathComponent(str)
- }
- }
|