Skip to content

Instantly share code, notes, and snippets.

@mkll
Forked from vzsg/1_Vapor+Proto.swift
Created February 15, 2023 16:28
Show Gist options
  • Save mkll/9122e410f285a88e759ff47b7d50e3df to your computer and use it in GitHub Desktop.
Save mkll/9122e410f285a88e759ff47b7d50e3df 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"}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment