All Projects β†’ davyzhang β†’ agw

davyzhang / agw

Licence: other
Route AWS APIGateway to lambda with standard router such as mux

Programming Languages

go
31211 projects - #10 most used programming language

Projects that are alternatives of or similar to agw

Upic
πŸ“€uPic is a native, powerful, beautiful and simple picture and file upload tool for macOS.
Stars: ✭ 2,465 (+10170.83%)
Mutual labels:  amazon
Utern
Multi group and stream log tailing for AWS CloudWatch Logs.
Stars: ✭ 241 (+904.17%)
Mutual labels:  amazon
privacy-settings
Guide to privacy settings for most major softwares and services.
Stars: ✭ 97 (+304.17%)
Mutual labels:  amazon
Knative Lambda Runtime
Running AWS Lambda Functions on Knative/Kubernetes Clusters
Stars: ✭ 201 (+737.5%)
Mutual labels:  amazon
Major Scrapy Spiders
Scrapy spiders of major websites. Google Play Store, Facebook, Instagram, Ebay, YTS Movies, Amazon
Stars: ✭ 223 (+829.17%)
Mutual labels:  amazon
Laravel Aws Eb
Ready-to-deploy configuration to run Laravel on AWS Elastic Beanstalk.
Stars: ✭ 247 (+929.17%)
Mutual labels:  amazon
Lector
An API for your Kindle data
Stars: ✭ 177 (+637.5%)
Mutual labels:  amazon
scripts
Scripts for managing my Ubuntu / Rclone / Plex Server
Stars: ✭ 20 (-16.67%)
Mutual labels:  amazon
S3sync
Really fast sync tool for S3
Stars: ✭ 224 (+833.33%)
Mutual labels:  amazon
amazon-ecs
With Laravel, search and lookup Amazon products easily.
Stars: ✭ 52 (+116.67%)
Mutual labels:  amazon
Alexaskillskit.net
.NET library that simplifies Alexa skills development; same object model as Amazon's AlexaSkillsKit for Java
Stars: ✭ 210 (+775%)
Mutual labels:  amazon
Homeassistant Config
Stars: ✭ 211 (+779.17%)
Mutual labels:  amazon
Alfred Web Search Suggest
Alfred search suggest workflow for various popular websites.
Stars: ✭ 249 (+937.5%)
Mutual labels:  amazon
Aws Lambda Fastify
Insipired by aws-serverless-express to work with Fastify with inject functionality.
Stars: ✭ 190 (+691.67%)
Mutual labels:  amazon
bam
Official Github repository of BAM!
Stars: ✭ 19 (-20.83%)
Mutual labels:  aws-apigateway
Home Assistant
Home-Assistant-Config
Stars: ✭ 182 (+658.33%)
Mutual labels:  amazon
Go Alexa
A collection of Amazon Echo / Alexa tools for Go development.
Stars: ✭ 245 (+920.83%)
Mutual labels:  amazon
google-aws-federator
A small command line tool to help manage AWS Federated Identities authenticated through Google Apps
Stars: ✭ 29 (+20.83%)
Mutual labels:  amazon
node-red-contrib-sonospollytts
Play speech TTS using Sonos.
Stars: ✭ 11 (-54.17%)
Mutual labels:  amazon
Alfred Searchio
Alfred workflow to auto-suggest search results from multiple search engines and languages.
Stars: ✭ 250 (+941.67%)
Mutual labels:  amazon

Route AWS APIGateway Requests with ease

AGW transforms AWS lambda event message to the standard http.Request which can make it easy to work with the existing http routers and chaining libraries. With AWS's native support for golang wrapper, shims like nodejs or python is no longer needed.

In short, the usage is

//your standard http handler
func testhandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("test", "test header")
    w.(*agw.LPResponse).WriteBody(map[string]string{
        "test":    "test body",
        "funcArn": agw.LambdaContext.InvokedFunctionArn, //can access context as global variable
        "event":   string(agw.RawMessage),               //can access RawMessage as global variable
    }, false)
}

