-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
223 additions
and
114 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.build | ||
.git |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,9 @@ | ||
.DS_Store | ||
/.build | ||
/.swiftpm | ||
/.devContainer | ||
/Packages | ||
/*.xcodeproj | ||
xcuserdata/ | ||
DerivedData/ | ||
.swiftpm/configuration/registries.json | ||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata | ||
.netrc | ||
.vscode | ||
Package.resolved | ||
/.vscode/* | ||
!/.vscode/hummingbird.code-snippets |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
# ================================ | ||
# Build image | ||
# ================================ | ||
FROM swift:5.10-jammy as build | ||
|
||
# Install OS updates | ||
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ | ||
&& apt-get -q update \ | ||
&& apt-get -q dist-upgrade -y \ | ||
&& apt-get install -y libjemalloc-dev \ | ||
&& rm -rf /var/lib/apt/lists/* | ||
|
||
# Set up a build area | ||
WORKDIR /build | ||
|
||
# First just resolve dependencies. | ||
# This creates a cached layer that can be reused | ||
# as long as your Package.swift/Package.resolved | ||
# files do not change. | ||
COPY ./Package.* ./ | ||
RUN swift package resolve | ||
|
||
# Copy entire repo into container | ||
COPY . . | ||
|
||
# Build everything, with optimizations, with static linking, and using jemalloc | ||
RUN swift build -c release \ | ||
--static-swift-stdlib \ | ||
-Xlinker -ljemalloc | ||
|
||
# Switch to the staging area | ||
WORKDIR /staging | ||
|
||
# Copy main executable to staging area | ||
RUN cp "$(swift build --package-path /build -c release --show-bin-path)/Todos" ./ | ||
|
||
# Copy static swift backtracer binary to staging area | ||
RUN cp "/usr/libexec/swift/linux/swift-backtrace-static" ./ | ||
|
||
# Copy resources bundled by SPM to staging area | ||
RUN find -L "$(swift build --package-path /build -c release --show-bin-path)/" -regex '.*\.resources$' -exec cp -Ra {} ./ \; | ||
|
||
# Copy any resouces from the public directory and views directory if the directories exist | ||
# Ensure that by default, neither the directory nor any of its contents are writable. | ||
RUN [ -d /build/public ] && { mv /build/public ./public && chmod -R a-w ./public; } || true | ||
|
||
# ================================ | ||
# Run image | ||
# ================================ | ||
FROM ubuntu:jammy | ||
|
||
# Make sure all system packages are up to date, and install only essential packages. | ||
RUN export DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true \ | ||
&& apt-get -q update \ | ||
&& apt-get -q dist-upgrade -y \ | ||
&& apt-get -q install -y \ | ||
libjemalloc2 \ | ||
ca-certificates \ | ||
tzdata \ | ||
# If your app or its dependencies import FoundationNetworking, also install `libcurl4`. | ||
# libcurl4 \ | ||
# If your app or its dependencies import FoundationXML, also install `libxml2`. | ||
# libxml2 \ | ||
&& rm -r /var/lib/apt/lists/* | ||
|
||
# Create a hummingbird user and group with /app as its home directory | ||
RUN useradd --user-group --create-home --system --skel /dev/null --home-dir /app hummingbird | ||
|
||
# Switch to the new home directory | ||
WORKDIR /app | ||
|
||
# Copy built executable and any staged resources from builder | ||
COPY --from=build --chown=hummingbird:hummingbird /staging /app | ||
|
||
# Provide configuration needed by the built-in crash reporter and some sensible default behaviors. | ||
ENV SWIFT_BACKTRACE=enable=yes,sanitize=yes,threads=all,images=all,interactive=no,swift-backtrace=./swift-backtrace-static | ||
|
||
# Ensure all further commands run as the hummingbird user | ||
USER hummingbird:hummingbird | ||
|
||
# Let Docker bind to port 8080 | ||
EXPOSE 8080 | ||
|
||
# Start the Hummingbird service when the image is run, default to listening on 8080 in production environment | ||
ENTRYPOINT ["./Todos"] | ||
CMD ["--hostname", "0.0.0.0", "--port", "8080"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,2 @@ | ||
# Todos Postgres Tutorial | ||
|
||
This is the sample code that goes along with the Postgres Todos [tutorial](https://hummingbird-project.github.io/hummingbird-docs/2.0/tutorials/todos) in the documentation. The application has six routes | ||
|
||
- GET /todos: Lists all the todos in the database | ||
- POST /todos: Creates a new todo | ||
- DELETE /todos: Deletes all the todos | ||
- GET /todos/:id : Returns a single todo with id | ||
- PATCH /todos/:id : Edits todo with id | ||
- DELETE /todos/:id : Deletes todo with id | ||
|
||
A todo consists of a title, order number, url to link to edit/get/delete that todo and whether that todo is complete or not. | ||
|
||
The example requires a postgres database running locally. Follow [instructions](https://hummingbird-project.github.io/hummingbird-docs/2.0/tutorials/hummingbird/todos-4-postgres) in the tutorial to set this up. | ||
# todos-postgres-tutorial | ||
Hummingbird server framework project |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import ArgumentParser | ||
import Hummingbird | ||
import Logging | ||
|
||
@main | ||
struct App: AsyncParsableCommand, AppArguments { | ||
@Option(name: .shortAndLong) | ||
var hostname: String = "127.0.0.1" | ||
|
||
@Option(name: .shortAndLong) | ||
var port: Int = 8080 | ||
|
||
@Option(name: .shortAndLong) | ||
var logLevel: Logger.Level? | ||
|
||
@Flag | ||
var inMemoryTesting: Bool = false | ||
|
||
func run() async throws { | ||
let app = try await buildApplication(self) | ||
try await app.runService() | ||
} | ||
} | ||
|
||
/// Extend `Logger.Level` so it can be used as an argument | ||
#if hasFeature(RetroactiveAttribute) | ||
extension Logger.Level: @retroactive ExpressibleByArgument {} | ||
#else | ||
extension Logger.Level: ExpressibleByArgument {} | ||
#endif |
77 changes: 77 additions & 0 deletions
77
todos-postgres-tutorial/Sources/App/Application+build.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import Hummingbird | ||
import Logging | ||
import PostgresNIO | ||
|
||
/// Application arguments protocol. We use a protocol so we can call | ||
/// `buildApplication` inside Tests as well as in the App executable. | ||
/// Any variables added here also have to be added to `App` in App.swift and | ||
/// `TestArguments` in AppTest.swift | ||
public protocol AppArguments { | ||
var hostname: String { get } | ||
var port: Int { get } | ||
var logLevel: Logger.Level? { get } | ||
var inMemoryTesting: Bool { get } | ||
} | ||
|
||
// Request context used by application | ||
typealias AppRequestContext = BasicRequestContext | ||
|
||
/// Build application | ||
/// - Parameter arguments: application arguments | ||
public func buildApplication(_ arguments: some AppArguments) async throws -> some ApplicationProtocol { | ||
let environment = Environment() | ||
let logger = { | ||
var logger = Logger(label: "todos-postgres-tutorial") | ||
logger.logLevel = | ||
arguments.logLevel ?? | ||
environment.get("LOG_LEVEL").map { Logger.Level(rawValue: $0) ?? .info } ?? | ||
.info | ||
return logger | ||
}() | ||
var postgresRepository: TodoPostgresRepository? | ||
let router: Router<AppRequestContext> | ||
if !arguments.inMemoryTesting { | ||
let client = PostgresClient( | ||
configuration: .init(host: "localhost", username: "todos", password: "todos", database: "hummingbird", tls: .disable), | ||
backgroundLogger: logger | ||
) | ||
let repository = TodoPostgresRepository(client: client, logger: logger) | ||
postgresRepository = repository | ||
router = buildRouter(repository) | ||
} else { | ||
router = buildRouter(TodoMemoryRepository()) | ||
} | ||
var app = Application( | ||
router: router, | ||
configuration: .init( | ||
address: .hostname(arguments.hostname, port: arguments.port), | ||
serverName: "todos-postgres-tutorial" | ||
), | ||
logger: logger | ||
) | ||
// if we setup a postgres service then add as a service and run createTable before | ||
// server starts | ||
if let postgresRepository { | ||
app.addServices(postgresRepository.client) | ||
app.beforeServerStarts { | ||
try await postgresRepository.createTable() | ||
} | ||
} | ||
return app | ||
} | ||
|
||
/// Build router | ||
func buildRouter(_ repository: some TodoRepository) -> Router<AppRequestContext> { | ||
let router = Router(context: AppRequestContext.self) | ||
// Add middleware | ||
router.addMiddleware { | ||
// logging middleware | ||
LogRequestsMiddleware(.info) | ||
} | ||
// Add health endpoint | ||
router.get("/health") { _, _ -> HTTPResponse.Status in | ||
return .ok | ||
} | ||
router.addRoutes(TodoController(repository: repository).endpoints, atPath: "/todos") | ||
return router | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
This file was deleted.
Oops, something went wrong.
8 changes: 5 additions & 3 deletions
8
...-postgres-tutorial/Tests/TodosTests.swift → ...es-tutorial/Tests/AppTests/AppTests.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters