import Vapor func routes(_ app: Application) { /** Post a message to the device for unlocking. The expects a `Message` in the body data of the POST request, containing the message to send to the device. Expects a header ``RouteAPI.authenticationHeader`` with the hexencoded authentication token with binary length ``ServerMessage.authTokenSize``. The request returns the ``ServerMessage.messageSize`` bytes of data constituting the device response, or a status code corresponding to a ``MessageResult``. This request does not complete until either the device responds or the request times out. The timeout is specified by the configuration parameter `deviceTimeout`. */ app.post(SesameRoute.postMessage.path) { request async throws in do { guard let authString = request.headers.first(name: SesameHeader.authenticationHeader), let authToken = Data(fromHexEncodedString: authString), authToken.count == SesameHeader.serverAuthenticationTokenSize else { throw MessageResult.missingOrInvalidAuthenticationHeader } guard let body = request.body.data, let message = body.getData(at: 0, length: body.readableBytes) else { throw MessageResult.noOrInvalidBodyDataInServerRequest } let responseMessage = try await deviceManager.sendMessageToDevice(message, authToken: authToken, on: request.eventLoop) return Response(status: .ok, body: .init(data: responseMessage)) } catch let error as MessageResult { return Response(status: .init(statusCode: error.statusCode)) } } /** Start a new websocket connection for the device to receive messages from the server. The request must contain a header ``RouteAPI.socketAuthenticationHeader`` with a valid authentication token. */ app.webSocket(SesameRoute.socket.path) { request, socket async in guard let authToken = request.headers.first(name: SesameHeader.authenticationHeader) else { try? await socket.close() return } await deviceManager.createNewDeviceConnection(socket: socket, auth: authToken) } }