Skip to content

Instantly share code, notes, and snippets.

@adirburke
Forked from vzsg/1_Vapor+Proto.swift
Last active January 10, 2020 14:30
Show Gist options
  • Save adirburke/855b8a9729002c8f45b756e091a5a224 to your computer and use it in GitHub Desktop.
Save adirburke/855b8a9729002c8f45b756e091a5a224 to your computer and use it in GitHub Desktop.
Using SwiftProtobuf with Vapor 4
import Vapor
import SwiftProtobuf
import Foundation
extension ByteBuffer {
public func allData() -> Data {
return getData(at: 0, length: readableBytes) ?? Data()
}
}
extension Request {
public func decodeMessage<M: SwiftProtobuf.Message>(_ type: M.Type = M.self) throws -> M {
let data = self.body.data?.allData() ?? Data()
if headers.contentType == .json {
return try M(jsonUTF8Data: data)
}
return try M(serializedData: data)
}
}
extension SwiftProtobuf.Message {
fileprivate func toHTTPResponse(json: Bool = false) throws -> Response {
let http = Response(status: .ok)
if json {
http.headers.contentType = .json
http.body = .init(string: try jsonString())
} else {
http.headers.contentType = .init(type: "application", subType: "protobuf")
http.body = .init(data: try serializedData())
}
return http
}
public func toResponse(on req: Request) throws -> Response {
let json = req.headers.accept.contains(where: { $0.mediaType == .json })
let response = try toHTTPResponse(json: json)
return response
}
}
extension EventLoopFuture {
public func toResponse<M>(_ type: M.Type = M.self, on req: Request) -> EventLoopFuture<Response> where Value : SwiftProtobuf.Message {
return self.flatMapThrowing { try $0.toResponse(on: req) }
}
}
router.get("test") { req -> Response in
var profile = Proto_UserProfile()
var user = Proto_User()
user.nickname = "FooBar"
user.firstName = "Foo"
user.lastName = "Bar"
profile.user = user
return try profile.toResponse(on: req)
}
// Calling without an accept header: curl localhost:8080/test
// --> returns binary message
// Calling with accept header: curl localhost:8080/test -H "Accept: application/json"
// --> returns JSON
// {"user":{"nickname":"FooBar","firstName":"Foo","lastName":"Bar"}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment