diff --git a/.github/workflows/danger.yml b/.github/workflows/danger.yml index 560ebb10..a28ed1b1 100644 --- a/.github/workflows/danger.yml +++ b/.github/workflows/danger.yml @@ -1,32 +1,25 @@ name: Danger + on: pull_request: + types: [opened, synchronize, edited] branches: - - stable + - stable jobs: Danger: - runs-on: macos-latest + runs-on: ubuntu-18.04 steps: - - uses: actions/checkout@v2 - - name: Cache Bundle Dependencies - uses: actions/cache@v1 - with: - path: vendor/bundle - key: 1-gems-{{ checksum "Gemfile.lock" }} - restore-keys: 1-gems- - - name: Set Ruby Version - uses: actions/setup-ruby@v1 + - uses: actions/checkout@v1 + + - uses: ruby/setup-ruby@v1 with: - ruby-version: 2.6 - - name: Install Ruby Dependencies + ruby-version: 2.6 # Not needed with a .ruby-version file + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Danger run: | - bundle config path vendor/bundle - bundle check || bundle install - env: - BUNDLE_JOBS: 4 - BUNDLE_RETRY: 3 - - name: Running Danger - run: bundle exec danger + bundle exec danger --fail-on-errors=true + shell: bash env: - DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + DANGER_GITHUB_API_TOKEN: ${{ secrets.BOT_ACCESS_TOKEN }} \ No newline at end of file diff --git a/.github/workflows/macos-tests.yml b/.github/workflows/macos-tests.yml index 4daba501..9989f63f 100644 --- a/.github/workflows/macos-tests.yml +++ b/.github/workflows/macos-tests.yml @@ -21,19 +21,19 @@ jobs: mkdir -p tmp/test-results/ - name: Run Unit Test - macOS run: | - cd XCode + cd Xcode set -o pipefail && xcodebuild test -scheme SwifterMac -sdk macosx -destination "arch=x86_64" | xcpretty -c -r html --output $TEST_REPORTS/macOS.html - name: Run Unit Test - iOS run: | - cd XCode + cd Xcode set -o pipefail && xcodebuild test -scheme SwifteriOS -sdk iphonesimulator -destination "name=iPhone 8" | xcpretty -c -r html --output $TEST_REPORTS/iOS.html - name: Run Unit Test - tvOS run: | - cd XCode + cd Xcode set -o pipefail && xcodebuild test -scheme SwiftertvOS -sdk appletvsimulator -destination "name=Apple TV 4K (at 1080p)" | xcpretty -c -r html --output $TEST_REPORTS/tvOS.html - name: Run Unit Test - Swift Package Manager run: | - cd XCode + cd Xcode swift build && swift test - name: Archive Test results uses: actions/upload-artifact@v1 diff --git a/.gitignore b/.gitignore index 239c7866..98201867 100644 --- a/.gitignore +++ b/.gitignore @@ -27,4 +27,4 @@ DerivedData .build/ Packages/ -/XCode/.DS_Store +/Xcode/.DS_Store diff --git a/.swiftlint.yml b/.swiftlint.yml index b66fc6ce..c90ba6f9 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -16,6 +16,6 @@ disabled_rules: excluded: # paths to ignore during linting. Takes precedence over `included`. - LinuxMain.swift - - XCode/Tests/XCTestManifests.swift + - Xcode/Tests/XCTestManifests.swift - Tests/XCTestManifests.swift - Package.swift diff --git a/CHANGELOG.md b/CHANGELOG.md index cd59d0a7..3779fb6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,26 @@ All notable changes to this project will be documented in this file. Changes not # [Unreleased] + +## Added + +- Add custom headers into .ok HttpResponse. ([#500](https://github.com/httpswift/swifter/pull/500) by [@yuri-qualtie](https://github.com/yuri-qualtie) +- Add support for using `**` as a catch-all at the end of a route. ([#479](https://github.com/httpswift/swifter/pull/479)) by [@michaelenger](https://github.com/michaelenger) +- Set `Content-Type` to HttpBody and Text HttpResponse. ([#474](https://github.com/httpswift/swifter/pull/474)) by [@mtgto](https://github.com/mtgto) +- The `shareFile` function now sets `Content-Type` and `Content-Length` headers like `shareFilesFromDirectory`. ([#493](https://github.com/httpswift/swifter/pull/493)) by [@jcrate](https://github.com/jcrate) +- Adds response body to any http response. ([#476](https://github.com/httpswift/swifter/pull/476) by [@mtgto](https://github.com/mtgto) + +## Fixed + +- Fix misspell `serialise`. ([#473](https://github.com/httpswift/swifter/pull/473)) by [@mtgto](https://github.com/mtgto) +- Fix an issue causing Danger was not working properly. ([#486](https://github.com/httpswift/swifter/pull/486)) by [@Vkt0r](https://github.com/Vkt0r) +- Set Swift version to 5.0 in podspec. ([#475](https://github.com/httpswift/swifter/pull/475)) by [@p-krasnobrovkin-tcs](https://github.com/p-krasnobrovkin-tcs) +- Improved performance of data reading. ([#487](https://github.com/httpswift/swifter/pull/487)) by [@till0xff](https://github.com/till0xff) + +## Changed + +- Rename `Example` product to `SwifterExample` ([#492](https://github.com/httpswift/swifter/pull/492) by [@fortmarek](https://github.com/fortmarek)) + # [1.5.0] ## Added diff --git a/Dangerfile b/Dangerfile index b75f2e29..e5d373de 100644 --- a/Dangerfile +++ b/Dangerfile @@ -26,10 +26,10 @@ swiftlint.config_file = '.swiftlint.yml' swiftlint.lint_files # Warn when new tests are added but the XCTestManifests wasn't updated to run on Linux -tests_added_or_modified = !git.modified_files.grep(/XCode\/Tests/).empty? || !git.added_files.grep(/XCode\/Tests/).empty? -xc_manifest_updated = !git.modified_files.grep(/XCode\/Tests\/XCTestManifests.swift/).empty? +tests_added_or_modified = !git.modified_files.grep(/Xcode\/Tests/).empty? || !git.added_files.grep(/Xcode\/Tests/).empty? +xc_manifest_updated = !git.modified_files.grep(/Xcode\/Tests\/XCTestManifests.swift/).empty? if tests_added_or_modified && !xc_manifest_updated - warn("It seems like you've added new tests to the library. If that's the case, please update the [XCTestManifests.swift](https://github.com/httpswift/swifter/blob/stable/XCode/Tests/XCTestManifests.swift) file running in your terminal the command `swift test --generate-linuxmain`.") + warn("It seems like you've added new tests to the library. If that's the case, please update the [XCTestManifests.swift](https://github.com/httpswift/swifter/blob/stable/Xcode/Tests/XCTestManifests.swift) file running in your terminal the command `swift test --generate-linuxmain`.") # This is a temporary warning to remove the entry for the failed test until we solve the issue in Linux warn("If you ran the command `swift test --generate-linuxmain` in your terminal, please remove the line `testCase(IOSafetyTests.__allTests__IOSafetyTests),` from `public func __allTests() -> [XCTestCaseEntry]` in the bottom of the file. For more reference see [#366](https://github.com/httpswift/swifter/issues/366).") diff --git a/Gemfile.lock b/Gemfile.lock index edf8c516..4fdd9b46 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ GEM remote: https://rubygems.org/ specs: - addressable (2.7.0) + addressable (2.8.0) public_suffix (>= 2.0.2, < 5.0) claide (1.0.3) claide-plugins (0.9.2) @@ -11,7 +11,7 @@ GEM colored2 (3.1.2) cork (0.3.0) colored2 (~> 3.1) - danger (8.0.5) + danger (8.2.3) claide (~> 1.0) claide-plugins (>= 0.9.2) colored2 (~> 3.1) @@ -23,36 +23,44 @@ GEM kramdown-parser-gfm (~> 1.0) no_proxy_fix octokit (~> 4.7) - terminal-table (~> 1) - danger-swiftlint (0.24.4) + terminal-table (>= 1, < 4) + danger-swiftlint (0.26.0) danger rake (> 10) thor (~> 0.19) - faraday (1.0.1) + faraday (1.4.1) + faraday-excon (~> 1.1) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.1) multipart-post (>= 1.2, < 3) + ruby2_keywords (>= 0.0.4) + faraday-excon (1.1.0) faraday-http-cache (2.2.0) faraday (>= 0.8) - git (1.7.0) + faraday-net_http (1.0.1) + faraday-net_http_persistent (1.1.0) + git (1.8.1) rchardet (~> 1.8) - kramdown (2.3.0) + kramdown (2.3.1) rexml kramdown-parser-gfm (1.1.0) kramdown (~> 2.0) multipart-post (2.1.1) nap (1.1.0) no_proxy_fix (0.1.2) - octokit (4.18.0) + octokit (4.21.0) faraday (>= 0.9) sawyer (~> 0.8.0, >= 0.5.3) open4 (1.3.4) public_suffix (4.0.6) - rake (13.0.1) + rake (13.0.3) rchardet (1.8.0) - rexml (3.2.4) + rexml (3.2.5) + ruby2_keywords (0.0.4) sawyer (0.8.2) addressable (>= 2.3.5) faraday (> 0.8, < 2.0) - terminal-table (1.8.0) + terminal-table (3.0.0) unicode-display_width (~> 1.1, >= 1.1.1) thor (0.20.3) unicode-display_width (1.7.0) diff --git a/Package.swift b/Package.swift index cfa4c833..66fde6e1 100644 --- a/Package.swift +++ b/Package.swift @@ -7,7 +7,7 @@ let package = Package( products: [ .library(name: "Swifter", targets: ["Swifter"]), - .executable(name: "Example", targets: ["Example"]) + .executable(name: "SwifterExample", targets: ["SwifterExample"]) ], dependencies: [], @@ -16,22 +16,23 @@ let package = Package( .target( name: "Swifter", dependencies: [], - path: "XCode/Sources" + path: "Xcode/Sources" ), .target( - name: "Example", + name: "SwifterExample", dependencies: [ "Swifter" ], - path: "Example"), + path: "SwifterExample" + ), .testTarget( name: "SwifterTests", dependencies: [ "Swifter" ], - path: "XCode/Tests" + path: "Xcode/Tests" ) ] -) \ No newline at end of file +) diff --git a/README.md b/README.md index 75461d25..c9aa41ac 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ Tiny http server engine written in [Swift](https://developer.apple.com/swift/) programming language. ### Branches -`* stable` - lands on CocoaPods and others. Supports the latest non-beta XCode and SPM. Stable. +`* stable` - lands on CocoaPods and others. Supports the latest non-beta Xcode and SPM. Stable. `* master` - stable branch plus experimental web-framework layer. diff --git a/Swifter.podspec b/Swifter.podspec index e876335c..73b4a501 100644 --- a/Swifter.podspec +++ b/Swifter.podspec @@ -10,7 +10,7 @@ Pod::Spec.new do |s| s.osx.deployment_target = "10.10" s.tvos.deployment_target = "9.0" s.source = { :git => "https://github.com/httpswift/swifter.git", :tag => "1.5.0" } - s.source_files = 'XCode/Sources/*.{swift}' - s.swift_version = '4.2' + s.source_files = 'Xcode/Sources/*.{swift}' + s.swift_version = '5.0' -end \ No newline at end of file +end diff --git a/Example/main.swift b/SwifterExample/main.swift similarity index 100% rename from Example/main.swift rename to SwifterExample/main.swift diff --git a/XCode/LinuxMain.swift b/Xcode/LinuxMain.swift similarity index 99% rename from XCode/LinuxMain.swift rename to Xcode/LinuxMain.swift index 42b4a191..581f29f5 100644 --- a/XCode/LinuxMain.swift +++ b/Xcode/LinuxMain.swift @@ -1,5 +1,4 @@ import XCTest - import SwifterTests var tests = [XCTestCaseEntry]() diff --git a/XCode/Resources/logo.png b/Xcode/Resources/logo.png similarity index 100% rename from XCode/Resources/logo.png rename to Xcode/Resources/logo.png diff --git a/XCode/Sources/DemoServer.swift b/Xcode/Sources/DemoServer.swift similarity index 94% rename from XCode/Sources/DemoServer.swift rename to Xcode/Sources/DemoServer.swift index 51fd73cf..49582147 100644 --- a/XCode/Sources/DemoServer.swift +++ b/Xcode/Sources/DemoServer.swift @@ -30,7 +30,7 @@ public func demoServer(_ publicDir: String) -> HttpServer { } } - server["/magic"] = { .ok(.htmlBody("You asked for " + $0.path)) } + server["/magic"] = { .ok(.htmlBody("You asked for " + $0.path), ["XXX-Custom-Header": "value"]) } server["/test/:param1/:param2"] = { request in scopes { @@ -98,7 +98,7 @@ public func demoServer(_ publicDir: String) -> HttpServer { guard let name = multipart.name, let fileName = multipart.fileName else { continue } response += "Name: \(name) File name: \(fileName) Size: \(multipart.body.count)
" } - return HttpResponse.ok(.htmlBody(response)) + return HttpResponse.ok(.htmlBody(response), ["XXX-Custom-Header": "value"]) } server.GET["/login"] = scopes { @@ -136,7 +136,7 @@ public func demoServer(_ publicDir: String) -> HttpServer { server.POST["/login"] = { request in let formFields = request.parseUrlencodedForm() - return HttpResponse.ok(.htmlBody(formFields.map({ "\($0.0) = \($0.1)" }).joined(separator: "
"))) + return HttpResponse.ok(.htmlBody(formFields.map({ "\($0.0) = \($0.1)" }).joined(separator: "
")), ["XXX-Custom-Header": "value"]) } server["/demo"] = scopes { @@ -165,11 +165,11 @@ public func demoServer(_ publicDir: String) -> HttpServer { server["/long"] = { _ in var longResponse = "" for index in 0..<1000 { longResponse += "(\(index)),->" } - return .ok(.htmlBody(longResponse)) + return .ok(.htmlBody(longResponse), ["XXX-Custom-Header": "value"]) } server["/wildcard/*/test/*/:param"] = { request in - return .ok(.htmlBody(request.path)) + return .ok(.htmlBody(request.path), ["XXX-Custom-Header": "value"]) } server["/stream"] = { _ in diff --git a/XCode/Sources/Errno.swift b/Xcode/Sources/Errno.swift similarity index 100% rename from XCode/Sources/Errno.swift rename to Xcode/Sources/Errno.swift diff --git a/XCode/Sources/Files.swift b/Xcode/Sources/Files.swift similarity index 81% rename from XCode/Sources/Files.swift rename to Xcode/Sources/Files.swift index f778975a..a45e2c5b 100644 --- a/XCode/Sources/Files.swift +++ b/Xcode/Sources/Files.swift @@ -10,19 +10,26 @@ import Foundation public func shareFile(_ path: String) -> ((HttpRequest) -> HttpResponse) { return { _ in if let file = try? path.openForReading() { - return .raw(200, "OK", [:], { writer in + let mimeType = path.mimeType() + var responseHeader: [String: String] = ["Content-Type": mimeType] + + if let attr = try? FileManager.default.attributesOfItem(atPath: path), + let fileSize = attr[FileAttributeKey.size] as? UInt64 { + responseHeader["Content-Length"] = String(fileSize) + } + return .raw(200, "OK", responseHeader, { writer in try? writer.write(file) file.close() }) } - return .notFound + return .notFound() } } public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String] = ["index.html", "default.html"]) -> ((HttpRequest) -> HttpResponse) { return { request in guard let fileRelativePath = request.params.first else { - return .notFound + return .notFound() } if fileRelativePath.value.isEmpty { for path in defaults { @@ -50,19 +57,19 @@ public func shareFilesFromDirectory(_ directoryPath: String, defaults: [String] file.close() }) } - return .notFound + return .notFound() } } public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) { return { request in guard let (_, value) = request.params.first else { - return HttpResponse.notFound + return .notFound() } let filePath = dir + String.pathSeparator + value do { guard try filePath.exists() else { - return .notFound + return .notFound() } if try filePath.directory() { var files = try filePath.files() @@ -85,7 +92,7 @@ public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) { }(request) } else { guard let file = try? filePath.openForReading() else { - return .notFound + return .notFound() } return .raw(200, "OK", [:], { writer in try? writer.write(file) @@ -93,7 +100,7 @@ public func directoryBrowser(_ dir: String) -> ((HttpRequest) -> HttpResponse) { }) } } catch { - return HttpResponse.internalServerError + return HttpResponse.internalServerError(.text("Internal Server Error")) } } } diff --git a/Xcode/Sources/HttpResponse.swift b/Xcode/Sources/HttpResponse.swift index 362db8be..cef8aa41 100644 --- a/Xcode/Sources/HttpResponse.swift +++ b/Xcode/Sources/HttpResponse.swift @@ -51,8 +51,8 @@ public enum HttpResponseBody { try $0.write(data) }) case .htmlBody(let body): - let serialised = "\(body)" - let data = [UInt8](serialised.utf8) + let serialized = "\(body)" + let data = [UInt8](serialized.utf8) return (data.count, { try $0.write(data) }) @@ -61,14 +61,14 @@ public enum HttpResponseBody { try $0.write(data) }) case .custom(let object, let closure): - let serialised = try closure(object) - let data = [UInt8](serialised.utf8) + let serialized = try closure(object) + let data = [UInt8](serialized.utf8) return (data.count, { try $0.write(data) }) } } catch { - let data = [UInt8]("Serialisation error: \(error)".utf8) + let data = [UInt8]("Serialization error: \(error)".utf8) return (data.count, { try $0.write(data) }) @@ -80,12 +80,10 @@ public enum HttpResponseBody { public enum HttpResponse { case switchProtocols([String: String], (Socket) -> Void) - case ok(HttpResponseBody), created, accepted + case ok(HttpResponseBody, [String: String] = [:]), created, accepted case movedPermanently(String) case movedTemporarily(String) - case badRequest(HttpResponseBody?), unauthorized, forbidden, notFound, notAcceptable - case tooManyRequests - case internalServerError + case badRequest(HttpResponseBody?), unauthorized(HttpResponseBody?), forbidden(HttpResponseBody?), notFound(HttpResponseBody? = nil), notAcceptable(HttpResponseBody?), tooManyRequests(HttpResponseBody?), internalServerError(HttpResponseBody?) case raw(Int, String, [String: String]?, ((HttpResponseBodyWriter) throws -> Void)? ) public var statusCode: Int { @@ -133,10 +131,14 @@ public enum HttpResponse { for (key, value) in switchHeaders { headers[key] = value } - case .ok(let body): + case .ok(let body, let customHeaders): + for (key, value) in customHeaders { + headers.updateValue(value, forKey: key) + } switch body { case .json: headers["Content-Type"] = "application/json" - case .html: headers["Content-Type"] = "text/html" + case .html, .htmlBody: headers["Content-Type"] = "text/html" + case .text: headers["Content-Type"] = "text/plain" case .data(_, let contentType): headers["Content-Type"] = contentType default:break } @@ -157,8 +159,8 @@ public enum HttpResponse { func content() -> (length: Int, write: ((HttpResponseBodyWriter) throws -> Void)?) { switch self { - case .ok(let body) : return body.content() - case .badRequest(let body) : return body?.content() ?? (-1, nil) + case .ok(let body, _) : return body.content() + case .badRequest(let body), .unauthorized(let body), .forbidden(let body), .notFound(let body), .tooManyRequests(let body), .internalServerError(let body) : return body?.content() ?? (-1, nil) case .raw(_, _, _, let writer) : return (-1, writer) default : return (-1, nil) } diff --git a/XCode/Sources/HttpRouter.swift b/Xcode/Sources/HttpRouter.swift similarity index 96% rename from XCode/Sources/HttpRouter.swift rename to Xcode/Sources/HttpRouter.swift index 3dac20fd..1429627e 100644 --- a/XCode/Sources/HttpRouter.swift +++ b/Xcode/Sources/HttpRouter.swift @@ -151,6 +151,12 @@ open class HttpRouter { } if let startStarNode = node.nodes["**"] { + if startStarNode.isEndOfRoute { + // ** at the end of a route works as a catch-all + matchedNodes.append(startStarNode) + return + } + let startStarNodeKeys = startStarNode.nodes.keys currentIndex += 1 while currentIndex < count, let pathToken = pattern[currentIndex].removingPercentEncoding { diff --git a/XCode/Sources/HttpServer.swift b/Xcode/Sources/HttpServer.swift similarity index 100% rename from XCode/Sources/HttpServer.swift rename to Xcode/Sources/HttpServer.swift index 06f7f3f6..b8d56790 100644 --- a/XCode/Sources/HttpServer.swift +++ b/Xcode/Sources/HttpServer.swift @@ -42,10 +42,10 @@ open class HttpServer: HttpServerIO { public var delete, patch, head, post, get, put: MethodRoute public subscript(path: String) -> ((HttpRequest) -> HttpResponse)? { + get { return nil } set { router.register(nil, path: path, handler: newValue) } - get { return nil } } public var routes: [String] { @@ -75,10 +75,10 @@ open class HttpServer: HttpServerIO { public let method: String public let router: HttpRouter public subscript(path: String) -> ((HttpRequest) -> HttpResponse)? { + get { return nil } set { router.register(method, path: path, handler: newValue) } - get { return nil } } } } diff --git a/XCode/Sources/HttpServerIO.swift b/Xcode/Sources/HttpServerIO.swift similarity index 98% rename from XCode/Sources/HttpServerIO.swift rename to Xcode/Sources/HttpServerIO.swift index 6ba89656..63fce25b 100644 --- a/XCode/Sources/HttpServerIO.swift +++ b/Xcode/Sources/HttpServerIO.swift @@ -8,7 +8,7 @@ import Foundation import Dispatch -public protocol HttpServerIODelegate: class { +public protocol HttpServerIODelegate: AnyObject { func socketConnectionReceived(_ socket: Socket) } @@ -112,7 +112,7 @@ open class HttpServerIO { } open func dispatch(_ request: HttpRequest) -> ([String: String], (HttpRequest) -> HttpResponse) { - return ([:], { _ in HttpResponse.notFound }) + return ([:], { _ in HttpResponse.notFound(nil) }) } private func handleConnection(_ socket: Socket) { diff --git a/XCode/Sources/MimeTypes.swift b/Xcode/Sources/MimeTypes.swift similarity index 100% rename from XCode/Sources/MimeTypes.swift rename to Xcode/Sources/MimeTypes.swift diff --git a/XCode/Sources/Process.swift b/Xcode/Sources/Process.swift similarity index 100% rename from XCode/Sources/Process.swift rename to Xcode/Sources/Process.swift diff --git a/XCode/Sources/Scopes.swift b/Xcode/Sources/Scopes.swift similarity index 100% rename from XCode/Sources/Scopes.swift rename to Xcode/Sources/Scopes.swift diff --git a/XCode/Sources/Socket+File.swift b/Xcode/Sources/Socket+File.swift similarity index 100% rename from XCode/Sources/Socket+File.swift rename to Xcode/Sources/Socket+File.swift diff --git a/Xcode/Sources/Socket.swift b/Xcode/Sources/Socket.swift index 590360c7..1a9887e9 100644 --- a/Xcode/Sources/Socket.swift +++ b/Xcode/Sources/Socket.swift @@ -149,13 +149,9 @@ open class Socket: Hashable, Equatable { /// - Returns: A buffer containing the bytes read /// - Throws: SocketError.recvFailed if unable to read bytes from the socket open func read(length: Int) throws -> [UInt8] { - var buffer = UnsafeMutableBufferPointer.allocate(capacity: length) - - let bytesRead = try read(into: &buffer, length: length) - - let rv = [UInt8](buffer[0.. HttpServer { let server = HttpServer() - server.GET["/ping"] = { request in + server.GET["/ping"] = { _ in return HttpResponse.ok(.text("pong!")) } return server diff --git a/Xcode/Tests/SwifterTestsHttpParser.swift b/Xcode/Tests/SwifterTestsHttpParser.swift index 0630adbb..b28c2190 100644 --- a/Xcode/Tests/SwifterTestsHttpParser.swift +++ b/Xcode/Tests/SwifterTestsHttpParser.swift @@ -50,7 +50,7 @@ class SwifterTestsHttpParser: XCTestCase { } } - // swiftlint:disable function_body_length + // swiftlint:disable function_body_length cyclomatic_complexity func testParser() { let parser = HttpParser() diff --git a/Xcode/Tests/SwifterTestsHttpRouter.swift b/Xcode/Tests/SwifterTestsHttpRouter.swift index bf26ea28..c4b06df5 100644 --- a/Xcode/Tests/SwifterTestsHttpRouter.swift +++ b/Xcode/Tests/SwifterTestsHttpRouter.swift @@ -85,6 +85,18 @@ class SwifterTestsHttpRouter: XCTestCase { XCTAssertNil(router.route(nil, path: "/a/e/f/g")) } + func testHttpRouterMultiplePathSegmentWildcardTail() { + + router.register(nil, path: "/a/b/**", handler: { _ in + return .ok(.htmlBody("OK")) + }) + + XCTAssertNil(router.route(nil, path: "/")) + XCTAssertNil(router.route(nil, path: "/a")) + XCTAssertNotNil(router.route(nil, path: "/a/b/c/d/e/f/g")) + XCTAssertNil(router.route(nil, path: "/a/e/f/g")) + } + func testHttpRouterEmptyTail() { router.register(nil, path: "/a/b/", handler: { _ in diff --git a/XCode/Tests/SwifterTestsStringExtensions.swift b/Xcode/Tests/SwifterTestsStringExtensions.swift similarity index 100% rename from XCode/Tests/SwifterTestsStringExtensions.swift rename to Xcode/Tests/SwifterTestsStringExtensions.swift diff --git a/XCode/Tests/SwifterTestsWebSocketSession.swift b/Xcode/Tests/SwifterTestsWebSocketSession.swift similarity index 98% rename from XCode/Tests/SwifterTestsWebSocketSession.swift rename to Xcode/Tests/SwifterTestsWebSocketSession.swift index 97a02988..85056464 100644 --- a/XCode/Tests/SwifterTestsWebSocketSession.swift +++ b/Xcode/Tests/SwifterTestsWebSocketSession.swift @@ -29,7 +29,7 @@ class SwifterTestsWebSocketSession: XCTestCase { } } - // swiftlint:disable function_body_length + // swiftlint:disable function_body_length cyclomatic_complexity func testParser() { do { diff --git a/XCode/Tests/XCTestManifests.swift b/Xcode/Tests/XCTestManifests.swift similarity index 85% rename from XCode/Tests/XCTestManifests.swift rename to Xcode/Tests/XCTestManifests.swift index 9f1f15c8..29f22b08 100644 --- a/XCode/Tests/XCTestManifests.swift +++ b/Xcode/Tests/XCTestManifests.swift @@ -1,6 +1,20 @@ #if !canImport(ObjectiveC) import XCTest +extension FilesTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__FilesTests = [ + ("testDirectoryBrowser", testDirectoryBrowser), + ("testDirectoryBrowserNotFound", testDirectoryBrowserNotFound), + ("testShareFile", testShareFile), + ("testShareFileNotFound", testShareFileNotFound), + ("testShareFilesFromDirectory", testShareFilesFromDirectory), + ("testShareFilesFromDirectoryFileNotFound", testShareFilesFromDirectoryFileNotFound), + ] +} + extension IOSafetyTests { // DO NOT MODIFY: This is autogenerated, use: // `swift test --generate-linuxmain` @@ -63,6 +77,7 @@ extension SwifterTestsHttpRouter { ("testHttpRouterHandlesOverlappingPathsInDynamicRoutes", testHttpRouterHandlesOverlappingPathsInDynamicRoutes), ("testHttpRouterHandlesOverlappingPathsInDynamicRoutesInTheMiddle", testHttpRouterHandlesOverlappingPathsInDynamicRoutesInTheMiddle), ("testHttpRouterMultiplePathSegmentWildcards", testHttpRouterMultiplePathSegmentWildcards), + ("testHttpRouterMultiplePathSegmentWildcardTail", testHttpRouterMultiplePathSegmentWildcardTail), ("testHttpRouterPercentEncodedPathSegments", testHttpRouterPercentEncodedPathSegments), ("testHttpRouterShouldHandleOverlappingRoutesInTrail", testHttpRouterShouldHandleOverlappingRoutesInTrail), ("testHttpRouterSimplePathSegments", testHttpRouterSimplePathSegments), @@ -97,6 +112,7 @@ extension SwifterTestsWebSocketSession { public func __allTests() -> [XCTestCaseEntry] { return [ + testCase(FilesTests.__allTests__FilesTests), testCase(MimeTypeTests.__allTests__MimeTypeTests), testCase(ServerThreadingTests.__allTests__ServerThreadingTests), testCase(SwifterTestsHttpParser.__allTests__SwifterTestsHttpParser),