wip
This commit is contained in:
parent
f86552cde7
commit
324ef421e2
|
@ -0,0 +1,67 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRouting"
|
||||||
|
BuildableName = "VaporRouting"
|
||||||
|
BlueprintName = "VaporRouting"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRouting"
|
||||||
|
BuildableName = "VaporRouting"
|
||||||
|
BlueprintName = "VaporRouting"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,114 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRouting"
|
||||||
|
BuildableName = "VaporRouting"
|
||||||
|
BlueprintName = "VaporRouting"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,109 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "YES"
|
||||||
|
customWorkingDirectory = "/tmp"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
<CommandLineArguments>
|
||||||
|
<CommandLineArgument
|
||||||
|
argument = "--allow-debug-build"
|
||||||
|
isEnabled = "YES">
|
||||||
|
</CommandLineArgument>
|
||||||
|
</CommandLineArguments>
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<BuildableProductRunnable
|
||||||
|
runnableDebuggingMode = "0">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "vapor-routing-benchmark"
|
||||||
|
BuildableName = "vapor-routing-benchmark"
|
||||||
|
BlueprintName = "vapor-routing-benchmark"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildableProductRunnable>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Scheme
|
||||||
|
LastUpgradeVersion = "1330"
|
||||||
|
version = "1.3">
|
||||||
|
<BuildAction
|
||||||
|
parallelizeBuildables = "YES"
|
||||||
|
buildImplicitDependencies = "YES">
|
||||||
|
<BuildActionEntries>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "YES"
|
||||||
|
buildForArchiving = "YES"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRouting"
|
||||||
|
BuildableName = "VaporRouting"
|
||||||
|
BlueprintName = "VaporRouting"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
<BuildActionEntry
|
||||||
|
buildForTesting = "YES"
|
||||||
|
buildForRunning = "YES"
|
||||||
|
buildForProfiling = "NO"
|
||||||
|
buildForArchiving = "NO"
|
||||||
|
buildForAnalyzing = "YES">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</BuildActionEntry>
|
||||||
|
</BuildActionEntries>
|
||||||
|
</BuildAction>
|
||||||
|
<TestAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
|
<Testables>
|
||||||
|
<TestableReference
|
||||||
|
skipped = "NO">
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRoutingTests"
|
||||||
|
BuildableName = "VaporRoutingTests"
|
||||||
|
BlueprintName = "VaporRoutingTests"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</TestableReference>
|
||||||
|
</Testables>
|
||||||
|
</TestAction>
|
||||||
|
<LaunchAction
|
||||||
|
buildConfiguration = "Debug"
|
||||||
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
launchStyle = "0"
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
debugDocumentVersioning = "YES"
|
||||||
|
debugServiceExtension = "internal"
|
||||||
|
allowLocationSimulation = "YES">
|
||||||
|
</LaunchAction>
|
||||||
|
<ProfileAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||||
|
savedToolIdentifier = ""
|
||||||
|
useCustomWorkingDirectory = "NO"
|
||||||
|
debugDocumentVersioning = "YES">
|
||||||
|
<MacroExpansion>
|
||||||
|
<BuildableReference
|
||||||
|
BuildableIdentifier = "primary"
|
||||||
|
BlueprintIdentifier = "VaporRouting"
|
||||||
|
BuildableName = "VaporRouting"
|
||||||
|
BlueprintName = "VaporRouting"
|
||||||
|
ReferencedContainer = "container:">
|
||||||
|
</BuildableReference>
|
||||||
|
</MacroExpansion>
|
||||||
|
</ProfileAction>
|
||||||
|
<AnalyzeAction
|
||||||
|
buildConfiguration = "Debug">
|
||||||
|
</AnalyzeAction>
|
||||||
|
<ArchiveAction
|
||||||
|
buildConfiguration = "Release"
|
||||||
|
revealArchiveInOrganizer = "YES">
|
||||||
|
</ArchiveAction>
|
||||||
|
</Scheme>
|
|
@ -46,6 +46,15 @@
|
||||||
"version": "4.3.1"
|
"version": "4.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"package": "swift-argument-parser",
|
||||||
|
"repositoryURL": "https://github.com/apple/swift-argument-parser",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "6b2aa2748a7881eebb9f84fb10c01293e15b52ca",
|
||||||
|
"version": "0.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"package": "swift-backtrace",
|
"package": "swift-backtrace",
|
||||||
"repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
|
"repositoryURL": "https://github.com/swift-server/swift-backtrace.git",
|
||||||
|
@ -55,6 +64,15 @@
|
||||||
"version": "1.3.1"
|
"version": "1.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"package": "Benchmark",
|
||||||
|
"repositoryURL": "https://github.com/google/swift-benchmark",
|
||||||
|
"state": {
|
||||||
|
"branch": null,
|
||||||
|
"revision": "a0564bf88df5f94eec81348a2f089494c6b28d80",
|
||||||
|
"version": "0.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"package": "swift-case-paths",
|
"package": "swift-case-paths",
|
||||||
"repositoryURL": "https://github.com/pointfreeco/swift-case-paths",
|
"repositoryURL": "https://github.com/pointfreeco/swift-case-paths",
|
||||||
|
@ -149,9 +167,9 @@
|
||||||
"package": "URLRouting",
|
"package": "URLRouting",
|
||||||
"repositoryURL": "https://github.com/pointfreeco/swift-url-routing",
|
"repositoryURL": "https://github.com/pointfreeco/swift-url-routing",
|
||||||
"state": {
|
"state": {
|
||||||
"branch": null,
|
"branch": "main",
|
||||||
"revision": "53f56e552b3932d5c11252cb6669a059e9e9e69a",
|
"revision": "97b2826fb5f1300b7b618c300569ed0725ce831a",
|
||||||
"version": "0.1.0"
|
"version": null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -15,7 +15,8 @@ let package = Package(
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
|
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0"),
|
||||||
.package(url: "https://github.com/pointfreeco/swift-url-routing", from: "0.1.0"),
|
.package(url: "https://github.com/pointfreeco/swift-url-routing", branch: "main"), // from: "0.1.0"),
|
||||||
|
.package(name: "Benchmark", url: "https://github.com/google/swift-benchmark", from: "0.1.1"),
|
||||||
],
|
],
|
||||||
targets: [
|
targets: [
|
||||||
.target(
|
.target(
|
||||||
|
@ -32,5 +33,13 @@ let package = Package(
|
||||||
.product(name: "XCTVapor", package: "vapor"),
|
.product(name: "XCTVapor", package: "vapor"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
.executableTarget(
|
||||||
|
name: "vapor-routing-benchmark",
|
||||||
|
dependencies: [
|
||||||
|
"VaporRouting",
|
||||||
|
.product(name: "Benchmark", package: "Benchmark"),
|
||||||
|
.product(name: "Vapor", package: "vapor"),
|
||||||
|
]
|
||||||
|
)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
|
@ -16,9 +16,9 @@ extension URLRequestData {
|
||||||
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
|
let components = URLComponents(url: url, resolvingAgainstBaseURL: false)
|
||||||
else { return nil }
|
else { return nil }
|
||||||
|
|
||||||
let body: [UInt8]?
|
let body: Data?
|
||||||
if var buffer = request.body.data,
|
if var buffer = request.body.data,
|
||||||
let bytes = buffer.readBytes(length: buffer.readableBytes)
|
let bytes = buffer.readData(length: buffer.readableBytes)
|
||||||
{
|
{
|
||||||
body = bytes
|
body = bytes
|
||||||
} else {
|
} else {
|
||||||
|
@ -27,12 +27,12 @@ extension URLRequestData {
|
||||||
|
|
||||||
self.init(
|
self.init(
|
||||||
method: request.method.string,
|
method: request.method.string,
|
||||||
scheme: request.url.scheme,
|
scheme: components.scheme,
|
||||||
user: request.headers.basicAuthorization?.username,
|
user: request.headers.basicAuthorization?.username,
|
||||||
password: request.headers.basicAuthorization?.password,
|
password: request.headers.basicAuthorization?.password,
|
||||||
host: request.url.host,
|
host: components.host,
|
||||||
port: request.url.port,
|
port: components.port,
|
||||||
path: request.url.path,
|
path: components.path,
|
||||||
query: components.queryItems?.reduce(into: [:]) { query, item in
|
query: components.queryItems?.reduce(into: [:]) { query, item in
|
||||||
query[item.name, default: []].append(item.value)
|
query[item.name, default: []].append(item.value)
|
||||||
} ?? [:],
|
} ?? [:],
|
||||||
|
@ -45,7 +45,7 @@ extension URLRequestData {
|
||||||
},
|
},
|
||||||
uniquingKeysWith: { $0 + $1 }
|
uniquingKeysWith: { $0 + $1 }
|
||||||
),
|
),
|
||||||
body: body.map { Data($0) }
|
body: body
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,54 @@ extension Application {
|
||||||
public func mount<R: Parser>(
|
public func mount<R: Parser>(
|
||||||
_ router: R,
|
_ router: R,
|
||||||
use closure: @escaping (Request, R.Output) async throws -> AsyncResponseEncodable
|
use closure: @escaping (Request, R.Output) async throws -> AsyncResponseEncodable
|
||||||
|
) where R.Input == URLRequestData {
|
||||||
|
self.middleware.use(AsyncRoutingMiddleware(router: router, respond: closure))
|
||||||
|
}
|
||||||
|
|
||||||
|
@_disfavoredOverload
|
||||||
|
public func _mount<R: Parser>(
|
||||||
|
_ router: R,
|
||||||
|
use closure: @escaping (Request, R.Output) -> EventLoopFuture<ResponseEncodable>
|
||||||
) where R.Input == URLRequestData {
|
) where R.Input == URLRequestData {
|
||||||
self.middleware.use(RoutingMiddleware(router: router, respond: closure))
|
self.middleware.use(RoutingMiddleware(router: router, respond: closure))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private struct RoutingMiddleware<Router: Parser>: AsyncMiddleware
|
private struct RoutingMiddleware<Router: Parser>: Middleware
|
||||||
|
where Router.Input == URLRequestData {
|
||||||
|
let router: Router
|
||||||
|
let respond: (Request, Router.Output) -> EventLoopFuture<ResponseEncodable>
|
||||||
|
|
||||||
|
public func respond(
|
||||||
|
to request: Request,
|
||||||
|
chainingTo next: Responder
|
||||||
|
) -> EventLoopFuture<Response> {
|
||||||
|
|
||||||
|
guard let requestData = URLRequestData(request: request)
|
||||||
|
else { return next.respond(to: request) }
|
||||||
|
|
||||||
|
let route: Router.Output
|
||||||
|
do {
|
||||||
|
route = try self.router.parse(requestData)
|
||||||
|
return self.respond(request, route)
|
||||||
|
.flatMap { $0.encodeResponse(for: request) }
|
||||||
|
} catch let routingError {
|
||||||
|
return next.respond(to: request)
|
||||||
|
.flatMapError { error in
|
||||||
|
request.logger.info("\(routingError)")
|
||||||
|
|
||||||
|
guard request.application.environment == .development
|
||||||
|
else { return request.eventLoop.makeFailedFuture(error) }
|
||||||
|
|
||||||
|
return request.eventLoop.makeSucceededFuture(
|
||||||
|
Response(status: .notFound, body: .init(string: "Routing \(routingError)"))
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private struct AsyncRoutingMiddleware<Router: Parser>: AsyncMiddleware
|
||||||
where Router.Input == URLRequestData {
|
where Router.Input == URLRequestData {
|
||||||
let router: Router
|
let router: Router
|
||||||
let respond: (Request, Router.Output) async throws -> AsyncResponseEncodable
|
let respond: (Request, Router.Output) async throws -> AsyncResponseEncodable
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import Benchmark
|
||||||
|
|
||||||
|
extension BenchmarkSuite {
|
||||||
|
func benchmark(
|
||||||
|
_ name: String,
|
||||||
|
run: @escaping () throws -> Void,
|
||||||
|
setUp: @escaping () -> Void = {},
|
||||||
|
tearDown: @escaping () -> Void = {}
|
||||||
|
) {
|
||||||
|
self.register(
|
||||||
|
benchmark: Benchmarking(name: name, run: run, setUp: setUp, tearDown: tearDown)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Benchmarking: AnyBenchmark {
|
||||||
|
let name: String
|
||||||
|
let settings: [BenchmarkSetting] = []
|
||||||
|
private let _run: () throws -> Void
|
||||||
|
private let _setUp: () -> Void
|
||||||
|
private let _tearDown: () -> Void
|
||||||
|
|
||||||
|
init(
|
||||||
|
name: String,
|
||||||
|
run: @escaping () throws -> Void,
|
||||||
|
setUp: @escaping () -> Void = {},
|
||||||
|
tearDown: @escaping () -> Void = {}
|
||||||
|
) {
|
||||||
|
self.name = name
|
||||||
|
self._run = run
|
||||||
|
self._setUp = setUp
|
||||||
|
self._tearDown = tearDown
|
||||||
|
}
|
||||||
|
|
||||||
|
func setUp() {
|
||||||
|
self._setUp()
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(_ state: inout BenchmarkState) throws {
|
||||||
|
try self._run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func tearDown() {
|
||||||
|
self._tearDown()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,319 @@
|
||||||
|
import Benchmark
|
||||||
|
import URLRouting
|
||||||
|
import Vapor
|
||||||
|
import VaporRouting
|
||||||
|
|
||||||
|
let routingSuite = BenchmarkSuite(name: "Routing", settings: MaxIterations(1_000)) { suite in
|
||||||
|
LoggingSystem.bootstrap { _ in SwiftLogNoOpLogHandler() }
|
||||||
|
|
||||||
|
let eventLoop = EmbeddedEventLoop()
|
||||||
|
var app: Application!
|
||||||
|
var req: Request!
|
||||||
|
var res: Response!
|
||||||
|
|
||||||
|
struct NoopMiddleware: Middleware {
|
||||||
|
func respond(to request: Request, chainingTo next: Responder) -> EventLoopFuture<Response> {
|
||||||
|
request.eventLoop.makeSucceededFuture(.init())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.baseline") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app.middleware.use(NoopMiddleware())
|
||||||
|
req = .init(application: app, method: .GET, url: .init(string: "/"), on: eventLoop)
|
||||||
|
} tearDown: {
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.home (no-op)") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(application: app, method: .GET, url: .init(string: "/"), on: eventLoop)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.home") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(application: app, method: .GET, url: .init(string: "/"), on: eventLoop)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.createUser") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .POST,
|
||||||
|
url: .init(string: "/users"),
|
||||||
|
headers: ["content-type": "application/json"],
|
||||||
|
collectedBody: .init(string: #"{"name":"Blob","bio":"Blobbed around the world!"}"#),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.createUser") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .POST,
|
||||||
|
url: .init(string: "/users"),
|
||||||
|
collectedBody: .init(string: #"{"name":"Blob","bio":"Blobbed around the world!"}"#),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.fetchUser") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(application: app, method: .GET, url: .init(string: "/users/42"), on: eventLoop)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.fetchUser") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(application: app, method: .GET, url: .init(string: "/users/42"), on: eventLoop)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.bookSearch") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/search"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.bookSearch") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/search"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.bookSearchQuery") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/search?direction=desc&sort=category&count=100"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.bookSearchQuery") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/search?direction=desc&sort=category&count=100"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
suite.benchmark("Vapor.fetchUserBook") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
try! routes(app)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/deadbeef-dead-beef-dead-beefdeadbeef"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
|
||||||
|
suite.benchmark("VaporRouting.fetchUserBook") {
|
||||||
|
res = try app.responder.respond(to: req).wait()
|
||||||
|
} setUp: {
|
||||||
|
app = .init()
|
||||||
|
app._mount(siteRouter, use: siteHandler)
|
||||||
|
req = .init(
|
||||||
|
application: app,
|
||||||
|
method: .GET,
|
||||||
|
url: .init(string: "/users/42/books/deadbeef-dead-beef-dead-beefdeadbeef"),
|
||||||
|
on: eventLoop
|
||||||
|
)
|
||||||
|
} tearDown: {
|
||||||
|
precondition(res.status == .ok)
|
||||||
|
app.shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CreateUser: Codable {
|
||||||
|
let bio: String
|
||||||
|
let name: String
|
||||||
|
}
|
||||||
|
struct SearchOptions: Decodable {
|
||||||
|
var sort: Sort = .title
|
||||||
|
var direction: Direction = .asc
|
||||||
|
var count = 10
|
||||||
|
|
||||||
|
enum Direction: String, CaseIterable, Decodable {
|
||||||
|
case asc, desc
|
||||||
|
}
|
||||||
|
enum Sort: String, CaseIterable, Decodable {
|
||||||
|
case title, category
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@inline(never)
|
||||||
|
public func blackHole<T>(_ x: T) {}
|
||||||
|
|
||||||
|
func routes(_ app: Application) throws {
|
||||||
|
app.get { req -> Response in
|
||||||
|
return .init()
|
||||||
|
}
|
||||||
|
app.post("users") { req -> Response in
|
||||||
|
blackHole(try req.content.decode(CreateUser.self))
|
||||||
|
return .init()
|
||||||
|
}
|
||||||
|
app.get("users", ":userId") { req -> Response in
|
||||||
|
blackHole(try req.parameters.require("userId", as: Int.self))
|
||||||
|
return .init()
|
||||||
|
}
|
||||||
|
app.get("users", ":userId", "books", "search") { req -> Response in
|
||||||
|
blackHole(try req.parameters.require("userId", as: Int.self))
|
||||||
|
blackHole((try? req.query.get(SearchOptions.Sort.self, at: "sort")) ?? .title)
|
||||||
|
blackHole((try? req.query.get(SearchOptions.Direction.self, at: "sort")) ?? .asc)
|
||||||
|
blackHole((try? req.query.get(Int.self, at: "count")) ?? 10)
|
||||||
|
return .init()
|
||||||
|
}
|
||||||
|
app.get("users", ":userId", "books", ":bookId") { req -> Response in
|
||||||
|
blackHole(try req.parameters.require("userId", as: Int.self))
|
||||||
|
blackHole(try req.parameters.require("bookId", as: UUID.self))
|
||||||
|
return .init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum BookRoute {
|
||||||
|
case fetch
|
||||||
|
}
|
||||||
|
enum BooksRoute {
|
||||||
|
case book(UUID, BookRoute = .fetch)
|
||||||
|
case search(SearchOptions = .init())
|
||||||
|
}
|
||||||
|
enum UserRoute {
|
||||||
|
case books(BooksRoute = .search())
|
||||||
|
case fetch
|
||||||
|
}
|
||||||
|
enum UsersRoute {
|
||||||
|
case create(CreateUser)
|
||||||
|
case user(Int, UserRoute = .fetch)
|
||||||
|
}
|
||||||
|
enum SiteRoute {
|
||||||
|
case home
|
||||||
|
case users(UsersRoute)
|
||||||
|
}
|
||||||
|
|
||||||
|
let bookRouter = OneOf {
|
||||||
|
Route(.case(BookRoute.fetch))
|
||||||
|
}
|
||||||
|
let booksRouter = OneOf {
|
||||||
|
Route(.case(BooksRoute.search)) {
|
||||||
|
Path { From(.utf8) { "search".utf8 } }
|
||||||
|
Parse(.memberwise(SearchOptions.init)) {
|
||||||
|
Query {
|
||||||
|
Field("sort", .string.representing(SearchOptions.Sort.self), default: .title)
|
||||||
|
Field("direction", .string.representing(SearchOptions.Direction.self), default: .asc)
|
||||||
|
Field("count", default: 10) { Digits() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Route(.case(BooksRoute.book)) {
|
||||||
|
Path { UUID.parser() }
|
||||||
|
bookRouter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let userRouter = OneOf {
|
||||||
|
Route(.case(UserRoute.fetch))
|
||||||
|
Route(.case(UserRoute.books)) {
|
||||||
|
Path { From(.utf8) { "books".utf8 } }
|
||||||
|
booksRouter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let usersRouter = OneOf {
|
||||||
|
Route(.case(UsersRoute.create)) {
|
||||||
|
Method.post
|
||||||
|
Body(.json(CreateUser.self))
|
||||||
|
}
|
||||||
|
Route(.case(UsersRoute.user)) {
|
||||||
|
Path { Digits() }
|
||||||
|
userRouter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let siteRouter = OneOf {
|
||||||
|
Route(.case(SiteRoute.home))
|
||||||
|
Route(.case(SiteRoute.users)) {
|
||||||
|
Path { From(.utf8) { "users".utf8 } }
|
||||||
|
usersRouter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func siteHandler(request: Request, route: SiteRoute) -> EventLoopFuture<ResponseEncodable> {
|
||||||
|
request.eventLoop.makeSucceededFuture(Response())
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
import Benchmark
|
||||||
|
|
||||||
|
Benchmark.main(
|
||||||
|
[
|
||||||
|
defaultBenchmarkSuite,
|
||||||
|
routingSuite,
|
||||||
|
]
|
||||||
|
)
|
Loading…
Reference in New Issue