Caps-Server/Sources/App/routes.swift

116 lines
3.6 KiB
Swift
Raw Normal View History

import Vapor
2022-06-24 11:31:09 +02:00
import Foundation
2020-05-19 15:19:19 +02:00
/// The decoder to extract caps from JSON payloads given to the `cap` route.
private let decoder = JSONDecoder()
2023-01-15 11:21:47 +01:00
/// The date formatter to decode dates in requests
private let dateFormatter: DateFormatter = {
let df = DateFormatter()
df.dateFormat = "yy-MM-dd-HH-mm-ss"
return df
}()
2022-05-27 09:25:41 +02:00
private func authorize(_ request: Request) throws {
2022-06-11 00:20:43 +02:00
guard let key = request.headers.first(name: "key") else {
2022-06-24 11:31:09 +02:00
throw Abort(.badRequest) // 400
2022-06-11 00:20:43 +02:00
}
2022-05-27 09:25:41 +02:00
guard server.hasAuthorization(for: key) else {
2022-06-24 11:31:09 +02:00
throw Abort(.forbidden) // 403
2022-05-27 09:25:41 +02:00
}
}
2023-01-11 18:29:32 +01:00
func routes(_ app: Application) {
2022-06-23 22:48:58 +02:00
2022-06-24 00:23:02 +02:00
app.get("version") { _ in
"\(server.classifierVersion)"
2022-06-23 22:48:58 +02:00
}
// Add or change a cap
app.postCatching("cap") { request in
2022-05-27 09:25:41 +02:00
try authorize(request)
let data = try request.getBodyData()
let cap = try decoder.decode(Cap.self, from: data)
try server.addOrUpdate(cap)
2020-05-19 15:19:19 +02:00
}
// Upload an image
app.postCatching("images", ":n") { request in
2022-05-27 09:25:41 +02:00
try authorize(request)
2020-09-20 11:36:35 +02:00
guard let cap = request.parameters.get("n", as: Int.self) else {
log("Invalid parameter for cap")
throw Abort(.badRequest)
}
let data = try request.getBodyData()
try server.save(image: data, for: cap)
}
2022-06-23 22:48:58 +02:00
// Update the classifier
2022-06-24 11:31:09 +02:00
app.on(.POST, "classifier", ":version", body: .collect(maxSize: "50mb")) { request -> HTTPStatus in
2022-06-23 22:48:58 +02:00
try authorize(request)
guard let version = request.parameters.get("version", as: Int.self) else {
log("Invalid parameter for version")
throw Abort(.badRequest)
}
guard version > server.classifierVersion else {
2022-06-24 11:31:09 +02:00
throw Abort(.alreadyReported) // 208
2022-06-23 22:48:58 +02:00
}
let data = try request.getBodyData()
2022-06-24 11:31:09 +02:00
try server.save(classifier: data, version: version)
return .ok
2022-06-23 22:48:58 +02:00
}
// Update the trained classes
2023-01-15 11:21:47 +01:00
app.postCatching("classes", ":date") { request in
guard let dateString = request.parameters.get("date") else {
log("Invalid parameter for date")
throw Abort(.badRequest)
}
guard let date = dateFormatter.date(from: dateString) else {
log("Invalid date specification")
throw Abort(.badRequest)
}
2022-06-23 22:48:58 +02:00
try authorize(request)
let body = try request.getStringBody()
server.updateTrainedClasses(content: body)
server.removeAllEntriesInImageChangeList(before: date)
}
// Get the list of missing thumbnails
app.get("thumbnails", "missing") { request in
let missingThumbnails = server.getListOfMissingThumbnails()
return missingThumbnails.map(String.init).joined(separator: ",")
}
app.postCatching("thumbnails", ":cap") { request in
guard let cap = request.parameters.get("cap", as: Int.self) else {
log("Invalid cap parameter for thumbnail upload")
throw Abort(.badRequest)
}
let data = try request.getBodyData()
server.saveThumbnail(data, for: cap)
}
}
private extension Request {
func getBodyData() throws -> Data {
guard let buffer = body.data else {
log("Missing body data")
2022-06-23 22:48:58 +02:00
throw CapError.invalidBody
}
return Data(buffer: buffer)
}
func getStringBody() throws -> String {
let data = try getBodyData()
2022-06-23 22:48:58 +02:00
guard let content = String(data: data, encoding: .utf8) else {
log("Invalid string body")
2022-06-23 22:48:58 +02:00
throw CapError.invalidBody
}
return content
2023-01-14 23:04:29 +01:00
}
}