Skip to content

Commit 499ece9

Browse files
author
Jan Kammerath
committed
added VaporProxy class to move the proxy code into a different class
1 parent df6d73d commit 499ece9

File tree

2 files changed

+87
-48
lines changed

2 files changed

+87
-48
lines changed

src/Handler.swift

+8-48
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,18 @@ struct HelloWorld: Content {
1111
struct APIGatewayProxyLambda: LambdaHandler {
1212
typealias Event = APIGatewayRequest
1313
typealias Output = APIGatewayResponse
14-
14+
1515
init(context: LambdaInitializationContext) async throws {
1616
print("Serverless Swift cold started!")
1717

18-
Task {
19-
// instanciate the vapor application
20-
let vaporApp = Vapor.Application()
21-
22-
// define the routes for the vapor app
23-
vaporApp.get { req in
18+
let vaporProxy = VaporProxy.shared
19+
if !vaporProxy.isRunning() {
20+
let app = vaporProxy.app
21+
app.get { req in
2422
return HelloWorld(message: "Hello, world!")
2523
}
26-
27-
// run the app locally, so we can proxy to it
28-
let vaporAddress = BindAddress.hostname("127.0.0.1", port: 8585)
29-
vaporApp.http.server.configuration.address = vaporAddress
30-
31-
try? vaporApp.run()
24+
25+
vaporProxy.start()
3226
}
3327
}
3428

@@ -37,40 +31,6 @@ struct APIGatewayProxyLambda: LambdaHandler {
3731
by executing the Vapor application and returning the json response
3832
*/
3933
func handle(_ request: APIGatewayRequest, context: LambdaContext) async throws -> APIGatewayResponse {
40-
// perform an http request to the vapor app
41-
let client = HTTPClient()
42-
var url = "http://127.0.0.1:8585" + request.path
43-
var headers = HTTPHeaders()
44-
var body: HTTPClient.Body?
45-
46-
let httpMethod = HTTPMethod(rawValue: request.requestContext.httpMethod)
47-
48-
if let queryString = request.queryStringParameters {
49-
url += "?" + queryString.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
50-
}
51-
52-
if let bodyString = request.body {
53-
let bodyData = Data(bodyString.utf8)
54-
body = .byteBuffer(ByteBuffer(data: bodyData))
55-
headers.add(name: "Content-Length", value: "\(bodyData.count)")
56-
headers.add(name: "Content-Type", value: "application/json")
57-
}
58-
59-
for (key, value) in request.headers {
60-
headers.add(name: key, value: value)
61-
}
62-
63-
let httpRequest = try HTTPClient.Request(url: url, method: httpMethod, headers: headers, body: body)
64-
let response = try await client.execute(request: httpRequest).get()
65-
66-
let bodyString = response.body!.getString(at: 0, length: response.body!.readableBytes)
67-
68-
var gatewayResponse = APIGatewayResponse(statusCode: .init(code: response.status.code))
69-
gatewayResponse.body = bodyString
70-
for (key, value) in response.headers {
71-
gatewayResponse.headers?[key] = value
72-
}
73-
74-
return gatewayResponse
34+
return try! await VaporProxy.shared.handle(request: request)
7535
}
7636
}

src/VaporProxy.swift

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import AWSLambdaEvents
2+
import Vapor
3+
4+
class VaporProxy {
5+
/* singleton instance of the VaporProxy class */
6+
static let shared = VaporProxy()
7+
8+
var app = Vapor.Application()
9+
let port = 8585
10+
private var running = false
11+
12+
/* returns true if the vapor app is running */
13+
func isRunning() -> Bool {
14+
return running
15+
}
16+
17+
/* starts the vapor app that listens on the
18+
defined port. The port is used to connect
19+
to the app through this proxy class */
20+
func start() {
21+
guard !running else {
22+
print("Vapor app is already running, not starting it")
23+
return
24+
}
25+
26+
let address = BindAddress.hostname("127.0.0.1", port: 8585)
27+
app.http.server.configuration.address = address
28+
29+
DispatchQueue.global().async {
30+
do {
31+
self.running = true
32+
try self.app.run()
33+
} catch {
34+
print("Failed to start app: \(error)")
35+
self.running = false
36+
}
37+
}
38+
}
39+
40+
/* handles api gateway requests and forwards them
41+
to the vapor app running on the defined port */
42+
func handle(request: APIGatewayRequest) async throws -> APIGatewayResponse {
43+
// perform an http request to the vapor app
44+
let client = HTTPClient()
45+
var url = "http://127.0.0.1:\(port)" + request.path
46+
var headers = HTTPHeaders()
47+
var body: HTTPClient.Body?
48+
49+
let httpMethod = HTTPMethod(rawValue: request.requestContext.httpMethod)
50+
51+
if let queryString = request.queryStringParameters {
52+
url += "?" + queryString.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
53+
}
54+
55+
if let bodyString = request.body {
56+
let bodyData = Data(bodyString.utf8)
57+
body = .byteBuffer(ByteBuffer(data: bodyData))
58+
headers.add(name: "Content-Length", value: "\(bodyData.count)")
59+
headers.add(name: "Content-Type", value: "application/json")
60+
}
61+
62+
for (key, value) in request.headers {
63+
headers.add(name: key, value: value)
64+
}
65+
66+
let httpRequest = try HTTPClient.Request(url: url, method: httpMethod, headers: headers, body: body)
67+
let response = try await client.execute(request: httpRequest).get()
68+
69+
let bodyString = response.body!.getString(at: 0, length: response.body!.readableBytes)
70+
71+
var gatewayResponse = APIGatewayResponse(statusCode: .init(code: response.status.code))
72+
gatewayResponse.body = bodyString
73+
for (key, value) in response.headers {
74+
gatewayResponse.headers?[key] = value
75+
}
76+
77+
return gatewayResponse
78+
}
79+
}

0 commit comments

Comments
 (0)