1
0

HttpHandlers.swift 4.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  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.params.first else {
  12. return HttpResponse.NotFound
  13. }
  14. let filesPath = dir + "/" + localPath.1
  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. var array = [UInt8](count: fileBody.length, repeatedValue: 0)
  26. fileBody.getBytes(&array, length: fileBody.length)
  27. return HttpResponse.RAW(200, "OK", nil, array)
  28. }
  29. let length = end - start
  30. let range = NSRange(location: start, length: length + 1)
  31. guard range.location + range.length <= fileBody.length else {
  32. return HttpResponse.RAW(416, "Requested range not satisfiable", nil, nil)
  33. }
  34. let subData = fileBody.subdataWithRange(range)
  35. let headers = [
  36. "Content-Range" : "bytes \(startStr)-\(endStr)/\(fileBody.length)"
  37. ]
  38. var array = [UInt8](count: subData.length, repeatedValue: 0)
  39. subData.getBytes(&array, length: subData.length)
  40. return HttpResponse.RAW(206, "Partial Content", headers, array)
  41. }
  42. else {
  43. var array = [UInt8](count: fileBody.length, repeatedValue: 0)
  44. fileBody.getBytes(&array, length: fileBody.length)
  45. return HttpResponse.RAW(200, "OK", nil, array)
  46. }
  47. }
  48. }
  49. public class func directoryBrowser(dir: String) -> ( HttpRequest -> HttpResponse ) {
  50. return { r in
  51. if let (_, value) = r.params.first {
  52. let filePath = dir + "/" + value
  53. let fileManager = NSFileManager.defaultManager()
  54. var isDir: ObjCBool = false
  55. if fileManager.fileExistsAtPath(filePath, isDirectory: &isDir) {
  56. if isDir {
  57. do {
  58. let files = try fileManager.contentsOfDirectoryAtPath(filePath)
  59. var response = "<h3>\(filePath)</h3></br><table>"
  60. response += files.map({ "<tr><td><a href=\"\(r.url)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
  61. response += "</table>"
  62. return HttpResponse.OK(.Html(response))
  63. } catch {
  64. return HttpResponse.NotFound
  65. }
  66. } else {
  67. if let fileBody = NSData(contentsOfFile: filePath) {
  68. var array = [UInt8](count: fileBody.length, repeatedValue: 0)
  69. fileBody.getBytes(&array, length: fileBody.length)
  70. return HttpResponse.RAW(200, "OK", nil, array)
  71. }
  72. }
  73. }
  74. }
  75. return HttpResponse.NotFound
  76. }
  77. }
  78. }