Skip to content

Commit df43537

Browse files
More demo examples at main.swift.
1 parent 14e61b5 commit df43537

File tree

3 files changed

+95
-31
lines changed

3 files changed

+95
-31
lines changed

Sources/Files.swift

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
//
77

88
import Foundation
9+
910
/*
10-
public func shareFile(_ path: String) -> ((HttpRequest) -> HttpResponse) {
11+
public func shareFile(_ path: String) {
1112
return { r in
1213
if let file = try? path.openForReading() {
1314
return .raw(200, "OK", [:], { writer in
@@ -17,34 +18,65 @@ public func shareFile(_ path: String) -> ((HttpRequest) -> HttpResponse) {
1718
}
1819
return .notFound
1920
}
20-
}
21+
}*/
2122

22-
public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String] = ["index.html", "default.html"]) -> ((HttpRequest) -> HttpResponse) {
23-
return { r in
24-
guard let fileRelativePath = r.params.first else {
25-
return .notFound
23+
#if os(iOS) || os(Linux)
24+
25+
func fileZeroCopy(from: Int32, to: Int32) {
26+
var buffer = [UInt8](repeating: 0, count: 1024)
27+
while true {
28+
let readResult = read(source, &buffer, buffer.count)
29+
guard readResult > 0 else {
30+
return Int32(readResult)
2631
}
27-
if fileRelativePath.value.isEmpty {
28-
for path in defaults {
29-
if let file = try? (directoryPath + String.pathSeparator + path).openForReading() {
30-
return .raw(200, "OK", [:], { writer in
31-
try? writer.write(file)
32-
file.close()
33-
})
34-
}
32+
var writeCounter = 0
33+
while writeCounter < readResult {
34+
let writeResult = write(target, &buffer + writeCounter, readResult - writeCounter)
35+
guard writeResult > 0 else {
36+
return Int32(writeResult)
3537
}
38+
writeCounter = writeCounter + writeResult
3639
}
37-
if let file = try? (directoryPath + String.pathSeparator + fileRelativePath.value).openForReading() {
38-
return .raw(200, "OK", [:], { writer in
39-
try? writer.write(file)
40-
file.close()
41-
})
42-
}
43-
return .notFound
4440
}
4541
}
4642

47-
public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) {
43+
#else
44+
45+
func fileZeroCopy(from: Int32, to: Int32) {
46+
var offset: off_t = 0
47+
var sf: sf_hdtr = sf_hdtr()
48+
sendfile(from, to, 0, &offset, &sf, 0)
49+
}
50+
51+
#endif
52+
53+
@available(OSXApplicationExtension 10.10, *)
54+
public func share(filesAtPath path: String, defaults: [String] = ["index.html", "default.html"]) -> (([String: String], Request, @escaping ((Response) -> Void)) -> Void) {
55+
return { (params, request, responder) in
56+
DispatchQueue.global(qos: .background).async {
57+
guard let fileRelativePath = params.first else {
58+
return responder(404)
59+
}
60+
if fileRelativePath.value.isEmpty {
61+
for path in defaults {
62+
if let file = try? (path + String.pathSeparator + path).openFile(forMode: "r+b") {
63+
fileZeroCopy(from: fileno(file.pointer), to: 0)
64+
file.close()
65+
}
66+
}
67+
}
68+
if let file = try? (path + String.pathSeparator + fileRelativePath.value).openFile(forMode: "r+b") {
69+
fileZeroCopy(from: fileno(file.pointer), to: 0)
70+
file.close()
71+
}
72+
return responder(404)
73+
}
74+
}
75+
}
76+
77+
/*
78+
79+
public func directoryBrowser(_ dir: String) -> (([String: String], Request, @escaping ((Response) -> Void)) -> Void) {
4880
return { r in
4981
guard let (_, value) = r.params.first else {
5082
return HttpResponse.notFound

Sources/String+File.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ extension String {
6464

6565
public static var pathSeparator = "/"
6666

67-
public func openFile(_ path: String, _ mode: String) throws -> File {
68-
guard let file = path.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
67+
public func openFile(forMode mode: String) throws -> File {
68+
guard let file = self.withCString({ pathPointer in mode.withCString({ fopen(pathPointer, $0) }) }) else {
6969
throw FileError.error(errno)
7070
}
7171
return File(file)

XCode/SwifterSampleOSX/main.swift

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import Foundation
88
import Swifter
99

10+
1011
let server = try Swifter()
1112

1213
server.get("/") { _, request, responder in
@@ -21,7 +22,7 @@ server.get("/hello") { _, _, responder in
2122
responder(200)
2223
}
2324

24-
server.get("/stream") { _, request, responder in
25+
server.get("/test/websocket") { _, request, responder in
2526
responder(WebsocketResponse(request) { event in
2627
switch event {
2728
case .text(let value):
@@ -34,7 +35,7 @@ server.get("/stream") { _, request, responder in
3435
})
3536
}
3637

37-
server.get("/background") { _, _, closure in
38+
server.get("/test/background") { _, _, closure in
3839

3940
if #available(OSXApplicationExtension 10.10, *) {
4041
DispatchQueue.global(qos: .background).async {
@@ -48,22 +49,53 @@ server.get("/background") { _, _, closure in
4849

4950
}
5051

51-
server.post("/post") { _, request, responder in
52+
server.get("/test/multipart") { _, request, responder in
5253

53-
let post = request.parseUrlencodedForm()
54+
responder(html(200) {
55+
"body" ~ {
56+
"form(method=POST,action=/test/multipart,enctype=multipart/form-data)" ~ {
57+
58+
"input(name=my_file1,type=file)" ~ ""
59+
"input(name=my_file2,type=file)" ~ ""
60+
"input(name=my_file3,type=file)" ~ ""
61+
62+
"button(type=submit)" ~ "Upload"
63+
}
64+
}
65+
})
66+
}
67+
68+
server.post("/test/multipart") { _, request, responder in
69+
70+
let multiparts = request.parseMultiPartFormData()
5471

5572
responder(html(200) {
5673
"body" ~ {
57-
"h4" ~ "You sent: "
74+
"h5" ~ "Parts"
5875
"ul" ~ {
59-
post.forEach { item in
60-
"li" ~ "\(item.0) -> \(item.1)"
76+
multiparts.forEach { part in
77+
"li" ~ "\(part.fileName) -- \(part.body.count)"
6178
}
6279
}
6380
}
6481
})
6582
}
6683

84+
server.notFoundHandler = { r in
85+
return html(200) {
86+
"body" ~ {
87+
"h5" ~ "Page not found. Try:"
88+
"ul" ~ {
89+
server.routes.forEach { route in
90+
"li" ~ {
91+
"a(href=\(route))" ~ route
92+
}
93+
}
94+
}
95+
}
96+
}
97+
}
98+
6799
while true {
68100
try server.loop()
69101
}

0 commit comments

Comments
 (0)