Vapor 3 RC 2 Updates
Vapor 3 RC 2 is out! To update, ensure that your Package.swift contains something like:
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0-rc"),
.package(url: "https://github.com/vapor/fluent-mysql.git", from: "3.0.0-rc"),
.package(url: "https://github.com/vapor/leaf.git", from: "3.0.0-rc"),
Depending on your dependenices - make sure that you use the "X.X.X-rc"
- that's the important bit.
You will also need to update your toolbox - Vapor 3 RC2 now requires LibreSSL for macOS with NIO - you can either upgrade you toolbox (brew upgrade vapor
) or just install LibreSSL (brew install libressl
)
Section 1
Video 4 - Accepting Data
The await(on:)
function has now been deprecated, and was always a stopgap. To accept data before learning about Futures you can use the POST helper function:
router.post(InfoData.self, at: "info") { req, data -> InfoResponse in
return InfoResponse(request: data)
}
Video 5 - Challenge Your Own Routes
As above, use the new function for your POST route:
router.post(UserInfoData.self, at: "user-info") { req, userInfo -> String in
return "Hello \(userInfo.name), you are \(userInfo.age)!"
}
Section 2
Video 3 - Controllers and CRUD
Remove the await(on:)
call in AcronymsController.swift. You can now call save(on:)
directly on a Future<Model>
:
func createHandler(_ req: Request) throws -> Future<Acronym> {
let acronym = try req.content.decode(Acronym.self)
return acronym.save(on: req)
}
Video 5 - Challenge Users and Categories
As for Video 3, in CategoriesController.swift you should now have:
func createHandler(_ req: Request) throws -> Future<Category> {
let category = try req.content.decode(Category.self)
return category.save(on: req)
}
Video 6 - Parent Child Relationships
Fluent's get(on:)
query now throws so the getCreatorHandler(_:)
in AcronymsController.swift now looks like:
func getCreatorHandler(_ req: Request) throws -> Future<User> {
return try req.parameter(Acronym.self).flatMap(to: User.self) { acronym in
return try acronym.creator.get(on: req)
}
Video 8 - Fluent Queries
Fluent's group(_:)
and filter(_:)
queries throw so the searchHandler(_:)
in AcronymsController.swift now looks like:
func searchHandler(_ req: Request) throws -> Future<[Acronym]> {
guard let searchTerm = req.query[String.self, at: "term"] else {
throw Abort(.badRequest)
}
return try Acronym.query(on: req).group(.or) { or in
try or.filter(\.short == searchTerm)
try or.filter(\.long == searchTerm)
}.all()
}
Video 9 - Persisting Data with MySQL
The configuration for MySQLDatabase
is now provided in a separate type. In configure.swift it should now look like:
var databases = DatabaseConfig()
let mysqlConfig = MySQLDatabaseConfig(hostname: "localhost", port: 3306, username: "til", password: "password", database: "vapor")
let database = MySQLDatabase(config: mysqlConfig)
databases.add(database: database, as: .mysql)
services.register(databases)
Section 3
Video 3 - Powerful Templates
As Fluent's get(on:)
query now throws, the acronymHandler(_:)
now looks like:
func acronymHandler(_ req: Request) throws -> Future<View> {
return try req.parameter(Acronym.self).flatMap(to: View.self) { acronym in
return try acronym.creator.get(on: req).flatMap(to: View.self) { creator in
let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator)
return try req.leaf().render("acronym", context)
}
}
}
Section 4
Video 2 - Passwords
Crypto's Random functions have been tweaked. The Token
extension to generate a token should now look like:
extension Token {
static func generate(for user: User) throws -> Token {
let random = try CryptoRandom().generateData(count: 16)
return try Token(token: random.base64EncodedString(), userID: user.requireID())
}
}
BCrypt
functions have been renamed as well. In your UsersController
you'll need to import Crypto
and change your createHandler(_:)
should look like:
func createHandler(_ req: Request) throws -> Future<User> {
return try req.content.decode(User.self).flatMap(to: User.self) { user in
let hasher = try req.make(BCryptDigest.self)
user.password = try String.convertFromData(hasher.hash(user.password))
return user.save(on: req)
}
}
Video 3 - API Authentication
When creating the basicAuthMiddleware
you need to rename the Verifier. Your line should look like:
let basicAuthMiddleware = User.basicAuthMiddleware(using: BCryptDigest())
Video 4 - Website Authentication
When creating the verifier
BCrypt types have been renamed:
let verifier = try req.make(BCryptDigest.self)
Hello *,
Just a few comments to keep in mind when working with more recent versions of Vapor and some of the other components such as Crypto and Leaf.
Notes:
import Crypto
when using BCryptDigest()req.parameters.next()
is used.Abort()
function at AcronymsController.swift:public func hash(_ plaintext: LosslessDataConvertible, cost: Int = 12, salt: LosslessDataConvertible? = nil) throws -> String {...
so there is no need to use
String.convertFromData()
the resulting function at UsersController.swift would look like:DatabaseConfig()
has been renamed toDatabasesConfig()
I hope you all find these comments useful.
Thank you very much