BT

Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ

Topics

Choose your language

InfoQ Homepage News Smoke is a New Lightweight Server-Side Framework for Swift from Amazon

Smoke is a New Lightweight Server-Side Framework for Swift from Amazon

This item in japanese

Amazon Smoke framework is a new open-source light-weight server-side framework written in Swift and aimed to build REST-like or RPC-like services. Its architecture stresses ease of use and favours a pure-functional programming style for request handlers.

Creating a service with Amazon Smoke requires three steps:

  • Defining the operations that will handle incoming requests. Each such operation is defined through a function that takes an OperationInput and a generic ApplicationContext, and returns an OperationOutput, either synchronously or asynchronously, as the following code shows:

    // Synchronous handler
    func handleTheOperation(input: OperationInput, context: MyApplicationContext) throws -> OperationOutput {
      return OperationOutput()
    }
    
    // Asynchronous handler
    func handleOperationAsync(input: OperationInput, context: MyApplicationContext,
                      responseHandler: (SmokeResult<OutputAttributes>) -> ()) throws {
    
      let result = OperationOutput()
      rensponseHandler(.response(attributes))
    }
    

Input and output types must conform to the ValidatableCodable protocol, which enables the validation of input and output fields through a validate function.

  • Specifying how operation handlers are selected to process incoming requests. Out of the box, Smoke provides a StandardSmokeHTTP1HandlerSelector that can be used for REST-like services, where the handler for a given request is selected based on its HTTP verb and URI:

    import SmokeOperations
    
    public typealias HandlerSelectorType =
    StandardSmokeHTTP1HandlerSelector<MyApplicationContext, JSONPayloadHTTP1OperationDelegate>
    
    public func createHandlerSelector() -> HandlerSelectorType {
      var newHandler = HandlerSelectorType()
    
      newHandler.addHandlerForUri("/theOperationPath", httpMethod: .POST,
                            operation: handleTheOperation,
                            allowedErrors: [(MyApplicationErrors.unknownResource, 400)])
    
      return newHandler
    }
    
  • Setting up an application server to decode requests, dispatch handlers, and encoding and sending responses back to the client. Encoding and decoding are responsibilities of an application delegate that is passed as an argument to the application server. Smoke includes a JSONPayloadHTTP1OperationDelegate for JSON requests and responses. The application server is also responsible to instantiate and pass the application context around:

    import Foundation
    import SmokeHTTP1
    import SmokeOperations
    import LoggerAPI
    
    // Enable logging here
    
    let operationContext = ... 
    
    do {
        try SmokeHTTP1Server.startAsOperationServer(
            withHandlerSelector: createHandlerSelector(),
            andContext: operationContext,
            defaultOperationDelegate: JSONPayloadHTTP1OperationDelegate())
    } catch {
        Log.error("Unable to start Operation Server: '\(error)'")
    }
    

A key concept in Amazon Smoke is the application context, which is created at launch time and passed to all handlers, possibly simultaneously. Amazon recommends to make this object strongly-typed and immutable in order to streamline concurrent behaviour by removing the need for being thread-safe. Other than that, it can be of any type. Using a context ensures handlers can be written as pure-functions, that is their output is only dependent on their inputs and the passed context. This makes it easier to unit test handlers and specifically to hide any differences between development and deployment environment to the handlers. This can be achieved by using the context to pass any dependency that might differ between development and deployment contexts, such as mocking services, random number generators, etc.

Amazon Smoke is built on top of Apple’s SwiftNIO and integrated in the Swift Package Manager. You can include it in a project by adding the following dependency rule to package.swift:

dependencies: [
    .package(url: "https://github.com/amzn/smoke-framework.git", .upToNextMajor(from: "0.6.0"))
]

Smoke is not the only server-side framework for Swift. Other notable examples are Vapor and Kitura. In comparison with Smoke, both Vapor and Kitura have more articulated architectures and recall in some ways Node Express API. Both also include a higher number of components, including components for database access, session and credentials managements, and many more.

Rate this Article

Adoption
Style

BT