HttpHandlers.swift 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. //
  2. // Handlers.swift
  3. // Swifter
  4. //
  5. // Copyright (c) 2014-2016 Damian Kołakowski. All rights reserved.
  6. //
  7. import Foundation
  8. public class HttpHandlers {
  9. private static let rangePrefix = "bytes="
  10. public class func directory(dir: String) -> (HttpRequest -> HttpResponse) {
  11. return { r in
  12. guard let localPath = r.params.first else {
  13. return HttpResponse.NotFound
  14. }
  15. let filesPath = dir + "/" + localPath.1
  16. guard let fileBody = NSData(contentsOfFile: filesPath) else {
  17. return HttpResponse.NotFound
  18. }
  19. if let rangeHeader = r.headers["range"] {
  20. guard rangeHeader.hasPrefix(HttpHandlers.rangePrefix) else {
  21. return HttpResponse.BadRequest
  22. }
  23. #if os(Linux)
  24. let rangeString = rangeHeader.substringFromIndex(HttpHandlers.rangePrefix.characters.count)
  25. #else
  26. let rangeString = rangeHeader.substringFromIndex(rangeHeader.startIndex.advancedBy(HttpHandlers.rangePrefix.characters.count))
  27. #endif
  28. let rangeStringExploded = rangeString.split("-")
  29. guard rangeStringExploded.count == 2 else {
  30. return HttpResponse.BadRequest
  31. }
  32. let startStr = rangeStringExploded[0]
  33. let endStr = rangeStringExploded[1]
  34. guard let start = Int(startStr), end = Int(endStr) else {
  35. var array = [UInt8](count: fileBody.length, repeatedValue: 0)
  36. fileBody.getBytes(&array, length: fileBody.length)
  37. return HttpResponse.RAW(200, "OK", nil, { $0.write(array) })
  38. }
  39. let chunkLength = end - start
  40. let chunkRange = NSRange(location: start, length: chunkLength + 1)
  41. guard chunkRange.location + chunkRange.length <= fileBody.length else {
  42. return HttpResponse.RAW(416, "Requested range not satisfiable", nil, nil)
  43. }
  44. let chunk = fileBody.subdataWithRange(chunkRange)
  45. let headers = [ "Content-Range" : "bytes \(startStr)-\(endStr)/\(fileBody.length)" ]
  46. var content = [UInt8](count: chunk.length, repeatedValue: 0)
  47. chunk.getBytes(&content, length: chunk.length)
  48. return HttpResponse.RAW(206, "Partial Content", headers, { $0.write(content) })
  49. } else {
  50. var content = [UInt8](count: fileBody.length, repeatedValue: 0)
  51. fileBody.getBytes(&content, length: fileBody.length)
  52. return HttpResponse.RAW(200, "OK", nil, { $0.write(content) })
  53. }
  54. }
  55. }
  56. public class func directoryBrowser(dir: String) -> ( HttpRequest -> HttpResponse ) {
  57. return { r in
  58. if let (_, value) = r.params.first {
  59. let filePath = dir + "/" + value
  60. let fileManager = NSFileManager.defaultManager()
  61. var isDir: ObjCBool = false
  62. if fileManager.fileExistsAtPath(filePath, isDirectory: &isDir) {
  63. if isDir {
  64. do {
  65. let files = try fileManager.contentsOfDirectoryAtPath(filePath)
  66. var response = "<h3>\(filePath)</h3></br><table>"
  67. response += files.map({ "<tr><td><a href=\"\(r.path)/\($0)\">\($0)</a></td></tr>"}).joinWithSeparator("")
  68. response += "</table>"
  69. return HttpResponse.OK(.Html(response))
  70. } catch {
  71. return HttpResponse.NotFound
  72. }
  73. } else {
  74. if let fileBody = NSData(contentsOfFile: filePath) {
  75. var array = [UInt8](count: fileBody.length, repeatedValue: 0)
  76. fileBody.getBytes(&array, length: fileBody.length)
  77. return HttpResponse.RAW(200, "OK", nil, { $0.write(array) })
  78. }
  79. }
  80. }
  81. }
  82. return HttpResponse.NotFound
  83. }
  84. }
  85. }