Skip to content

Instantly share code, notes, and snippets.

@vzsg
Created March 3, 2019 11:19
Show Gist options
  • Save vzsg/7a309d24a1a92cf706a0dd17183673b9 to your computer and use it in GitHub Desktop.
Save vzsg/7a309d24a1a92cf706a0dd17183673b9 to your computer and use it in GitHub Desktop.
Using SwiftProtobuf with Vapor 3
import Vapor
import SwiftProtobuf
import Foundation
extension Request {
public func decodeMessage<M: SwiftProtobuf.Message>(_ type: M.Type = M.self) throws -> M {
let data = http.body.data ?? Data()
if http.contentType == MediaType.json {
return try M(jsonUTF8Data: data)
}
return try M(serializedData: data)
}
}
extension SwiftProtobuf.Message {
fileprivate func toHTTPResponse(json: Bool = false) throws -> HTTPResponse {
var http = HTTPResponse(status: .ok)
if json {
http.contentType = MediaType.json
http.body = try jsonUTF8Data().convertToHTTPBody()
} else {
http.contentType = MediaType(type: "application", subType: "x-protobuf")
http.body = try serializedData().convertToHTTPBody()
}
return http
}
public func toResponse(on req: Request) throws -> Response {
let json = req.http.accept.contains(where: { $0.mediaType == MediaType.json })
return Response(http: try toHTTPResponse(json: json), using: req)
}
}
extension Future {
public func toResponse<M>(_ type: M.Type = M.self, on req: Request) -> Future<Response> where Expectation: SwiftProtobuf.Message {
return map { 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"}}
@vzsg
Copy link
Author

vzsg commented Jan 13, 2020

Thank you!

@3a4oT
Copy link

3a4oT commented Jan 25, 2020

Thanks for sharing! It is clever!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment