Heimdall: Writing HTTP request logger for Vapor

This article is a brief overview of Heimdall’s source code and explains the process of writing third party plugins for Vapor Web Framework.

Last year, a mentor suggested me to write a logger for Vapor web framework. Initially, it seemed to be a complicated task but the outcome couldn’t have been any simpler. Let’s create a plugin!

Create a Swift Package

A vapor plugin has to be a swift package so it can be imported using Swift Package Manager. So start by creating a swift package by running the following commands on your terminal.

mkdir Heimdall
cd Heimdall
swift package init --type executable

This creates the following directory structure.

Delete the main.swift file in Sources directory. Heimdall is just 2 swift files and it’s less than 200 lines of code! The following is the explanation of both the files without implementation details. Please refer to github repo if you want to go through all the code.

The Logger

What does an HTTP Logger do?

It accesses the information about each request and response like statuscode, HTTP Method etc. and writes it to a file.

You need to create a “Middleware” which runs for each request and simple writes the data to the file. The following code snippet shows a bare bones middleware without implementation details.

class Logger: Middleware {

var path: String = "~/Logs/logfile.txt"
    // This method runs for each web request
public func respond(to request: Request,
chainingTo next: Responder) throws -> Response {
// Access data from the response object
writeToFile(dataToBeLogged)
}
    func writeToFile(path: ) {
// Write swift code that writes to a file
}
}

Provider for integrating the Logger with Vapor Project

Now you have a logger but how will other developers import your logger in their projects? For adding functionality or creating third party packages for Vapor you need to create a “Provider”.

A Provider provides a unified way to import third party packages in a Vapor Web App. In this provider, we initialize the Logger Class and add it as a middleware to the droplet.

public final class Provider: Vapor.Provider {
    public static let repositoryName = "heimdall"
    public let logger: Logger
    public func beforeRun(_: Vapor.Droplet) {}
    public init(format: LogType, path: String) {
logger = Logger(format: format, path: path)
}
    public func boot(_ drop: Droplet) { }
    public func boot(_ config: Config) throws {
// This is how you add a middleware
config.addConfigurable(middleware: logger, name: "heimdall")
}
}

Implement and put these files in Sources directory. And that’s it.

Push the swift package on Github, add a tag to it and anyone can import it in their swift project by adding it as a dependency. Read detailed installation instructions here.

P.S. Heimdall is the all-seeing and all-hearing guardian sentry of Asgard who stands on the rainbow bridge Bifröst to watch for any attacks to Asgard. Now you know why it’s called Heimdall. :)

This guy.

Acknowledgements

I would like to thank Santosh Rajan for suggesting the project, Himani for contributing to the codebase and Fabrizio Brancati for sending us a pull request when we needed it the most. :)