HttpHandlers+Files.swift 5.2 KB

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