A while back I covered building a web application with Vapor 3. Since then a lot has changed in Swift and Vapor. Vapor now fully supports async await and has full sendable conformance. In this series we’ll explore building a Vapor application that is a backend for an app that manages songs and set lists for cover bands. This will offer us a chance to build with the new async/await style as well as explore how to use Fluent and Postgresql to persist and query our data.
Length: about 3 hours
Docker is a common choice for running services locally for development as well as server deployment. Vapor comes by default with a working Docker setup, so in this video we will explore how this all works. We'll also explore how to configure the database with Environment variables.
In order to evolve a persistent store over time you have to migrate the data. Fluent, the Vapor Framework that offers ORM support for popular databases, has a solution for this. In this episode we will understand how to write migrations, how to revert them and how to evolve your schema over time without losing data.
Now that we have our database setup, we can create our models. We'll start by examining the Model and Content protocols, then implement the necessary properties decorated with Fluent's property wrappers to denote primary keys, fields, and foreign keys.
In this episode, we explore Vapor routing more deeply. We set up a route to fetch a band by its slug, handling async operations and errors. After testing, we refactor with a findBySlug method for reusability. We add a route to fetch songs for a band and discuss avoiding inefficient querying. To organize the code, we create BandsController and SongsController to group routes.
In this episode, we create a form to create songs from our API by implementing a create route. We use a payload struct to normalize and validate user input for song title and artist name. We also ensure that duplicate artists are not created by using a custom comparison method. Finally, we create the artist and song in the database and return the newly created song. We also configure the JSON output to use snake case instead of camelcase for our default encoder and decoder for our Vapor app.
This episode will introduce a new model for a User that will contain validations to ensure the email address format is correct (using a built-in regular expression) and that the password length is good and secure. We'll also ensure to hash the password with bcrypt before storing it in the database. Finally we'll make a custom Response model for our User so that we don't reveal internal fields to clients.
In this episode we will explore how to use AsyncRequestAuthenticator types, such as AsyncBasicAuthenticator and AsyncBearerAuthenticator. We’ll see how to compose these to support multiple authentication strategies and how to protect certain routes to require authenticated users.
In this episode we will explore supporting JSON Web Tokens, or JWTs. These are a common standard for use in authentication tokens which allows you to support 3rd party authentication providers, token expiration, user metadata and more. These are cryptographically signed and can be verified by the server with a secret. There is also the option to use RSA public/private key pairs to allow clients to verify tokens without going back to the server that signed them. For these reasons JWTs are a really powerful option. Here we will use the Vapor JWT package to provide support for generating and authenticating with HS256 tokens.
Redis is a popular choice for a key-value store for backend applications. This can be used for a multitude of different reasons, such as caching with automatic expiration, rate limiting based on ip address, leaderboards, pub/sub and much more. Its performance characteristics make it a fantastic choice for queuing systems, which we'll cover soon. In this episode we will set up a redis server in our docker compose file, then integrate it into our Vapor application with a simple middleware to count the number of requests to a given path.
In this episode we will introduce Vapor's Queues package and use Redis as our backing storage engine. The performance characteristics of Redis make it a great choice to store work to be processed later. We'll then set up an EmailJob to send a welcome email to new users. We'll also explore how to run these in-process in development as well as separate processes for production. As a final bonus, we'll create a custom Vapor command to test this all out to see how it behaves with many jobs enqueued.