func main() {
    //use any exsiting router supporting the standard http.Handler
    //like 	"github.com/gorilla/mux"
    mux := mux.NewRouter()
    mux.HandleFunc("/test1/hello", testhandler)
    //lambda is from official sdk "https://github.com/aws/aws-lambda-go"
    lambda.Start(agw.Handler(mux))
}

The Full Picture

To use it in the real project it might need some more setups

  1. AWS APIGateway must be configured with lambda proxy mode, typically {/proxy+} here's the doc from aws
  2. Using any http router such as lightning fast Bone or popular and feature rich Gorilla Mux and even with chaining libraries like Alice to write your middlewares

A complex example

You can deploy this code to aws lambda and link it to apigateway to see how it works in the test console of aws apigateway.

func handler1(w http.ResponseWriter, r *http.Request) {
    p1 := bone.GetValue(r, "var")
    bd := string(r.Context().Value(agw.ContextKeyBody).([]byte))
    w.(*agw.LPResponse).WriteBody(map[string]string{
        "agent": r.UserAgent(),
        "var":   p1,
        "bd":    bd,
    }, false)
}

func main() {
    mux := bone.New()
    cors := alice.New(agw.Logging, agw.EnableCORS, agw.ParseBodyBytes)
    mux.Post("/test1/:var", cors.ThenFunc(handler1))

    lambda.Start(func() agw.GatewayHandler {
        return func(ctx context.Context, event json.RawMessage) (interface{}, error) {
            //might be useful to store ctx and event as global variable here
            agp := agw.NewAPIGateParser(event)
            lctx, _ := lambdacontext.FromContext(ctx)
            //deal with the different ctx and event,such as connecting to different db endpoint
            //or setting up global variables
            log.Printf("init here with method %s, req ctx: %+v", agp.Method(), lctx)
            return agw.Process(agp, mux), nil
        }
    }())
} 

Support both standard http server and the lambda environment

It is a common scenario that debugging programs with local servers. However, aws lambda and apigateway have limited this possibility. We must upload the code and wait for the logs coming out in the cloudwatch, which is slow and inconvenient. This library provides a little wrapper func to write back data that can help to identify the real type of http.ResponseWriter and invoke corresponding write function.

func handlerTest(w http.ResponseWriter, r *http.Request) { //you can pass this handler to a standard local http server
    //your code...
    agw.WriteResponse(w, ret, false) //corresponding Write function will be invoked
})

Firstly, build the standard http router

func buildMux() http.Handler {
	mux := bone.New()
	cors := alice.New(agw.Logging, agw.EnableCORS)
    mux.Get("/test", cors.ThenFunc(handlerTest))
    mux.Options("/*", cors.ThenFunc(handlerDummy)) //handle option requests to support POST/PATCH.. requests
}

Typically, there are 2 entry points, one for local or standard server which looks like this:

func DevHTTPEntry() {
	srv := &http.Server{
		Handler:      buildMux(),
		Addr:         "localhost:9090",
		WriteTimeout: 15 * time.Second,
		ReadTimeout:  15 * time.Second,
	}
	log.Fatal(srv.ListenAndServe())
}

and there's another one for lambda:

func LambdaHTTPEntry() {
	lambda.Start(func() agw.GatewayHandler {
		return func(ctx context.Context, event json.RawMessage) (interface{}, error) {
			agp := agw.NewAPIGateParser(event)
			return agw.Process(agp, buildMux()), nil
		}
	}())
}

then switch them according to the environment variable

func HTTPEntry() {
	plat, ok := os.LookupEnv("APP_PLATFORM")
	if !ok || plat != "Lambda" {
		DevHTTPEntry()
	} else {
		LambdaHTTPEntry()
	}
}

Notes

  • The ResponseWriter.Write([]byte) (int, error) is not going to work as normal http response due to the way how lambda and aws apigateway work
  • You need to type assert ResponseWriter as (*agw.LPResponse) and use WriteBody(out, false|true) to set the return body
  • Information about aws's base64 support is here
 func MyHandler(w http.ResponseWriter, r *http.Request) {
    //your logic ....
    w.(*agw.LPResponse).WriteBody(out, false)//false|true indicates whether the body is encoded with base64 or not
}

License

BSD licensed. See the LICENSE file for details.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].