HttpHandlers.swift 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. //
  2. // Handlers.swift
  3. // Swifter
  4. // Copyright (c) 2014 Damian Kołakowski. All rights reserved.
  5. //
  6. import Foundation
  7. public class HttpHandlers {
  8. private static let rangeExpression = try! NSRegularExpression(pattern: "bytes=(\\d*)-(\\d*)", options: .CaseInsensitive)
  9. public class func directory(dir: String) -> ( HttpRequest -> HttpResponse ) {
  10. return { request in
  11. guard let localPath = request.capturedUrlGroups.first else {
  12. return HttpResponse.NotFound
  13. }
  14. let filesPath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(localPath)
  15. guard let fileBody = NSData(contentsOfFile: filesPath) else {
  16. return HttpResponse.NotFound
  17. }
  18. if let rangeHeader = request.headers["range"] {
  19. guard let match = rangeExpression.matchesInString(rangeHeader, options: .Anchored, range: NSRange(location: 0, length: rangeHeader.characters.count)).first where match.numberOfRanges == 3 else {
  20. return HttpResponse.BadRequest
  21. }
  22. let startStr = (rangeHeader as NSString).substringWithRange(match.rangeAtIndex(1))
  23. let endStr = (rangeHeader as NSString).substringWithRange(match.rangeAtIndex(2))
  24. guard let start = Int(startStr), end = Int(endStr) else {
  25. return HttpResponse.RAW(200, "OK", nil, fileBody)
  26. }
  27. let length = end - start
  28. let range = NSRange(location: start, length: length + 1)
  29. guard range.location + range.length <= fileBody.length else {
  30. return HttpResponse.RAW(416, "Requested range not satisfiable", nil, NSData())
  31. }
  32. let subData = fileBody.subdataWithRange(range)
  33. let headers = [
  34. "Content-Range" : "bytes \(startStr)-\(endStr)/\(fileBody.length)"
  35. ]
  36. print(rangeHeader, headers)
  37. return HttpResponse.RAW(206, "Partial Content", headers, subData)
  38. }
  39. else {
  40. return HttpResponse.RAW(200, "OK", nil, fileBody)
  41. }
  42. }
  43. }
  44. public class func directoryBrowser(dir: String) -> ( HttpRequest -> HttpResponse ) {
  45. return { request in
  46. if let pathFromUrl = request.capturedUrlGroups.first {
  47. let filePath = dir.stringByExpandingTildeInPath.stringByAppendingPathComponent(pathFromUrl)
  48. let fileManager = NSFileManager.defaultManager()
  49. var isDir: ObjCBool = false;
  50. if ( fileManager.fileExistsAtPath(filePath, isDirectory: &isDir) ) {
  51. if ( isDir ) {
  52. do {
  53. let files = try fileManager.contentsOfDirectoryAtPath(filePath)
  54. var response = "<h3>\(filePath)</h3></br><table>"
  55. response += files.map({ "<tr><td><a href=\"\(request.url)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
  56. response += "</table>"
  57. return HttpResponse.OK(.Html(response))
  58. } catch {
  59. return HttpResponse.NotFound
  60. }
  61. } else {
  62. if let fileBody = NSData(contentsOfFile: filePath) {
  63. return HttpResponse.RAW(200, "OK", nil, fileBody)
  64. }
  65. }
  66. }
  67. }
  68. return HttpResponse.NotFound
  69. }
  70. }
  71. }
  72. private extension String {
  73. var stringByExpandingTildeInPath: String {
  74. return (self as NSString).stringByExpandingTildeInPath
  75. }
  76. func stringByAppendingPathComponent(str: String) -> String {
  77. return (self as NSString).stringByAppendingPathComponent(str)
  78. }
  79. }