Skip to content

Instantly share code, notes, and snippets.

@justinjones
Created December 5, 2018 02:07
Show Gist options
  • Save justinjones/99b8debfc723cfc4ef9a75d6da4c098f to your computer and use it in GitHub Desktop.
Save justinjones/99b8debfc723cfc4ef9a75d6da4c098f to your computer and use it in GitHub Desktop.
Amber Prototype - AWS Lambda Runtime, API Gateway (Proxy)
require "http/client"
require "http/request"
require "http/params"
require "http/server/response"
require "http/server/context"
require "../config/*"
class ApiGatewayEvent
include JSON::Serializable
property path : String
@[JSON::Field(key: "httpMethod")]
property method : String
@[JSON::Field(key: "queryStringParameters")]
property query_params : Hash(String, String)?
property body : String?
property headers : Hash(String, String)?
end
class LambdaRequest
@@handler : Amber::Pipe::Pipeline
@@handler = Amber::Server.handler
@@handler.prepare_pipelines
@response : HTTP::Client::Response?
def self.handler
@@handler
end
getter event : ApiGatewayEvent
getter request_id : String
getter response : HTTP::Client::Response
def initialize(response : HTTP::Client::Response)
@lambda_response = response
@request_id = response.headers["Lambda-Runtime-Aws-Request-Id"]
@event = ApiGatewayEvent.from_json(response.body)
@response = process_request
end
def payload
hdrs = Hash(String, String).new
response.headers.each do |k, v|
hdrs[k] = v.join(", ")
end
{
"headers" => hdrs,
"statusCode" => response.status_code,
"body" => response.body,
}.to_json
end
private def request
request = HTTP::Request.new(method: event.method, resource: event.path, headers: request_headers, body: event.body)
if q = event.query_params
request.query = HTTP::Params.encode(q)
end
request
end
private def process_request
output = IO::Memory.new
response = HTTP::Server::Response.new(output)
context = HTTP::Server::Context.new(request, response)
self.class.handler.call(context)
response.close
output.rewind
HTTP::Client::Response.from_io(output, decompress: false)
end
private def request_headers
headers = HTTP::Headers.new
if hdrs = event.headers
hdrs.each do |k, v|
headers.add(k, v)
end
end
headers.add("Content-Type", "application/json")
headers
end
end
loop do
response = HTTP::Client.get(%{http://#{ENV["AWS_LAMBDA_RUNTIME_API"]}/2018-06-01/runtime/invocation/next})
lambda = LambdaRequest.new(response)
HTTP::Client.post("http://#{ENV["AWS_LAMBDA_RUNTIME_API"]}/2018-06-01/runtime/invocation/#{lambda.request_id}/response", body: lambda.payload)
end
# curl https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets
# [{"id":"0","pet":"BAR"}]
# curl https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets -d "pet=Noodle"
# {"id":"1","pet":"Noodle"}
# curl https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets
# [{"id":"0","pet":"BAR"},{"id":"1","pet":"Noodle"}]
# curl -X PUT https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets/0 -d "pet=Kitty"
# {"id":"0","pet":"Kitty"}
# curl -X DELETE https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets/0
# {"id":"0","pet":"Kitty"}
# curl https://m3cl8nu27a.execute-api.ap-southeast-2.amazonaws.com/default/pets
# [{"id":"1","pet":"Noodle"}]
# You can see that Amber pipelines are run by the presence of the x-powered-by: Amber header
< HTTP/2 200
< date: Wed, 05 Dec 2018 02:03:54 GMT
< content-type: text/html
< content-length: 24
< x-amzn-requestid: 04637414-f832-11e8-8301-3748e98c690b
< x-amzn-remapped-content-length: 24
< x-amzn-remapped-connection: Keep-Alive
< x-amz-apigw-id: RaTBkH6rywMF7fg=
< x-powered-by: Amber
< x-amzn-trace-id: Root=1-5c07320a-3d765b466952731ce2e74312;Sampled=0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment