<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Optical Aberration</title><description>Used to make video games, can't be arsed anymore.</description><link>https://opticalaberration.com</link><language>en</language><lastBuildDate>Sat, 26 Oct 2024 15:18:32 +0000</lastBuildDate><pubDate>Sat, 26 Oct 2024 15:18:32 +0000</pubDate><ttl>1440</ttl><atom:link href="https://opticalaberration.com/feed.xml" rel="self" type="application/rss+xml"/><item><guid>https://opticalaberration.com/2024/10/writing-responses.html</guid><link>https://opticalaberration.com/2024/10/writing-responses.html</link><title>The complexity of writing responses</title><description>It's been a while since I posted anything to my blog. I thought I would write this article though because it has been an issue that has had a lot of discussion among key members of the swift on server community.We recently released version 2.0 of Hummingbird the swift server framework. During its development the thing that has probably taken the most of my head space is how to return an HTTP response with a streamed payload within the structured concurrency paradigm.To provide some context, each request to…</description><pubDate>Sat, 26 Oct 2024 16:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="the_complexity_of_writing_responses">The complexity of writing responses</h1><div class="article-icon">
<a href="https://github.com/hummingbird-project"><img src="/images/hummingbird-logo256.png"/></a>
</div><p>It's been a while since I posted anything to my blog. I thought I would write this article though because it has been an issue that has had a lot of discussion among key members of the swift on server community.</p><p>We recently released version 2.0 of Hummingbird the swift server framework. During its development the thing that has probably taken the most of my head space is how to return an HTTP response with a streamed payload within the structured concurrency paradigm.</p><p>To provide some context, each request to the server is processed by a middleware stack and then an endpoint that returns a response which will be processed by the middleware stack in the reverse order. One of the key features is that each middleware must be able to process the response payload as it traverses back down the stack.</p><p>The example route I'm going to use to demonstrate the issues will return a response where the payload consists of 10 chunks of data, each 1K of random bytes, with a one second pause between sending each chunk.</p><h2 id="asyncsequence">AsyncSequence</h2><p>The first tool in the box that most people will reach for in this situation is an AsyncSequence of byte buffers. It seems obvious they allow us to provide a stream of data over time. In middleware you can process the contents of the response payload by mapping the results of one AsyncSequence onto another.</p><p>But in this situation it is not the right tool. You need to return from your endpoint handler back to the server level of your application to read your AsyncSequence and write the results out to the underlying transport, but you also need a task to feed the AsyncSequence with buffers, but if you have already returned from your endpoint that task cannot be generated in a structured way. Below is an example demonstrating the issue.</p><pre><code><span class="swift-keyword">func</span> stream(request: <span class="swift-type">Request</span>) <span class="swift-keyword">async throws</span> -&gt; <span class="swift-type">Response</span> {
    <span class="swift-keyword">let</span> (stream, cont) = <span class="swift-type">AsyncStream</span>.<span class="swift-call">makeStream</span>(of: [<span class="swift-type">UInt8</span>].<span class="swift-keyword">self</span>)
    <span class="swift-comment">// the only way I can feed the AsyncStream is with an unstructured
    // task.</span>
    <span class="swift-type">Task</span> {
        <span class="swift-keyword">for _ in</span> <span class="swift-number">0</span>..&lt;<span class="swift-number">10</span> {
            <span class="swift-keyword">try await</span> <span class="swift-type">Task</span>.<span class="swift-call">sleep</span>(for: .<span class="swift-call">seconds</span>(<span class="swift-number">1</span>))
            <span class="swift-keyword">let</span> buffer = (<span class="swift-number">0</span>..&lt;size).<span class="swift-call">map</span> { <span class="swift-keyword">_ in</span> <span class="swift-type">UInt8</span>.<span class="swift-call">random</span>(in: <span class="swift-number">0</span>...<span class="swift-number">255</span>) }
            cont.<span class="swift-call">yield</span>(buffer)
        }
        cont.<span class="swift-call">finish</span>()
    }
    <span class="swift-keyword">return</span> <span class="swift-type">Response</span>(status: .<span class="swift-dotAccess">ok</span>, body: stream)
}</code></pre><h2 id="response_body_writer_with_closure">Response body writer with closure</h2><p>The second solution is to use a closure that accepts a writer type for the response body. The endpoint returns the closure and at the server level this closure is called with a writer type that writes data to the underlying transport.</p><pre><code><span class="swift-keyword">func</span> stream(request: <span class="swift-type">Request</span>) <span class="swift-keyword">async throws</span> -&gt; <span class="swift-type">Response</span> {
    <span class="swift-keyword">let</span> responseBody = <span class="swift-type">ResponseBody</span> { writer <span class="swift-keyword">in 
        for _ in</span> <span class="swift-number">0</span>..&lt;<span class="swift-number">10</span> {
            <span class="swift-keyword">try await</span> <span class="swift-type">Task</span>.<span class="swift-call">sleep</span>(for: .<span class="swift-call">seconds</span>(<span class="swift-number">1</span>))
            <span class="swift-keyword">let</span> buffer = (<span class="swift-number">0</span>..&lt;size).<span class="swift-call">map</span> { <span class="swift-keyword">_ in</span> <span class="swift-type">UInt8</span>.<span class="swift-call">random</span>(in: <span class="swift-number">0</span>...<span class="swift-number">255</span>) }
            <span class="swift-keyword">try await</span> writer.<span class="swift-call">write</span>(buffer)
        }
    }
    <span class="swift-keyword">return</span> <span class="swift-type">Response</span>(status: .<span class="swift-dotAccess">ok</span>, body: responseBody)
}</code></pre><p>Using this method it is easy to add shortcuts to ResponseBody to make it easy to return single buffers, sequences of buffers etc</p><pre><code><span class="swift-keyword">extension</span> <span class="swift-type">ResponseBody</span> {
    <span class="swift-keyword">public init</span>(buffer: <span class="swift-type">ByteBuffer</span>) {
        <span class="swift-keyword">self</span>.<span class="swift-keyword">init</span> { writer <span class="swift-keyword">in
            try await</span> writer.<span class="swift-call">write</span>(buffer)
        }
    }

    <span class="swift-keyword">public func init</span>(contentsOf buffers: <span class="swift-keyword">some</span> <span class="swift-type">Sequence</span>&lt;<span class="swift-type">ByteBuffer</span>&gt;) {
        <span class="swift-keyword">self</span>.<span class="swift-keyword">init</span> { writer <span class="swift-keyword">in
            for</span> buffer <span class="swift-keyword">in</span> buffers {
                <span class="swift-keyword">try await</span> writer.<span class="swift-call">write</span>(buffer)
            }
        }
    }
}</code></pre><p>By creating a new writer type that processes your response payload and passes it onto the original writer provided you can process the response body in a middleware as well. For this to work though you need a protocol defining the requirements for your writer type and then accept an existential of this protocol in your response closure so any writer can be used.</p><pre><code><span class="swift-keyword">let</span> newResponseBody = <span class="swift-type">ResponseBody</span> { writer <span class="swift-keyword">in
    let</span> newWriter = <span class="swift-type">TransformingWriter</span>(writer)
    <span class="swift-keyword">try await</span> oldResponseBody.<span class="swift-call">write</span>(newWriter)
}</code></pre><p>This isn't strictly true structured concurrency though. The closure you construct in your endpoint function isn't being run while you are in that function. The idea behind structured concurrency is that all the code encapsulated inside a single function has finished by the time you leave that function.</p><h2 id="passing_in_a_response_writer">Passing in a response writer</h2><p>The third solution allows you to write endpoint functions in a completely structured way. We do this by passing the writer into the endpoint function and have the function write the response itself.</p><pre><code><span class="swift-keyword">func</span> stream(request: <span class="swift-type">Request</span>, responseWriter: <span class="swift-type">ResponseWriter</span>) <span class="swift-keyword">async throws</span> {
    <span class="swift-keyword">try await</span> responseWriter.<span class="swift-call">writeHead</span>(status: .<span class="swift-dotAccess">ok</span>)
    <span class="swift-keyword">for _ in</span> <span class="swift-number">0</span>..&lt;<span class="swift-number">10</span> {
        <span class="swift-keyword">try await</span> <span class="swift-type">Task</span>.<span class="swift-call">sleep</span>(for: .<span class="swift-call">seconds</span>(<span class="swift-number">1</span>))
        <span class="swift-keyword">let</span> buffer = (<span class="swift-number">0</span>..&lt;size).<span class="swift-call">map</span> { <span class="swift-keyword">_ in</span> <span class="swift-type">UInt8</span>.<span class="swift-call">random</span>(in: <span class="swift-number">0</span>...<span class="swift-number">255</span>) }
        <span class="swift-keyword">try await</span> responseWriter.<span class="swift-call">writeBody</span>(buffer)
    }
    responseWriter.<span class="swift-call">finish</span>()
}</code></pre><p>By the time we leave this function we know for sure all response writing has finished. It passes all the requirements of structured concurrency. It is the most flexible method and allows us to do more complex things like sending informational status (1xx) responses separately from the main response.</p><p>But it also passes a lot of the complexity of writing the response onto the end user. Ergonomically it is more awkward to write than just returning a Response. Error handling is complex, you have to keep track of what parts of the response you have written. You have to differentiate between errors generated that you want to provide responses for eg authentication errors and errors that occurred when writing the response to the underlying transport. Some of this can be caught at compile time with clever usage of non-copyable types, but even so this doesn't reduce the complexity pushed onto your endpoint function.</p><p>I don't know of a solution for implementing middleware processing of response payloads using this method though. I haven't looked into it too hard but I imagine it would involve passing in a new response writer type that wraps the original response write.</p><h2 id="hummingbird">Hummingbird</h2><p>So what did I end up going for in Hummingbird? I ended up going for a combination of the third and second methods. I don't think most end users want the added complexity, so at the router level where most users will experience Hummingbird we use a version of method 2. We can hide the complexity of the response writing as it is encapsulated in one type but still allows users to do more complex things.</p><p>It is possible to implement method 2 on top of a server using method 3. If you return a response which consists of the response head and body writing closure, you can use a response writer to write the returned head, then pass a response body writer that writes to the response writer into the response body closure. Because of this at the server level we have implemented method 3.</p><p>If someone wants to write a server that uses response writers they can still use the Hummingbird server, they'll just need to write their own Router.</p><p>You find the Hummingbird implementation <a href="https://github.com/hummingbird-project/hummingbird/tree/main/Sources/HummingbirdCore/Response">here</a>.</p><h2 id="other_packages">Other packages</h2><p>What are other packages in the Swift on server eco-system doing? There are two other packages I know that are tackling this issue at the moment. Version 2.0 of <a href="https://github.com/grpc/grpc-swift">gRPC</a> currently in development is using a version of method 2. The <a href="https://github.com/swift-server/swift-aws-lambda-runtime/pull/339">proposal</a> for v2 of swift-aws-lambda-runtime is considering something similar to method 3. So there is no correct way to do this, it just depends on your preferences.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2022/11/vscode-features.html</guid><link>https://opticalaberration.com/2022/11/vscode-features.html</link><title>VS Code Swift extension lesser known features</title><description>For most of this year I have been working on the Swift extension for Visual Studio Code. The work is part of the Swift Server Workgroup push to improve the Swift development experience outside of the Apple eco-system. In July I posted an article on the &lt;a href="https://www.swift.org/blog/vscode-extension/"&gt;swift.org&lt;/a&gt; website giving an overview of the extension and what functionality it provides. Given this was a general overview a number of the more minor features were not included in that article…</description><pubDate>Thu, 10 Nov 2022 11:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="vs_code_swift_extension_lesser_known_features">VS Code Swift extension lesser known features</h1><p>For most of this year I have been working on the Swift extension for Visual Studio Code. The work is part of the Swift Server Workgroup push to improve the Swift development experience outside of the Apple eco-system. In July I posted an article on the <a href="https://www.swift.org/blog/vscode-extension/">swift.org</a> website giving an overview of the extension and what functionality it provides. Given this was a general overview a number of the more minor features were not included in that article. Below is a list of some of those, plus some new features that have been added since the original article was written.</p><h2 id="local_editing_of_packages">Local editing of packages</h2><p>The extension provides the ability to replace a package dependency with a locally edited version of that dependency via a context menu in the package dependency view. Right click on the dependency you want to replace and select <code>Use Local Version</code>. A file dialog will come up. Select the folder for the local version of the dependency and you will now be using that version of the dependency. If you want to edit the code in the local version, right click on the dependency again and select <code>Add to Workspace</code>. This will add the package to your workspace. To revert to using the the original version of the dependency there is a context menu entry <code>Revert to Original Version</code>.</p><img src="/images/vscode-edit-local.png"/><p>I would have included this in the original swift.org article except with Swift 5.6 the feature is a bit flakey. Sometimes the edit state would be changed without any user input. This has since been resolved in Swift 5.7.</p><h2 id="commands">Commands</h2><p>The VS Code Swift extension adds a number of Swift related commands. To bring up the command list press <code>Cmd+Shift+P</code> (<code>Ctrl+Shift+P</code> on Linux). Then type "swift" in the filter bar at the top. This will display the list of commands available to you given the current context. Some commands are only available in certain situations.</p><h3 id="running_swift_scripts">Running Swift Scripts</h3><p>The command <code>Run Swift Script</code> will use the contents of the current editor that has focus and run it as a Swift script. It is not necessary to have a file that backs up the editor contents. This means you can open a new file, set its type to Swift and treat its contents as if it is a Swift Playground. With this you can test new Swift features quickly and easily or maybe remind yourself how an API works. Swift scripts are limited to only importing frameworks that come with your Swift installation like <code>Foundation</code>.</p><h3 id="running_debugging_swift_snippets">Running/Debugging Swift Snippets</h3><p>A Swift Snippet is a new feature of Swift 5.7. They are single Swift files meant to demonstrate features of a Swift package. They can be used to provide code to be display inline in documentation, or complete sample projects. The extension provides two functions to ensure Snippets work as expected. <code>Run Swift Snippet</code> which will run the Snippet and display its output in the terminal and <code>Debug Swift Snippet</code> which will run the Snippet inside a debugger. Both of these commands and the <code>Run Swift Script</code> command are available via the <code>Swift</code> submenu of the editor context menu.</p><h3 id="select_xcode_install">Select Xcode Install</h3><p>On macOS Visual Studio Code gets its Swift toolchain/SDK from your Xcode installation. By default it will use the toolchain included in your active Xcode installation ie the one returned from <code>xcode-select -p</code>. If you would like to use a toolchain from a different Xcode installation there is a command <code>Select Xcode Developer Dir</code>. This will display a list of all the Xcode installations on your system. Selecting one will set the toolchain for your current workspace.</p><h2 id="comment_completion">Comment Completion</h2><p>Documenting your code is important and there is a standard method to provide inline documentation for functions in Swift. It involves a block comment with each line prefixed by <code>///</code>. it includes a description of your function, the parameters passed in and the return value. Remembering the format for this comment can be a pain. So the extension provides a text completion snippet to generate this block comment. Type <code>///</code> above a function and an option to insert the block comment will appear next to your cursor. Press return and it will be inserted. You can move between the function description, parameter descriptions and return value description by pressing tab.</p><img src="/images/vscode-comment-completion.png"/><h2 id="swift_log">Swift Log</h2><p>Go to the output pane (Cmd+Shift+U). In the drop down box on the right hand of the screen select <code>Swift</code>. This will show a log of many of the operations the Swift extension has performed. You can extend this log by enabling the <code>Swift: Diagnostics</code> setting. If you are having an issue with the extension and want to add an Issue to the GitHub repository, it is very helpful if you also provide the contents of this log.</p><h2 id="swift_command_plugins">Swift Command Plugins</h2><p>The extension will create a Task for each Swift command plugin. Select <code>Run Task...</code> from the <code>Terminal</code> menu and type <code>swift-plugin</code> in the filter bar. A list of the Command Plugins attached to the Swift Packages you have in your workspace will appear. Select one to run it. You can edit the options for a plugin by pressing the cog icon on the right hand side of the menu. This will generate an entry in the <code>tasks.json</code> file which you can edit. Below you can see an edited task for building documentation for the MQTTNIO package.</p><img src="/images/vscode-command-task.png"/><!--
```json
{
    "version": "2.0.0",
    "tasks": [
        {
            "type": "swift-plugin",
            "command": "generate-documentation",
            "args": [
                "--target",
                "MQTTNIO",
                "--output-path",
                "./docs",
                "--transform-for-static-hosting"
            ],
            "disableSandbox": false,
            "allowWritingToPackageDirectory": true,
            "problemMatcher": [],
            "label": "swift: Swift-DocC Static Site",
            "detail": "swift package generate-documentation"
        }
    ]
}
```
--><p>The list of features above alongside the <a href="https://www.swift.org/blog/vscode-extension/">swift.org</a> article cover most of the features of the Visual Studio Code Swift extension. Hopefully this article has give some exposure to some of those lesser known features.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/12/proxy-server.html</guid><link>https://opticalaberration.com/2021/12/proxy-server.html</link><title>Building a HTTP Proxy with Swift</title><description>In this article I am going to cover how to build a HTTP Proxy server using Swift. We will use the &lt;a href="https://github.com/hummingbird-project/hummingbird"&gt;Hummingbird&lt;/a&gt; HTTP server framework as the basis for the server and use the Swift server &lt;a href="https://github.com/swift-server/async-http-client"&gt;AsyncHTTPClient&lt;/a&gt; HTTP client to forward on requests to the target service.A proxy server is a service that sits between a client and another service. It forwards messages from the client onto the…</description><pubDate>Fri, 3 Dec 2021 12:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="building_a_http_proxy_with_swift">Building a HTTP Proxy with Swift</h1><div class="article-update">

Since writing this post we have released Hummingbird v2 which makes building a proxy considerably more simple. You can find a new version of the sample code <a href="https://github.com/hummingbird-project/hummingbird-examples/tree/main/proxy-server">here</a>. The swiftonserver.com site has a more up to date <a href="https://swiftonserver.com/how-to-build-a-proxy-server-with-hummingbird/">article</a> about this.

</div><p>In this article I am going to cover how to build a HTTP Proxy server using Swift. We will use the <a href="https://github.com/hummingbird-project/hummingbird">Hummingbird</a> HTTP server framework as the basis for the server and use the Swift server <a href="https://github.com/swift-server/async-http-client">AsyncHTTPClient</a> HTTP client to forward on requests to the target service.</p><h2 id="what_is_a_proxy_server">What is a proxy server</h2><p>A proxy server is a service that sits between a client and another service. It forwards messages from the client onto the other service and returns the responses received back to the client. Before forwarding messages it may process these in some manner and similarly it can process responses returned.</p><h2 id="uses">Uses</h2><p>Proxy servers can be used for many purposes: as a gateway between different domains, providing an authentication layer to a service, allowing anonymous access to services, logging API calls, load balancing by passing requests to one of many instances of a service, caching responses, decrypting TLS requests and encrypting responses.</p><h2 id="let_s_build_one">Let’s build one</h2><p>In this article we are going to build a proxy server that just forwards HTTP packets on to the target service. You can find the sample code for the article <a href="https://github.com/hummingbird-project/hummingbird-examples/tree/main/proxy-server">here</a>.</p><h2 id="creating_the_project">Creating the project</h2><p>We will use the <a href="https://github.com/hummingbird-project/template">Hummingbird template project</a> as the starting point for our server. We can either clone this repository, or press the <code>use this template</code> button on the GitHub web page for the project and create our own repo. The template project creates a server and starts it, provides command line options and a place to configure our application. More can be found out about it <a href="https://opticalaberration.com/2021/12/hummingbird-template.html">here</a>.</p><h2 id="add_asynchttpclient">Add AsyncHTTPClient</h2><p>We are using <code>AsyncHTTPClient</code> in our project so we need to add it as a dependency in <code>Package.swift</code>.</p><p>First add it as a Package dependency</p><pre><code>dependencies: [
    ...
    .<span class="swift-call">package</span>(url: <span class="swift-string">"https://github.com/swift-server/async-http-client.git"</span>, from: <span class="swift-string">"1.6.0"</span>),
],</code></pre><p>And then add it as a target dependency</p><pre><code>targets: [
    .<span class="swift-call">executableTarget</span>(name: <span class="swift-string">"App"</span>,
        dependencies: [
            ...
            .<span class="swift-call">product</span>(name: <span class="swift-string">"AsyncHTTPClient"</span>, package: <span class="swift-string">"async-http-client"</span>),
        ],</code></pre><p>We are going to store the <code>HTTPClient</code> as an extension to the <code>HBApplication</code>. This allows us to manage the <code>HTTPClient</code>'s lifecycle and call <code>syncShutdown</code> on it before it is deleted.</p><pre><code><span class="swift-keyword">extension</span> <span class="swift-type">HBApplication</span> {
    <span class="swift-keyword">var</span> httpClient: <span class="swift-type">HTTPClient</span> {
        <span class="swift-keyword">get</span> { <span class="swift-keyword">self</span>.<span class="swift-property">extensions</span>.<span class="swift-call">get</span>(\.<span class="swift-property">httpClient</span>) }
        <span class="swift-keyword">set</span> { <span class="swift-keyword">self</span>.<span class="swift-property">extensions</span>.<span class="swift-call">set</span>(\.<span class="swift-property">httpClient</span>, value: newValue) { httpClient <span class="swift-keyword">in
            try</span> httpClient.<span class="swift-call">syncShutdown</span>()
        }}
    }
}</code></pre><p>The closure at the end of the <code>set</code> function is called on <code>HBApplication</code> shutdown. This also means we have access to the <code>HTTPClient</code> whenever we have a reference to the <code>HBApplication</code> although we are not going to use this here.</p><h2 id="add_middleware">Add middleware</h2><p>We are going to implement our proxy server as middleware. The middleware will take a request, send it on to the target service and then respond with the response from the target service. Here is our initial version of the middleware. It will require the <code>HTTPClient</code> and the URL of the target service.</p><pre><code><span class="swift-keyword">struct</span> HBProxyServerMiddleware: <span class="swift-type">HBMiddleware</span> {
    <span class="swift-keyword">let</span> httpClient: <span class="swift-type">HTTPClient</span>
    <span class="swift-keyword">let</span> target: <span class="swift-type">String</span>

    <span class="swift-keyword">func</span> apply(to request: <span class="swift-type">HBRequest</span>, next: <span class="swift-type">HBResponder</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">HBResponse</span>&gt; {
        <span class="swift-keyword">return</span> httpClient.<span class="swift-call">execute</span>(
            request: request,
            eventLoop: .<span class="swift-call">delegateAndChannel</span>(on: request.<span class="swift-property">eventLoop</span>),
            logger: request.<span class="swift-property">logger</span>
        )
    }
}</code></pre><p>Now we have the <code>HTTPClient</code> and the <code>HBProxyServerMiddleware</code> middleware we add them to application in <code>HBApplication.configure</code>. Lets set the target of our proxy to be <code>http://httpbin.org</code>.</p><pre><code><span class="swift-keyword">func</span> configure(<span class="swift-keyword">_</span> args: <span class="swift-type">AppArguments</span>) <span class="swift-keyword">throws</span> {
    <span class="swift-keyword">self</span>.<span class="swift-property">httpClient</span> = <span class="swift-type">HTTPClient</span>(eventLoopGroupProvider: .<span class="swift-call">shared</span>(<span class="swift-keyword">self</span>.<span class="swift-property">eventLoopGroup</span>))
    <span class="swift-keyword">self</span>.<span class="swift-property">middleware</span>.<span class="swift-call">add</span>(<span class="swift-type">HBProxyServerMiddleware</span>(httpClient: <span class="swift-keyword">self</span>.<span class="swift-property">httpClient</span>, target: <span class="swift-string">"http://httpbin.org"</span>))
}</code></pre><h2 id="converting_types">Converting types</h2><p>When we build the above, it fails to compile. This is because we need to convert between <code>Hummingbird</code> and <code>AsyncHTTPClient</code> Request and Response types. Also we need to incorporate the target service URL into the request.</p><h3 id="request_conversion">Request conversion</h3><p>To convert from a <code>Hummingbird</code> <code>HBRequest</code> to a <code>AsyncHTTPClient</code> <code>HTTPClient.Request</code> we first need to collate the <code>HBRequest</code> body which may still be loading. This makes the conversion process asynchronous. So it needs to return an <code>EventLoopFuture</code> which will be fulfilled with the result of the conversion later on. Lets add a conversion function to <code>HBRequest</code></p><pre><code><span class="swift-keyword">extension</span> <span class="swift-type">HBRequest</span> {
    <span class="swift-keyword">func</span> ahcRequest(host: <span class="swift-type">String</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">HTTPClient</span>.<span class="swift-type">Request</span>&gt; {
        <span class="swift-comment">// consume request body and then construct AHC Request once we have the
        // result. The URL for the request is the target server plus the URI from
        // the `HBRequest`.</span>
        <span class="swift-keyword">return self</span>.<span class="swift-property">body</span>.<span class="swift-call">consumeBody</span>(on: <span class="swift-keyword">self</span>.<span class="swift-property">eventLoop</span>).<span class="swift-call">flatMapThrowing</span> { buffer <span class="swift-keyword">in
            return try</span> <span class="swift-type">HTTPClient</span>.<span class="swift-type">Request</span>(
                url: host + <span class="swift-keyword">self</span>.<span class="swift-property">uri</span>.<span class="swift-property">description</span>,
                method: <span class="swift-keyword">self</span>.<span class="swift-property">method</span>,
                headers: <span class="swift-keyword">self</span>.<span class="swift-property">headers</span>,
                body: buffer.<span class="swift-call">map</span> { .<span class="swift-call">byteBuffer</span>($0) }
            )
        }
    }
}</code></pre><h3 id="response_conversion">Response conversion</h3><p>The conversion from <code>HTTPClient.Response</code> to <code>HBResponse</code> is considerably simpler.</p><pre><code><span class="swift-keyword">extension</span> <span class="swift-type">HTTPClient</span>.<span class="swift-type">Response</span> {
    <span class="swift-keyword">var</span> hbResponse: <span class="swift-type">HBResponse</span> {
        <span class="swift-keyword">return</span> .<span class="swift-keyword">init</span>(
            status: <span class="swift-keyword">self</span>.<span class="swift-property">status</span>,
            headers: <span class="swift-keyword">self</span>.<span class="swift-property">headers</span>,
            body: <span class="swift-keyword">self</span>.<span class="swift-property">body</span>.<span class="swift-call">map</span> { <span class="swift-type">HBResponseBody</span>.<span class="swift-call">byteBuffer</span>($0) } ?? .<span class="swift-dotAccess">empty</span>
        )
    }
}</code></pre><p>We can now add these two conversion steps into the <code>apply</code> function of <code>HBProxyServerMiddleware</code>. While we are at it, lets also add some logging.</p><pre><code><span class="swift-keyword">func</span> apply(to request: <span class="swift-type">HBRequest</span>, next: <span class="swift-type">HBResponder</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">HBResponse</span>&gt; {
    <span class="swift-comment">// log request</span>
    request.<span class="swift-property">logger</span>.<span class="swift-call">info</span>(<span class="swift-string">"Forwarding</span> \(request.<span class="swift-property">uri</span>.<span class="swift-property">path</span>)<span class="swift-string">"</span>)
    <span class="swift-comment">// convert to HTTPClient.Request, execute, convert to HBResponse</span>
    <span class="swift-keyword">return</span> request.<span class="swift-call">ahcRequest</span>(host: target).<span class="swift-call">flatMap</span> { ahcRequest <span class="swift-keyword">in</span>
        httpClient.<span class="swift-call">execute</span>(
            request: ahcRequest,
            eventLoop: .<span class="swift-call">delegateAndChannel</span>(on: request.<span class="swift-property">eventLoop</span>),
            logger: request.<span class="swift-property">logger</span>
        )
    }.<span class="swift-call">map</span> { response <span class="swift-keyword">in
        return</span> response.<span class="swift-property">hbResponse</span>
    }
}</code></pre><p>Now everything should compile. The middleware will collate the <code>HBRequest</code> body, convert it to a <code>HTTPClient.Request</code>, send this request to the target service using <code>HTTPClient</code> and then convert the response to a <code>HBResponse</code> which is then returned back to the application.</p><p>Run the application, open a web browser and type in <code>localhost:8080</code>. We should see the <code>httpbin.org</code> web site which we set as the proxy target earlier on.</p><h2 id="streaming">Streaming</h2><p>The setup above is not very optimal. It waits until a request is fully loaded before forwarding it on to its target service and similarly in the other direction it waits until the response has loaded before sending that back to the client. This slows down the forwarding process and also can use a lot of memory if request or response payloads are large.</p><p>We can improve this by streaming request and response payloads. Start sending the request to the target service as soon as we have its head and stream the body parts as they are received. Similarly in the other direction start sending the response back once we have its head. Removing that wait for a full request or response will improve the performance of the proxy server.</p><p>We can still have memory issues though if communication between the client and the proxy and communication between the proxy and target service run at different speeds. Data will start to back up if we are receiving it faster than we are processing it. To avoid this happening we need to be able to apply back pressure to stop reading in additional data until we have processed enough of the data that is in memory. With this we can keep the amount of memory used by the proxy to a minimum.</p><h3 id="streaming_requests">Streaming requests</h3><p>Streaming the request payload is a fairly easy process. In actual fact it simplifies the construction of the <code>HTTPClient.Request</code> as we don't need to wait for the request to be fully loaded. How we construct the <code>HTTPClient.Request</code> body though will be based on whether the full <code>HBRequest</code> is already in memory. If we return a streaming request, back pressure is automatically applied as the Hummingbird server framework does this for us.</p><pre><code><span class="swift-keyword">func</span> ahcRequest(host: <span class="swift-type">String</span>, eventLoop: <span class="swift-type">EventLoop</span>) <span class="swift-keyword">throws</span> -&gt; <span class="swift-type">HTTPClient</span>.<span class="swift-type">Request</span> {
    <span class="swift-keyword">let</span> body: <span class="swift-type">HTTPClient</span>.<span class="swift-type">Body</span>?

    <span class="swift-keyword">switch self</span>.<span class="swift-property">body</span> {
    <span class="swift-keyword">case</span> .<span class="swift-dotAccess">byteBuffer</span>(<span class="swift-keyword">let</span> buffer):
        body = buffer.<span class="swift-call">map</span> { .<span class="swift-call">byteBuffer</span>($0) }
    <span class="swift-keyword">case</span> .<span class="swift-dotAccess">stream</span>(<span class="swift-keyword">let</span> stream):
        body = .<span class="swift-call">stream</span> { writer <span class="swift-keyword">in</span>
            <span class="swift-comment">// as we consume buffers from `HBRequest` we write them to
            // the `HTTPClient.Request`.</span>
            <span class="swift-keyword">return</span> stream.<span class="swift-call">consumeAll</span>(on: eventLoop) { byteBuffer <span class="swift-keyword">in</span>
                writer.<span class="swift-call">write</span>(.<span class="swift-call">byteBuffer</span>(byteBuffer))
            }
        }
    }
    <span class="swift-keyword">return try</span> <span class="swift-type">HTTPClient</span>.<span class="swift-type">Request</span>(
        url: host + <span class="swift-keyword">self</span>.<span class="swift-property">uri</span>.<span class="swift-property">description</span>,
        method: <span class="swift-keyword">self</span>.<span class="swift-property">method</span>,
        headers: <span class="swift-keyword">self</span>.<span class="swift-property">headers</span>,
        body: body
    )
}</code></pre><h3 id="streaming_responses">Streaming responses</h3><p>Streaming responses requires a class conforming to <code>HTTPClientResponseDelegate</code>. This will receive data from the <code>HTTPClient</code> response as soon as it is available. The response body is received as a series of <code>ByteBuffers</code>. We can feed these <code>ByteBuffers</code> to a <code>HBByteBufferStreamer</code>. The <code>HBResponse</code> we return is constructed with this streamer instead of a static <code>ByteBuffer</code>.</p><p>If we combine the request streaming with the response streaming code our final <code>apply</code> function should look like this</p><pre><code><span class="swift-keyword">func</span> apply(to request: <span class="swift-type">HBRequest</span>, next: <span class="swift-type">HBResponder</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">HBResponse</span>&gt; {
    <span class="swift-keyword">do</span> {
        request.<span class="swift-property">logger</span>.<span class="swift-call">info</span>(<span class="swift-string">"Forwarding</span> \(request.<span class="swift-property">uri</span>.<span class="swift-property">path</span>)<span class="swift-string">"</span>)
        <span class="swift-comment">// create request</span>
        <span class="swift-keyword">let</span> ahcRequest = <span class="swift-keyword">try</span> request.<span class="swift-call">ahcRequest</span>(host: target, eventLoop: request.<span class="swift-property">eventLoop</span>)
        <span class="swift-comment">// create response body streamer. maxSize is the maximum size of object it can process
        // maxStreamingBufferSize is the maximum size of data the streamer is allowed to have
        // in memory at any one time</span>
        <span class="swift-keyword">let</span> streamer = <span class="swift-type">HBByteBufferStreamer</span>(eventLoop: request.<span class="swift-property">eventLoop</span>, maxSize: <span class="swift-number">2048</span>*<span class="swift-number">1024</span>, maxStreamingBufferSize: <span class="swift-number">128</span>*<span class="swift-number">1024</span>)
        <span class="swift-comment">// HTTPClientResponseDelegate for streaming bytebuffers from AsyncHTTPClient</span>
        <span class="swift-keyword">let</span> delegate = <span class="swift-type">StreamingResponseDelegate</span>(on: request.<span class="swift-property">eventLoop</span>, streamer: streamer)
        <span class="swift-comment">// execute request</span>
        <span class="swift-keyword">_</span> = httpClient.<span class="swift-call">execute</span>(
            request: ahcRequest,
            delegate: delegate,
            eventLoop: .<span class="swift-call">delegateAndChannel</span>(on: request.<span class="swift-property">eventLoop</span>),
            logger: request.<span class="swift-property">logger</span>
        )
        <span class="swift-comment">// when delegate receives head then signal completion</span>
        <span class="swift-keyword">return</span> delegate.<span class="swift-property">responsePromise</span>.<span class="swift-property">futureResult</span>
    } <span class="swift-keyword">catch</span> {
        <span class="swift-keyword">return</span> request.<span class="swift-call">failure</span>(error)
    }
}</code></pre><p>You'll notice in the code above we don't wait on the result of <code>httpClient.execute</code>. This is because if we did, the function would wait for the whole response body to be in memory before continuing. We want to be processing the response straight away so instead we add a promise to the delegate that is fulfilled with a <code>HBResponse</code> holding the head details and the streamer as soon as we receive the head. The <code>EventLoopFuture</code> of this promise is what we pass back from the <code>apply</code> function.</p><p>I haven't included the code for <code>StreamingResponseDelegate</code> here as it is not small, but you can find it in the full <a href="https://github.com/hummingbird-project/hummingbird-examples/blob/main/proxy-server/Sources/App/Middleware/StreamingResponseDelegate.swift">sample code</a>.</p><h2 id="sample_code_additions">Sample code additions</h2><p>The <a href="https://github.com/hummingbird-project/hummingbird-examples/tree/main/proxy-server">sample code</a> has a few changes to what is detailed above.</p><ol><li>The default bind address port is 8081 instead of 8080. Most Hummingbird examples run on 8080 so to use the proxy alongside those examples it needs to bind to a different port.</li><li>I added a location option which allows us to forward only requests from a particular base URL</li><li>I added command line options for both target and location so these can be changed without rebuilding the application</li><li>I remove the <code>host</code> header or request so it can be filled out with the correct value</li><li>When converting a streaming request if the <code>content-length</code> header was provided I pass that along to the <code>HTTPClient</code> streamer to ensure the <code>content-length</code> header is set correctly for the request to the target server.</li></ol><h2 id="alternatives">Alternatives</h2><p>Instead of using Hummingbird for the Proxy server we could use HummingbirdCore instead. This would provide a bit of extra performance as it would remove extra layers of code but at the expense of flexibility. Adding any extra routing or middleware would require a lot more work. I have example code for a proxy server using only HummingbirdCore <a href="https://github.com/hummingbird-project/hummingbird-examples/tree/main/proxy-server-core">here</a>.</p><p>Of course the other alternative would be to use Vapor. I would imagine an implementation in Vapor would look very similar to what is described above and shouldn't be too hard. I'll leave that to someone else though.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/12/hummingbird-template.html</guid><link>https://opticalaberration.com/2021/12/hummingbird-template.html</link><title>A template for building Hummingbird applications</title><description>The Hummingbird server framework is designed to be flexible. It imposes as little structure as possible on how you build your application, but sometimes you need some structure. Do you really want to build all your application setup boilerplate every time you create a new app? To avoid this I have written a hummingbird project template which can be your starting point for your next app.GitHub has a feature called template repositories. These allow you to create a new project repository setup for a…</description><pubDate>Wed, 1 Dec 2021 11:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="a_template_for_building_hummingbird_applications">A template for building Hummingbird applications</h1><p>The Hummingbird server framework is designed to be flexible. It imposes as little structure as possible on how you build your application, but sometimes you need some structure. Do you really want to build all your application setup boilerplate every time you create a new app? To avoid this I have written a hummingbird project template which can be your starting point for your next app.</p><h2 id="template_repository">Template repository</h2><p>GitHub has a feature called template repositories. These allow you to create a new project repository setup for a particular type of project. I have created a Hummingbird template <a href="https://github.com/hummingbird-project/template">here</a>.</p><p>To create your Hummingbird project you go to the <a href="https://github.com/hummingbird-project/template">template project</a> in GitHub and press the <code>Use this template</code> button. You now have the basis for building your next great server application.</p><div class="centre"><img src="/images/use-this-template.png" alt="Use this template button"/></div><h2 id="details">Details</h2><p>Here I will go into a bit of detail of what is involved in the template.</p><h3 id="package_swift">Package.Swift</h3><p>The project is setup with the Swift Package Manager. The <code>Package.swift</code> file defines all the project dependencies and targets.</p><pre><code><span class="swift-comment">// swift-tools-version:5.5</span>
<span class="swift-keyword">import</span> PackageDescription

<span class="swift-keyword">let</span> package = <span class="swift-type">Package</span>(
    name: <span class="swift-string">"hummingbird-template"</span>,
    products: [
        .<span class="swift-call">executable</span>(name: <span class="swift-string">"App"</span>, targets: [<span class="swift-string">"App"</span>]),
    ],
    dependencies: [
        .<span class="swift-call">package</span>(url: <span class="swift-string">"https://github.com/hummingbird-project/hummingbird.git"</span>, from: <span class="swift-string">"0.15.0"</span>),
        .<span class="swift-call">package</span>(url: <span class="swift-string">"https://github.com/apple/swift-argument-parser.git"</span>, from: <span class="swift-string">"1.0.0"</span>)
    ],
    targets: [
        .<span class="swift-call">executableTarget</span>(name: <span class="swift-string">"App"</span>,
            dependencies: [
                .<span class="swift-call">product</span>(name: <span class="swift-string">"ArgumentParser"</span>, package: <span class="swift-string">"swift-argument-parser"</span>),
                .<span class="swift-call">product</span>(name: <span class="swift-string">"Hummingbird"</span>, package: <span class="swift-string">"hummingbird"</span>),
            ],
            swiftSettings: [
                <span class="swift-comment">// Enable better optimizations when building in Release configuration. Despite the use of
                // the `.unsafeFlags` construct required by SwiftPM, this flag is recommended for Release
                // builds. See &lt;https://github.com/swift-server/guides#building-for-production&gt; for details.</span>
                .<span class="swift-call">unsafeFlags</span>([<span class="swift-string">"-cross-module-optimization"</span>], .<span class="swift-dotAccess">when</span>(configuration: .<span class="swift-dotAccess">release</span>))
            ]
        ),
        .<span class="swift-call">testTarget</span>(name: <span class="swift-string">"AppTests"</span>,
            dependencies: [
                .<span class="swift-call">byName</span>(name: <span class="swift-string">"App"</span>),
                .<span class="swift-call">product</span>(name: <span class="swift-string">"HummingbirdXCT"</span>, package: <span class="swift-string">"hummingbird"</span>)
            ]
        )
    ]
)</code></pre><p>In this file you can see we have</p><ol><li>The project name, currently <code>hummingbird-template</code></li><li>The name of the executable, <code>App</code> and the targets it requires</li><li>The packages we are dependent on ie <code>hummingbird</code> and also Apple's <code>swift-argument-parser</code> to ease reading of command line arguments.</li><li>Two targets, the application <code>App</code> and the test project <code>AppTests</code>.</li></ol><h3 id="source_code">Source code</h3><p>The <code>App</code> source code consists of two files.</p><ol><li><code>App.swift</code> this is the entrypoint for your application. It defines the commandline arguments and starts and stops your application. If you need to add more commandline arguments to your application do it here.</li><li><code>Application+configure.swift</code> which is where you configure your application, add routes, add middleware and any other general <code>HBApplication</code> setup. There is one default route added <code>GET /health</code> which return <code>.ok</code>.</li></ol><p>The <code>AppTests</code> source code consists of one set of tests <code>AppTests.swift</code>. It has one example test in there using the <code>HummingbirdXCT</code> framework to test the <code>GET health</code> route setup in your <code>App</code>.</p><h3 id="other_files">Other files</h3><p>The project template also includes the following files.</p><ol><li><code>Dockerfile</code> for building and running docker images of your project</li><li><code>.dockerignore</code> file containing folders you don't need to sync when building your docker images</li><li><code>.gitignore</code> with a list of standard files to not include in your project</li><li><code>README.md</code> for you to tell everyone about your great project</li></ol><p>This is all the boilerplate you should need to start your application. How you structure the rest of it is up to you. Now, let's get creating!</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/09/hummingbird-swift-concurrency.html</guid><link>https://opticalaberration.com/2021/09/hummingbird-swift-concurrency.html</link><title>Hummingbird and Swift concurrency</title><description>Swift 5.5 has been released. This new release includes a series of new concurrency features including, async/await, structured concurrency and actors. Probably one of the most exciting series of additions to Swift in a long time (and this is from a language with new features appearing, what seems like, every other week).The recently released version of Hummingbird (&lt;a href="https://github.com/hummingbird-project/hummingbird/releases/tag/0.13.0"&gt;v0.13.0&lt;/a&gt;) includes new APIs that allow you to take…</description><pubDate>Tue, 21 Sep 2021 15:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="hummingbird_and_swift_concurrency">Hummingbird and Swift concurrency</h1><p>Swift 5.5 has been released. This new release includes a series of new concurrency features including, async/await, structured concurrency and actors. Probably one of the most exciting series of additions to Swift in a long time (and this is from a language with new features appearing, what seems like, every other week).</p><p>The recently released version of Hummingbird (<a href="https://github.com/hummingbird-project/hummingbird/releases/tag/0.13.0">v0.13.0</a>) includes new APIs that allow you to take advantage of some of these new concurrency features. You can add async route handlers functions, add middleware using async functions and various systems have been augmented with new async apis.</p><h2 id="async_route_handlers">Async route handlers</h2><p>Where previously an asynchronous route handler function would return an <code>EventLoopFuture</code> it is now possible instead to use an async handler function. Adding an async handler is as easy as adding any other handler.</p><pre><code>app.<span class="swift-property">router</span>.<span class="swift-call">get</span>(<span class="swift-string">"test-async"</span>) { request -&gt; <span class="swift-type">String</span> <span class="swift-keyword">in</span>
    <span class="swift-comment">// the await means this is an async function</span>
    <span class="swift-keyword">let</span> result = <span class="swift-keyword">await</span> <span class="swift-call">asyncOperation</span>()
    <span class="swift-keyword">return</span> result.<span class="swift-property">description</span>
}</code></pre><h2 id="async_middleware">Async middleware</h2><p>There is a new protocol <code>HBAsyncMiddleware</code>. This requires an async <code>apply</code> method be implemented instead of the standard <code>HBMiddleware</code> which requires a method returning an <code>EventLoopFuture</code>. Below is an example session middleware using <code>HBAsyncMiddleware</code>, HummingbirdAuth framework and persist system for storing persistent data between requests. A session cookie is extracted from the request, this is then used to get the authenticatable type <code>Session</code> from the persist system which is then attached to the request using <code>authLogin</code>.</p><pre><code><span class="swift-keyword">struct</span> AsyncSessionMiddleware: <span class="swift-type">HBAsyncMiddleware</span> {
    <span class="swift-keyword">public func</span> apply(to request: <span class="swift-type">HBRequest</span>, next: <span class="swift-type">HBResponder</span>) <span class="swift-keyword">async throws</span> -&gt; <span class="swift-type">HBResponse</span> {
        <span class="swift-keyword">var</span> request = request
        <span class="swift-keyword">if let</span> sessionCookie = request.<span class="swift-property">cookies</span>[<span class="swift-string">"_SESSION_ID"</span>] {
            <span class="swift-comment">// persist system has an async/await api</span>
            <span class="swift-keyword">let</span> session = <span class="swift-keyword">try await</span> request.<span class="swift-property">persist</span>.<span class="swift-call">get</span>(key: sessionCookie.<span class="swift-property">value</span>, as: <span class="swift-type">Session</span>.<span class="swift-keyword">self</span>)
            <span class="swift-keyword">if let</span> session = session {
                request.<span class="swift-call">authLogin</span>(session)
            }
        }
        <span class="swift-keyword">return try await</span> next.<span class="swift-call">respond</span>(to: request)
    }
}</code></pre><p>Normally when using the HummingbirdAuth package for building authentication middleware you would use an <code>HBAuthenticator</code>. The HummingbirdAuth package also includes the <code>HBAsyncAuthenticator</code> protocol to implement authenticators with async/await.</p><h2 id="streaming_request_body">Streaming request body</h2><p>Streamed request bodies can now be access via an <code>AsyncSequence</code> of <code>ByteBuffers</code>. You can get access to this via <code>HBRequest.body.stream?.sequence</code>. There has also been a change to the flag to indicate you want a streamed request. The <code>body</code> parameter has been changed into an <code>options</code> parameter that can include other route options. The example below uses the new <code>AsyncSequence</code> to return the size of the buffer supplied.</p><pre><code>app.<span class="swift-property">router</span>.<span class="swift-call">post</span>(<span class="swift-string">"stream"</span>, options: .<span class="swift-dotAccess">streamBody</span>) { request -&gt; <span class="swift-type">String</span> <span class="swift-keyword">in
    guard let</span> stream = request.<span class="swift-property">body</span>.<span class="swift-property">stream</span> <span class="swift-keyword">else</span> { <span class="swift-keyword">throw</span> <span class="swift-type">HBHTTPError</span>(.<span class="swift-dotAccess">badRequest</span>) }
    <span class="swift-keyword">var</span> size = <span class="swift-number">0</span>
    <span class="swift-comment">// for buffers in AsyncSequence</span>
    <span class="swift-keyword">for try await</span> buffer <span class="swift-keyword">in</span> stream.<span class="swift-property">sequence</span> {
        size += buffer.<span class="swift-property">readableBytes</span>
    }
    <span class="swift-keyword">return</span> size.<span class="swift-property">description</span>
}</code></pre><h2 id="request_and_response_struct">Request and Response struct</h2><p>The new release of Hummingbird includes a couple of version breaking changes. Unfortunate as this is I believe they are necessary to ensure Hummingbird is used in a thread/task safe manner.</p><p>Previously both <code>HBRequest</code> and <code>HBResponse</code> were classes. These have now been changed to structs. Making them value types instead of reference types removes a whole class of race conditions that could occur. These changes don’t come without some cost though. You can only modify a struct from mutating methods that are members of that struct. This affected HummingbirdAuth which used an internal type <code>Auth</code> to mutate the <code>HBRequest</code>. This is no longer possible so the internal type has been removed and calls like <code>HBRequest.auth.login</code> have been replaced with <code>HBRequest.authLogin</code>.</p><h2 id="performance">Performance</h2><p>The performance of the new concurrency features are not in line with what the SwiftNIO is capable of. At the moment there is no way to ensure what <code>EventLoop</code> you are running on and tasks can move about threads. This has a performance impact. This hopefully will be resolved over time though as custom executors are implemented, allowing SwiftNIO to implement an EventLoop model within Swift concurrency. Nothing is guaranteed though.</p><p>At the same time it is a lot easier writing async/await code than getting lost in chaining various <code>EventLoopFuture.flatMaps</code> together. The loss in code performance has to be measured against the gain in development performance. Many people won't need the code performance and should probably move across to async/await now, but there will be systems that still need the performance of SwiftNIO and should stick with the <code>EventLoopFuture</code> routes for the moment.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/06/jmespath.html</guid><link>https://opticalaberration.com/2021/06/jmespath.html</link><title>JMESPath</title><description>JMESPath is a query language for JSON. WIth it you can script searching large JSON datasets and transform the results.A search can be as simple as a single field name. &lt;code&gt;result&lt;/code&gt; would return the object attached to the &lt;code&gt;result&lt;/code&gt; field at the top level of a JSON file. This can be specialized to return an object inside &lt;code&gt;result&lt;/code&gt; by added a dot and then another field name eg &lt;code&gt;result.object&lt;/code&gt;.Queries can index arrays as followsWhich will return the &lt;code&gt;name&lt;/code&gt; field…</description><pubDate>Thu, 3 Jun 2021 12:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="jmespath">JMESPath</h1><h2 id="what_is_it">What is it?</h2><p>JMESPath is a query language for JSON. WIth it you can script searching large JSON datasets and transform the results.</p><h3 id="basic_queries">Basic queries</h3><p>A search can be as simple as a single field name. <code>result</code> would return the object attached to the <code>result</code> field at the top level of a JSON file. This can be specialized to return an object inside <code>result</code> by added a dot and then another field name eg <code>result.object</code>.</p><p>Queries can index arrays as follows</p><pre><code>users[0].name
</code></pre><p>Which will return the <code>name</code> field of the first element of the array <code>users</code>. You can use a negative index to access an array from the end, so the index of <code>-1</code> will give you the last element of an array.</p><h3 id="projection_queries">Projection queries</h3><p>Projections allow you to apply a query to multiple objects. The left hand side of a projection query defines the projection and the right hand side defines the query to apply to each object returned by the projection. Using the example from above by replacing the array index with a <code>*</code> we create a list projection <code>users[*]</code> which we then apply the query <code>name</code> to. The following returns the <code>name</code> field from every element in the <code>users</code> array.</p><pre><code>users[*].name
</code></pre><p>There are five different types of projection:</p><ul><li>list: applies query to each object in array as demonstrated above.</li><li>slice: applies query to each object in a slice from an array</li><li>flatten: applies query to each object in an array and flattens the result into a parent array</li><li>object: applies query to all the child objects</li><li>filter: applies query to a filtered version of the object</li></ul><p>As this article isn't meant to cover the full spec of JMESPath but just give you a feel for what can be done with it I'll only cover filter projections here. A filter projection allows you to filter the left hand side of the projection before the query on the right hand side is applied to it. For example the following will return all the entries in the users array that have the field <code>country</code> set to <code>USA</code>.</p><pre><code>users[?country=="USA"]
</code></pre><h3 id="functions">Functions</h3><p>JMESPath has a number of standard functions that can be applied to results within a query. Using the same users example we have been using throughout we can sort the results by placing it inside the <code>sort</code> function.</p><pre><code>sort(users[*].name)
</code></pre><p>You can also use functions inside filter projections. The following would return all the users whose names start with <code>A</code>.</p><pre><code>users[?starts_with(name, "A")]
</code></pre><h3 id="transforming_the_results">Transforming the results</h3><p>If you want the results of your query in a specific format you can use multi-select queries. These can be used to create arrays or objects from your results. If I'm only interested in the <code>name</code> and <code>age</code> fields of the entries in my <code>users</code> array I can transform the list query results using a multi-select hash</p><pre><code>users[*].{"name": name, "age": age}
</code></pre><h2 id="why_am_i_telling_you_this">Why am I telling you this</h2><p>Well, AWS uses JMESPath in their SDK generation. If you have used their CLI tool you might recognise the syntax from the <code>--query</code> option. So far in my work on Soto (a third party Swift SDK for AWS) I have been able to hardcode the queries I came across and write custom code for them. Through recent work though, I have found a number of queries that were too complex. So I took the leap and decided to implement JMESPath for Swift. You can find the code <a href="https://github.com/adam-fowler/jmespath.swift">here</a>. Given there are versions of JMESPath for a number of languages already I had a lot of prior art to help in my implementation. The Swift version is based off the Rust version and follows its implementation fairly closely. The JMESPath site provides a comprehensive set of compliance tests and my version passes them all so I am fairly confident it is up to scratch.</p><p>The Swift code works as follows. You create a compiled <code>Expression</code> and then use <code>Expression.search</code> to apply the expression to your JSON.</p><pre><code><span class="swift-keyword">let</span> expression = <span class="swift-keyword">try</span> <span class="swift-type">JMESExpression</span>.<span class="swift-call">compile</span>(<span class="swift-string">"users[*].name"</span>)
<span class="swift-keyword">let</span> result = <span class="swift-keyword">try</span> expression.<span class="swift-call">search</span>(json: myjson)</code></pre><p>The above will return <code>Any</code> as it is undefined what type the expression will return. You can pass this straight into <code>JSONSerialization.data</code> to get the result as JSON if desired. Or if you know the type that the search will return you can add it into the <code>search</code> call as follows</p><pre><code><span class="swift-keyword">let</span> result = <span class="swift-keyword">try</span> expression.<span class="swift-call">search</span>(json: myjson, as: [<span class="swift-type">String</span>].<span class="swift-keyword">self</span>)</code></pre><p>In addition to parsing JSON I've added <code>Mirror</code> reflection to search objects of any type. This means the Swift implementation of JMESPath isn't restricted to just querying JSON data it can be used to query any data structure. Below is a sample where we have a struct <code>Service</code> which includes an array of <code>User</code>. We use JMESPath to create a sorted list of all the <code>User</code> member <code>name</code>.</p><pre><code><span class="swift-keyword">struct</span> Service {
    <span class="swift-keyword">struct</span> User {
        <span class="swift-keyword">let</span> name: <span class="swift-type">String</span>
    }
    <span class="swift-keyword">let</span> users: [<span class="swift-type">User</span>]
}
<span class="swift-keyword">let</span> service = <span class="swift-type">Service</span>(
    users: [
        .<span class="swift-keyword">init</span>(name: <span class="swift-string">"james"</span>),
        .<span class="swift-keyword">init</span>(name: <span class="swift-string">"anne"</span>),
        .<span class="swift-keyword">init</span>(name: <span class="swift-string">"tom"</span>)
    ]
)
<span class="swift-keyword">let</span> expression = <span class="swift-keyword">try</span> <span class="swift-type">JMESExpression</span>.<span class="swift-call">compile</span>(<span class="swift-string">"users[*].name | sort(@)"</span>)
<span class="swift-keyword">let</span> result = <span class="swift-keyword">try</span> expression.<span class="swift-call">search</span>(object: service, as: [<span class="swift-type">String</span>.<span class="swift-keyword">self</span>])
<span class="swift-call">assert</span>(result == [<span class="swift-string">"anne"</span>, <span class="swift-string">"james"</span>, <span class="swift-string">"tom"</span>])</code></pre><p>The expression used here includes two new pieces of grammar <code>|</code> which pipes the result of the expression on the left hand side into the expression on the right hand side and <code>@</code> which indicates the current result being evaluated. So above the array of names returned by <code>users[*].name</code> is passed into the <code>sort</code> function.</p><h2 id="usage">Usage</h2><p>JMESPath provides an easy way to script filtering and transforming of JSON responses from different services. It can be used to parse responses from cloud providers and other services from your backend into the formats that your client expects.</p><h2 id="more_information">More Information</h2><p>This article only details a small sample of the possibilities with JMESPath. If you'd like to find out more about JMESPath you can go the website <a href="https://jmespath.org/">jmespath.org</a>. It has a great tutorial section where you can test out different queries.</p><p>You can checkout the Swift version of JMESPath here <a href="https://github.com/adam-fowler/jmespath.swift">https://github.com/adam-fowler/jmespath.swift</a>.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/04/hummingbird-update.html</guid><link>https://opticalaberration.com/2021/04/hummingbird-update.html</link><title>Hummingbird Update</title><description>Almost 8 weeks back I published a post announcing the release of my Swift based http application framework &lt;a href="https://github.com/hummingbird-project/hummingbird"&gt;hummingbird&lt;/a&gt;. This post is to update everyone on all the new stuff that has been added since that first post.The web application layer has had a number of changes. Much of these have been API changes as I continue to refine the interfaces. I apologize to anymore who might have been using the framework and having to fix up their code on…</description><pubDate>Fri, 9 Apr 2021 11:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="hummingbird_update">Hummingbird Update</h1><p>Almost 8 weeks back I published a post announcing the release of my Swift based http application framework <a href="https://github.com/hummingbird-project/hummingbird">hummingbird</a>. This post is to update everyone on all the new stuff that has been added since that first post.</p><h2 id="web_application_layer__hummingbird">Web Application Layer (Hummingbird)</h2><p>The web application layer has had a number of changes. Much of these have been API changes as I continue to refine the interfaces. I apologize to anymore who might have been using the framework and having to fix up their code on new releases. I promise the APIs will stabilise in the near future. Although async/await will probably cause some considerable changes.</p><p>The library has had a number of optimisations to improve performance. It is now according to <a href="https://github.com/the-benchmarker/web-frameworks#usage">The Benchmarker</a> the fastest Swift server framework out there, if you want a 200 response with an empty body. I know these numbers don't necessarily mean much but its still nice to be in that position. TechEmpower report similar results from their Live results.</p><p>One minor addition, although I think it is worth noting, is a new protocol for defining a route. A route handler <code>HBRouteHandler</code> allows you to encapsulate all the components required for a route, and provide separation of the extraction of input parameters from the request and the processing of those parameters. For example</p><pre><code><span class="swift-keyword">struct</span> AddOrder: <span class="swift-type">HBRouteHandler</span> {
    <span class="swift-keyword">struct</span> Input: <span class="swift-type">Decodable</span> {
        <span class="swift-keyword">let</span> name: <span class="swift-type">String</span>
        <span class="swift-keyword">let</span> amount: <span class="swift-type">Double</span>
    }
    <span class="swift-keyword">struct</span> Output: <span class="swift-type">HBResponseEncodable</span> {
        <span class="swift-keyword">let</span> id: <span class="swift-type">String</span>
    }
    <span class="swift-keyword">let</span> input: <span class="swift-type">Input</span>
    <span class="swift-keyword">let</span> user: <span class="swift-type">User</span>

    <span class="swift-keyword">init</span>(from request: <span class="swift-type">HBRequest</span>) <span class="swift-keyword">throws</span> {
        <span class="swift-keyword">self</span>.<span class="swift-property">input</span> = <span class="swift-keyword">try</span> request.<span class="swift-call">decode</span>(as: <span class="swift-type">Input</span>.<span class="swift-keyword">self</span>)
        <span class="swift-keyword">self</span>.<span class="swift-property">user</span> = <span class="swift-keyword">try</span> request.<span class="swift-property">auth</span>.<span class="swift-call">require</span>(<span class="swift-type">User</span>.<span class="swift-keyword">self</span>)
    }
    <span class="swift-keyword">func</span> handle(request: <span class="swift-type">HBRequest</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">Output</span>&gt; {
        <span class="swift-keyword">let</span> order = <span class="swift-type">Order</span>(user: <span class="swift-keyword">self</span>.<span class="swift-property">user</span>.<span class="swift-property">id</span>, details: <span class="swift-keyword">self</span>.<span class="swift-property">input</span>)
        <span class="swift-keyword">return</span> order.<span class="swift-call">save</span>(on: request.<span class="swift-property">db</span>)
            .<span class="swift-call">map</span> { .<span class="swift-keyword">init</span>(id: order.<span class="swift-property">id</span>) }
    }
}
application.<span class="swift-property">router</span>.<span class="swift-call">put</span>(<span class="swift-string">"order"</span>, use: <span class="swift-type">AddOrder</span>.<span class="swift-keyword">self</span>)</code></pre><p><code>HBRouteHandler</code> doesn't provide a great deal of extra functionality, but it does provide a place to centralize all the components that make up a route.</p><h2 id="websockets">WebSockets</h2><p>Just after the initial release of Hummingbird I released a <a href="https://github.com/hummingbird-project/hummingbird-websocket">websocket library</a>. The first release included a websocket server accessed via <code>HBApplication.ws</code>. Here is a basic example of a websocket server that returns everything that is sent to it</p><pre><code><span class="swift-keyword">let</span> app = <span class="swift-type">HBApplication</span>()
<span class="swift-comment">// add HTTP to WebSocket upgrade</span>
app.<span class="swift-property">ws</span>.<span class="swift-call">addUpgrade</span>()
<span class="swift-comment">// on websocket connect.</span> 
app.<span class="swift-property">ws</span>.<span class="swift-call">on</span>(<span class="swift-string">"/ws"</span>) { req, ws <span class="swift-keyword">in</span>
    <span class="swift-comment">// send ping and wait for pong and repeat every 60 seconds</span>
    ws.<span class="swift-call">initiateAutoPing</span>(interval: .<span class="swift-call">seconds</span>(<span class="swift-number">60</span>))
    <span class="swift-comment">// on read from client send the same data back</span>
    ws.<span class="swift-call">onRead</span> { data, ws <span class="swift-keyword">in</span>
        ws.<span class="swift-call">write</span>(data)
    }
}
app.<span class="swift-call">start</span>()
app.<span class="swift-call">wait</span>()</code></pre><p>Given the code for a websocket client and server is almost identical setting up a client didn't take too much effort either and was included in a later release. I included a simple chat server example using websockets in the examples repository <a href="https://github.com/hummingbird-project/hummingbird-examples/tree/main/websocket-chat">hummingbird-examples</a>.</p><h2 id="mustache_templating_engine">Mustache templating engine</h2><p><a href="http://mustache.github.io/mustache.5.html">Mustache</a> is a "logicless" templating engine that can be used to create dynamic HTML. I have provided a Swift implementation of the engine <a href="https://github.com/hummingbird-project/hummingbird-mustache">HummingbirdMustache</a> as a separate standalone project. It is a full implementatin of the mustache <a href="https://github.com/mustache/spec">spec</a> along with some additional bells and whistles. It supports all the standard tags along with transforms for transforming objects before being rendered, sequence context objects for rendered content based on position within a sequence, template inheritance for overriding sections of a partial and pragmas for setting implementation specific configuration parameters.</p><h2 id="future">Future</h2><p>I guess the next big change is async/await. The initial release of swift including async/await will probably not have the support that Swift NIO needs to create an optimal HTTP server pipeline. So any initial release of Hummingbird with async/await will only include additive elements and will keep the Swift NIO <code>EventLoopFuture</code> interfaces. Async/await style routes and middleware will be available but I can't guarantee how performant they will be.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/02/going-serverless-with-hummingbird.html</guid><link>https://opticalaberration.com/2021/02/going-serverless-with-hummingbird.html</link><title>Going Serverless with Hummingbird</title><description>Along with Hummingbird, my web application framework, comes &lt;a href="https://github.com/hummingbird-project/hummingbird"&gt;HummingbirdLambda&lt;/a&gt;. This allows you to take your Hummingbird application and run it on an AWS Lambda with API Gateway as an interface.As long as all the services your application uses are accessible from AWS Lambda and your application doesn't have any internal persistent state moving to Lambda should be fairly easy. You should be able to move your application setup, middleware,…</description><pubDate>Sun, 28 Feb 2021 15:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="going_serverless_with_hummingbird">Going Serverless with Hummingbird</h1><p>Along with Hummingbird, my web application framework, comes <a href="https://github.com/hummingbird-project/hummingbird">HummingbirdLambda</a>. This allows you to take your Hummingbird application and run it on an AWS Lambda with API Gateway as an interface.</p><p>As long as all the services your application uses are accessible from AWS Lambda and your application doesn't have any internal persistent state moving to Lambda should be fairly easy. You should be able to move your application setup, middleware, routes to your Lambda with very little change.</p><p>In a standard server based Hummingbird application you create your <code>HBApplication</code>, set it up and then call <code>HBApplication.start</code>. Instead in a Hummingbird Lambda you create an <code>HBLambda</code> object which is initialized with an already created <code>HBApplication</code> which you then setup. Do NOT call <code>HBApplication.start</code> on this though.</p><p>Where you were doing the following for your server app.</p><pre><code><span class="swift-keyword">let</span> app = <span class="swift-type">HBApplication</span>()
<span class="swift-comment">// set encoder and decoder</span>
app.<span class="swift-property">encoder</span> = <span class="swift-type">JSONEncoder</span>()
app.<span class="swift-property">decoder</span> = <span class="swift-type">JSONDecoder</span>()
<span class="swift-comment">// middleware</span>
app.<span class="swift-property">middleware</span>.<span class="swift-call">add</span>(<span class="swift-type">HBLogRequestsMiddleware</span>(.<span class="swift-dotAccess">debug</span>))
app.<span class="swift-property">router</span>.<span class="swift-call">get</span>(<span class="swift-string">"/"</span>) { <span class="swift-keyword">_ in
    return</span> <span class="swift-string">"hello"</span>
}
...
app.<span class="swift-call">start</span>()
app.<span class="swift-call">wait</span>()</code></pre><p>On Lambda you would replace this with</p><pre><code><span class="swift-keyword">struct</span> MyHandler: <span class="swift-type">HBLambda</span> {
    <span class="swift-comment">// define input and output</span>
    <span class="swift-keyword">typealias</span> In = <span class="swift-type">APIGateway</span>.<span class="swift-type">Request</span>
    <span class="swift-keyword">typealias</span> Out = <span class="swift-type">APIGateway</span>.<span class="swift-type">Response</span>
    
    <span class="swift-keyword">init</span>(<span class="swift-keyword">_</span> app: <span class="swift-type">HBApplication</span>) {
        app.<span class="swift-property">encoder</span> = <span class="swift-type">JSONEncoder</span>()
        app.<span class="swift-property">decoder</span> = <span class="swift-type">JSONDecoder</span>()
        <span class="swift-comment">// middleware</span>
        app.<span class="swift-property">middleware</span>.<span class="swift-call">add</span>(<span class="swift-type">HBLogRequestsMiddleware</span>(.<span class="swift-dotAccess">debug</span>))
        app.<span class="swift-property">router</span>.<span class="swift-call">get</span>(<span class="swift-string">"/"</span>) { <span class="swift-keyword">_ in
            return</span> <span class="swift-string">"hello"</span>
        }
        ...
    }
}

<span class="swift-type">Lambda</span>.<span class="swift-call">run</span> { context <span class="swift-keyword">in
    return</span> <span class="swift-type">HBLambdaHandler</span>&lt;<span class="swift-type">MyHandler</span>&gt;(context: context)
}</code></pre><p>The exact same application setup is used it is just inside the <code>MyHandler.init</code> function. In this situation we are using an APIGateway REST interface to invoke the Lambda so we need to define the <code>In</code> and <code>Out</code> types to be the APIGateway input and output types. You can set these to <code>APIGateway.V2.Request</code> and <code>APIGateway.V2.Response</code> if you want to use an APIGateway HTML interface.</p><h2 id="building_and_uploading">Building and uploading</h2><p>You will need to build your Lambda with the <a href="https://github.com/swift-server/swift-aws-lambda-runtime">swift-aws-lambda-runtime</a>. There are numerous articles on doing this. You can read Fabian Fett's article <a href="https://fabianfett.de/getting-started-with-swift-aws-lambda-runtime">here</a> for details on how to build and upload your Lambda.</p><h2 id="apigateway">APIGateway</h2><p>Once you have a Lambda uploaded, you need to setup your API Gateway interface. Go to the APIGateway console and create a new REST API. Once in the editor for your API you need to replicate the routes you setup in your Hummingbird Lambda and have them invoke the Lambda.</p><p>Click on the "Actions" dropdown.</p><img src="/images/going-serverless-with-hummingbird/actions-dropdown.png"/><p>You create path elements through <code>Create Resource</code>. If you have a route "/user" create a resource with path "user". If you have another route "/user/:id" create a resource inside the "user" resource with the path "{id}". This is the syntax for URI parameters. For each path you have methods, select the path and then choose <code>Create Method</code>, select the method you want in the dropdown. In the method creation dialog choose <code>Lambda Function</code>, enable <code>Use Lambda Proxy Integration</code> and select the Lambda Function you setup earlier. Once you have setup a method you can add validation for request inputs. This isn't truely necessary as Hummingbird will do this for you, but it does mean not invoking your Lambda when clients send bad requests which is a cost saving for you.</p><p>Once your resources and methods are entered select <code>Deploy API</code>. You should be able to invoke your Hummingbird Lambda using the endpoint provided to you and hey presto you've gone serverless.</p><h2 id="example">Example</h2><p>The <a href="https://github.com/hummingbird-project/hummingbird-examples">hummingbird-examples</a> repository has two examples: todos-dynamodb and todos-lambda. These are both the same application one written to be run as a server and one to be run serverless on AWS Lambda. The code for these two examples is almost exactly the same. There is one minor difference where I needed to workout the host name. The Lambda example also includes a Swagger file you can use to initialize your API Gateway setup with the required resources and methods. You just need to wire up the methods to your Lambda. Please take a look and see how easy it can be to go serverless.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/02/hummingbird.html</guid><link>https://opticalaberration.com/2021/02/hummingbird.html</link><title>Hummingbird: A Swift HTTP server framework</title><description>Hey, I wrote a new SwiftNIO based HTTP server framework. What'd you do that for Adam? Well I guess I like making tech, but also I thought there was a gap in the market for something a little more slimline than the "market leader". Yes you guessed it Vapor. I don't think anyone can really consider building a Swift server framework without trying to differentiate themselves from Vapor.Welcome to &lt;a href="https://github.com/hummingbird-project/hummingbird"&gt;Hummingbird&lt;/a&gt;. Hummingbird is a lightweight,…</description><pubDate>Thu, 18 Feb 2021 15:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="hummingbird__a_swift_http_server_framework">Hummingbird: A Swift HTTP server framework</h1><p>Hey, I wrote a new SwiftNIO based HTTP server framework. What'd you do that for Adam? Well I guess I like making tech, but also I thought there was a gap in the market for something a little more slimline than the "market leader". Yes you guessed it Vapor. I don't think anyone can really consider building a Swift server framework without trying to differentiate themselves from Vapor.</p><p>Welcome to <a href="https://github.com/hummingbird-project/hummingbird">Hummingbird</a>. Hummingbird is a lightweight, flexible server framework. It is split into three section. HummingbirdCore: the HTTP server, Hummingbird: the web application framework and finally the extension modules.</p><h2 id="hummingbird_core">Hummingbird Core</h2><p><a href="https://github.com/hummingbird-project/hummingbird-core">Hummingbird Core</a> is a SwiftNIO based HTTP server. It abstracts all the Swift NIO server code away. You just need to provide it with an object conforming to protocol <code>HBHTTPResponder</code> when you start the server. This protocol requires one function to be implemented:</p><pre><code><span class="swift-keyword">func</span> respond(
    to request: <span class="swift-type">HBHTTPRequest</span>, 
    context: <span class="swift-type">ChannelHandlerContext</span>
) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">HBHTTPResponse</span>&gt;</code></pre><p>You are provided with an HTTP request object <code>HBHTTPRequest</code> as a parameter and are expected to return an <code>EventLoopFuture</code> holding a <code>HBHTTPResponse</code>. With this you have the core of a web server, that receives incoming requests and sends outgoing responses.</p><p>The idea behind splitting off the web server element of Hummingbird is to provide people with a starting point to write their own frameworks without having to worry about all the Swift NIO server code.</p><h2 id="hummingbird">Hummingbird</h2><p><a href="https://github.com/hummingbird-project/hummingbird">Hummingbird</a> is the web application framework that sits atop of HummingbirdCore. It is designed to require the minimum of dependencies: <code>swift-backtrace</code>, <code>swift-log</code>, <code>swift-nio</code>, <code>swift-nio-extras</code>, <code>swift-service-lifecycle</code> and <code>swift-metrics</code> and makes no use of Foundation. This is where I hope to provide something different. Vapor is heavyweight. It brings in a lot of dependencies and has a lot of code that possibly won't be used in many projects. Hummingbird is trying to do the exact opposite. You get a minimal core framework which can be extended through separate modules.</p><p>The framework provides a standard set of features: a router for directing endpoints to their handlers, middleware for processing requests before they reach their handlers and processing the responses returned, custom channel handlers to extend the HTTP server (TLS, HTTP2 and compression are already implemented), extending the core <code>HBApplication</code>, <code>HBRequest</code> and <code>HBResponse</code> classes and providing custom encoding/decoding of <code>Codable</code> objects.</p><p>The interface is fairly standard. Anyone with experience of Vapor, Express.js etc will recognise most of the APIs. You could construct a simple example that returns the string "Hello" in the response payload as follows.</p><pre><code><span class="swift-keyword">import</span> Hummingbird

<span class="swift-keyword">let</span> app = <span class="swift-type">Application</span>(configuration: .<span class="swift-keyword">init</span>(address: .<span class="swift-call">hostname</span>(<span class="swift-string">"127.0.0.1"</span>, port: <span class="swift-number">8080</span>)))
app.<span class="swift-property">router</span>.<span class="swift-call">get</span>(<span class="swift-string">"hello"</span>) { <span class="swift-keyword">_ in
    return</span> <span class="swift-string">"Hello"</span>
}
app.<span class="swift-call">start</span>()
app.<span class="swift-call">wait</span>()</code></pre><h2 id="hummingbird_extensions">Hummingbird extensions</h2><p>Because of the desire to keep the core library dependencies to a minimum I provide extension libraries for features that bring in additional dependencies. <code>HummingbirdFoundation</code> provides features I couldn't implement without <code>Foundation</code>. These include JSON encoding/decoding, URL encoded form encoding/decoding, static file serving and cookies.</p><p>Additional extensions are available in separate repositories.</p><ul><li><a href="https://github.com/hummingbird-project/hummingbird-auth">HummingbirdAuth</a>: An authentication framework with supporting libraries.</li><li><a href="https://github.com/hummingbird-project/hummingbird-compression">HummingbirdCompression</a>: Request decompression and response compression support.</li><li><a href="https://github.com/hummingbird-project/hummingbird-fluent">HummingbirdFluent</a>: Hummingbird doesn't provide a database ORM, so I have taken the liberty to provide an interface to Vapor's <a href="https://github.com/vapor/fluent-kit">Fluent</a>.</li><li><a href="https://github.com/hummingbird-project/hummingbird-redis">HummingbirdRedis</a>: Hummingbird interface to Redis, using <a href="https://gitlab.com/mordil/RediStack">RediStack</a>.</li><li><a href="https://github.com/hummingbird-project/hummingbird-websocket">HummingbirdWebSocket</a>: Adds support for WebSocket connection upgrades.</li></ul><h2 id="thanks">Thanks</h2><p>I am very thankful for the work the Vapor team have done and to say Vapor hasn't influenced some of the choices made when developing Hummingbird would be a lie. Also given Hummingbird doesn't provide a database solution we are dependent on the one provided by Vapor. Thankfully they have been forward thinking enough and generous to ensure many of their modules can be used separate from Vapor.</p><p>Without the Swift NIO team, Hummingbird would not exist. Swift NIO does all the hard work, Hummingbird is just trying to bring it all together and present it in an easy to use package.<br><br>Hummingbird is in its infancy at the moment and many features are still to be implemented, but a standard web app can be built with it. You can find the code for Hummingbird <a href="https://github.com/hummingbird-project/hummingbird">here</a>.</p>]]></content:encoded></item><item><guid>https://opticalaberration.com/2021/01/mqtt-nio-chat.html</guid><link>https://opticalaberration.com/2021/01/mqtt-nio-chat.html</link><title>Chat client using MQTT NIO</title><description>I recently wrote a MQTT client with Swift NIO. You can find it &lt;a href="https://github.com/adam-fowler/mqtt-nio"&gt;here&lt;/a&gt;. This article covers how to create a simple chat client using said library.For those who don't know MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol used extensively in IoT (Internet of Things) technologies. The MQTT protocol defines two types of network entities: a message broker and a client. The broker receives all the messages from the…</description><pubDate>Wed, 6 Jan 2021 16:00:00 +0000</pubDate><content:encoded><![CDATA[<h1 id="chat_client_using_mqtt_nio">Chat client using MQTT NIO</h1><p>I recently wrote a MQTT client with Swift NIO. You can find it <a href="https://github.com/adam-fowler/mqtt-nio">here</a>. This article covers how to create a simple chat client using said library.</p><p>For those who don't know MQTT (Message Queuing Telemetry Transport) is a lightweight publish/subscribe messaging protocol used extensively in IoT (Internet of Things) technologies. The MQTT protocol defines two types of network entities: a message broker and a client. The broker receives all the messages from the clients and then routes these to the appropriate destination clients based on whether they are subscribed to the relevant message topic. The protocol is lightweight making it ideal for IoT devices which don't necessarily have a great deal of processing power.</p><p>Swift NIO is a low level event driven networking library written by Apple. It is described as being like <a href="https://netty.io/">Netty</a> but written for Swift. I have had a fair amount of experience using Swift NIO with my work on <a href="https://github.com/soto-project/soto">Soto</a> but I have never implemented a client for a specific protocol with it. Given this I thought I would use this as an excuse to learn a little more about both Swift NIO and MQTT. The result was <a href="https://github.com/adam-fowler/mqtt-nio">MQTT NIO</a></p><h2 id="concept">Concept</h2><p>We'll keep this fairly simple. We are going to create a console application that will allow you to connect to a MQTT server and particular topic, with a username. You will be able to send messages to a topic and receive all other messages published to the same topic. Originally I wrote an article detailing all the code in the chat client but ditched that in favour of something that concentrates just on the MQTT elements of client. You can see full source for the client <a href="https://github.com/adam-fowler/mqtt-nio-chat">here</a>.</p><h2 id="client_initialization">Client initialization</h2><p>The MQTT client is setup with the default configuration but could be configured to connect to a websocket or TLS connection if required. You need an identifier for your client. If you connect with an identifier already used, the broker will disconnect the other client using that identifier. We prefix the identifier with "MQTTNIOChat-" to avoid clashing with other systems using the MQTT broker.</p><pre><code><span class="swift-keyword">self</span>.<span class="swift-property">mqttClient</span> = <span class="swift-type">MQTTClient</span>(
    host: command.<span class="swift-property">servername</span>,
    port: command.<span class="swift-property">port</span>,
    identifier: <span class="swift-string">"MQTTNIOChat-</span>\(command.<span class="swift-property">username</span>)<span class="swift-string">"</span>,
    eventLoopGroupProvider: .<span class="swift-dotAccess">createNew</span>,
    configuration: .<span class="swift-keyword">init</span>()
)</code></pre><h2 id="connection">Connection</h2><p>The first thing we need to do is connect to the MQTT broker. In the sample I use a locally running broker but you could use your own, or a public broker. Please note if you use a public broker all your messages will visible to the rest of the world.</p><pre><code><span class="swift-keyword">func</span> setup() -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">Void</span>&gt; {
    <span class="swift-comment">// connect, subscribe and publish joined message</span>
    <span class="swift-keyword">self</span>.<span class="swift-property">mqttClient</span>.<span class="swift-call">connect</span>(cleanSession: <span class="swift-keyword">true</span>).<span class="swift-call">flatMap</span> { hasSession -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">Void</span>&gt; <span class="swift-keyword">in
        let</span> subscription = <span class="swift-type">MQTTSubscribeInfo</span>(topicFilter: <span class="swift-keyword">self</span>.<span class="swift-property">topicName</span>, qos: .<span class="swift-dotAccess">exactlyOnce</span>)
        <span class="swift-keyword">return self</span>.<span class="swift-property">mqttClient</span>.<span class="swift-call">subscribe</span>(to: [subscription])
    }
    .<span class="swift-call">flatMap</span> { <span class="swift-keyword">_ in
        self</span>.<span class="swift-call">addListeners</span>()
        <span class="swift-keyword">return self</span>.<span class="swift-call">sendMessage</span>(<span class="swift-string">"Joined!"</span>)
    }
}</code></pre><p>In <code>mqttClient.connect</code> we set <code>cleanSession</code> to true. This means if there is already an existing session for this user (identifier) then we will ditch it. The existing session will include subscriptions to topics we are maybe no longer interested in. We then subscribe to the topic we are interested in. In the subscription we set <code>qos</code> to <code>.exactlyOnce</code> to ensure we only receive published messages once. If we set it to <code>.atLeastOnce</code> we could receive messages twice if there are connection issues. We would need to keep a record of previously received messages to avoid outputting them twice. If we set it to <code>.atMostOnce</code> we could miss messages if there are connection issues.</p><h2 id="receiving_messages">Receiving messages</h2><p>Once the subscription has gone through we call <code>addListeners()</code>. This adds a listener waiting for PUBLISH events from the broker. For every PUBLISH event the callback is called.</p><pre><code><span class="swift-keyword">func</span> addListeners() {
    <span class="swift-keyword">self</span>.<span class="swift-property">mqttClient</span>.<span class="swift-call">addPublishListener</span>(named: <span class="swift-string">"ListenForChat"</span>) { result <span class="swift-keyword">in
        switch</span> result {
        <span class="swift-keyword">case</span> .<span class="swift-dotAccess">failure</span>:
            <span class="swift-keyword">self</span>.<span class="swift-property">closePromise</span>.<span class="swift-call">fail</span>(error)
        <span class="swift-keyword">case</span> .<span class="swift-dotAccess">success</span>(<span class="swift-keyword">let</span> publishInfo):
            <span class="swift-keyword">if</span> publishInfo.<span class="swift-property">topicName</span> == <span class="swift-keyword">self</span>.<span class="swift-property">topicName</span> {
                <span class="swift-call">receiveMessage</span>(publishInfo.<span class="swift-property">payload</span>)
            }
        }
    }
}</code></pre><p>If the listener calls the callback with an error we fail the <code>closePromise</code> <code>EventLoopPromise</code> setup in the chat client object. If we receive a message packet and the message topic is equal to the topic we are subscribed to then we call the <code>receiveMessage</code> function. This parses the message packet (it is formatting in JSON), and as long as you didn't send it, outputs it to the console.</p><h2 id="sending_messages">Sending messages</h2><p>The main loop of the client reads from <code>stdin</code> using <code>readLine</code> and then creates a message packet and uses <code>MQTTClient.publish</code> to publish the packet to the MQTT broker. The <code>sendMessage</code> function is as follows.</p><pre><code><span class="swift-keyword">func</span> sendMessage(<span class="swift-keyword">_</span> message: <span class="swift-type">String</span>) -&gt; <span class="swift-type">EventLoopFuture</span>&lt;<span class="swift-type">Void</span>&gt; {
    <span class="swift-keyword">let</span> packet = <span class="swift-type">ChatPacket</span>(from: command.<span class="swift-property">username</span>, message: message)
    <span class="swift-keyword">var</span> buffer = <span class="swift-type">ByteBufferAllocator</span>().<span class="swift-call">buffer</span>(capacity: <span class="swift-number">0</span>)
    <span class="swift-keyword">try</span>? <span class="swift-type">JSONEncoder</span>().<span class="swift-call">encode</span>(packet, into: &amp;buffer)
    <span class="swift-keyword">return self</span>.<span class="swift-property">mqttClient</span>.<span class="swift-call">publish</span>(to: <span class="swift-keyword">self</span>.<span class="swift-property">topicName</span>, payload: buffer, qos: .<span class="swift-dotAccess">exactlyOnce</span>)
}</code></pre><p>Construct <code>ChatPacket</code>, encode into JSON formatted <code>ByteBuffer</code> and then publish the <code>ByteBuffer</code> to the topic.</p><h2 id="errors">Errors</h2><p>I run the mainloop on the global default system queue using <code>DispatchQueue</code> and leave the main thread waiting on a result from the <code>closePromise</code>. If there is an error the client will exit as the <code>closePromise</code> is fulfilled with an error. We can also catch a disconnection from the broker using a <code>closeListener</code> which fails the <code>closePromise</code>.</p><pre><code><span class="swift-keyword">func</span> addListeners() {
    ...
    <span class="swift-keyword">self</span>.<span class="swift-property">mqttClient</span>.<span class="swift-call">addCloseListener</span>(named: <span class="swift-string">"CheckForClose"</span>) { result <span class="swift-keyword">in
        self</span>.<span class="swift-property">closePromise</span>.<span class="swift-call">fail</span>(<span class="swift-type">MQTTChatClientError</span>(message: <span class="swift-string">"Lost connection"</span>))
    }
}</code></pre><h2 id="extending">Extending</h2><p>This is a really simple example of how MQTT can be used. I probably spent more time trying to get the ANSI escape sequences working (for overwriting the prompt with new messages) than the chat functionality. It has no real user management or access control. You would need additional services for that. But it gives you a quick idea what an MQTT broker can be used for. Please go to <a href="https://github.com/adam-fowler/mqtt-nio-chat">https://github.com/adam-fowler/mqtt-nio-chat</a> and checkout the full running example.</p>]]></content:encoded></item></channel></rss>