Coder Social home page Coder Social logo

agw's Introduction

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.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.