Code Monkey home page Code Monkey logo

gateway's Introduction

No longer maintained

This software is no longer being maintainted and should not be chosen for new projects. See this issue for more information

Apex Serverless Architecture

Apex lets you build, deploy, and manage AWS Lambda functions with ease. With Apex you can use languages that are not natively supported by AWS Lambda through the use of a Node.js shim injected into the build. A variety of workflow related tooling is provided for testing functions, rolling back deploys, viewing metrics, tailing logs, hooking into the build system and more.

This project is designed for event-driven pipelines as it does not abstract away FaaS (functions as a service). If you are building web applications, APIs, or sites, consider using Apex Up, which provides a more out-of-the-box experience for these use-cases.

Installation

On macOS, Linux, or OpenBSD run the following:

curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sh

Note that you may need to run the sudo version below, or alternatively chown /usr/local:

curl https://raw.githubusercontent.com/apex/apex/master/install.sh | sudo sh

On Windows download binary.

After downloading, rename binary file 'apex.exe', then add to PATH.

If already installed, upgrade with:

apex upgrade

Runtimes

Currently supports:

  • Node.js
  • Golang
  • Python
  • Ruby
  • Java
  • Rust
  • Clojure

Example projects for all supported runtimes can be found in _examples directory.

Features

  • Supports languages Lambda does not natively support via shim
  • Binary install (install apex quickly for continuous deployment in CI etc)
  • Hook support for running commands (transpile code, lint, dependency management, etc)
  • Batteries included but optional (opt-in to higher level abstractions)
  • Environment variable population via command-line, file, or inline config
  • Idempotent deployments (checksums skip already-deployed code)
  • Multiple environments via project.ENV.json and function.ENV.json files
  • Configuration inheritance and overrides
  • Command-line function invocation with JSON streams
  • Command & function name autocompletion
  • Function name globbing (ex: apex deploy api_*)
  • Transparently generates a zip for your deploy
  • Project bootstrapping with optional Terraform support
  • Function metrics and cost analysis
  • Ignore deploying files with .apexignore
  • Function rollback support
  • Tail function logs
  • Concurrency for quick deploys
  • Dry-run to preview changes
  • VPC support
  • Multiple region support
  • Lambda@Edge support

Sponsors

Does your company use Apex? Help keep the project bug-free and feature rich by sponsoring the project.

Backers

Love our work and community? Become a backer.

Example

Apex projects are made up of a project.json configuration file, and zero or more Lambda functions defined in the "functions" directory. Here's an example file structure:

project.json
functions
├── bar
│   ├── function.json
│   └── index.js
└── foo
    ├── function.json
    └── index.js

The project.json file defines project level configuration that applies to all functions, and defines dependencies. For this simple example the following will do:

{
  "name": "example",
  "description": "Example project"
}

Each function uses a function.json configuration file to define function-specific properties such as the runtime, amount of memory allocated, and timeout. This file is completely optional, as you can specify defaults in your project.json file. For example:

{
  "name": "bar",
  "description": "Node.js example function",
  "runtime": "nodejs4.3",
  "memory": 128,
  "timeout": 5,
  "role": "arn:aws:iam::293503197324:role/lambda"
}

Now the directory structure for your project would be:

project.json
functions
├── bar
│   └── index.js
└── foo
    └── index.js

Finally the source for the functions themselves look like this in Node.js:

console.log('start bar')
exports.handle = function(e, ctx) {
  ctx.succeed({ hello: e.name })
}

Apex operates at the project level, but many commands allow you to specify specific functions. For example you may deploy the entire project with a single command:

$ apex deploy

Or whitelist functions to deploy:

$ apex deploy foo bar

Invoke it!

$ echo '{ "name": "Tobi" }' | apex invoke bar
{ "hello": "Tobi" }

See the Documentation for more information.

Links


Build Status Slack Status GoDoc OpenCollective OpenCollective

gateway's People

Contributors

alikor avatar earthboundkid avatar fleaz avatar nobu-k avatar olivoil avatar raeesbhatti avatar tj avatar wirepair avatar wolfeidau avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gateway's Issues

Lambda - using gateway 301 error

i had added follow sameple code, zip and upload to aws lambda
but its not work for me...
Any suggestion please?


螢幕截圖 2020-09-23 下午12 48 38

螢幕截圖 2020-09-23 下午12 48 53


import (
	"fmt"
	"log"
	"net/http"
	"os"

	"github.com/apex/gateway"
)

func main() {
	http.HandleFunc("/", hello)
	log.Fatal(gateway.ListenAndServe(":3000", nil))
}

func hello(w http.ResponseWriter, r *http.Request) {
	// example retrieving values from the api gateway proxy request context.
	requestContext, ok := gateway.RequestContext(r.Context())
	if !ok || requestContext.Authorizer["sub"] == nil {
		fmt.Fprint(w, "Hello World from Go")
		return
	}

	userID := requestContext.Authorizer["sub"].(string)
	fmt.Fprintf(w, "Hello %s from Go", userID)
}

Is it possible to include assets in the binary?

Hello,

I've only just come across this library and I think it's great! I was trying to figure out how I could build some small generic tools that run directly on lambda for mostly house keeping tasks and I think this will do the trick.

I was wondering though, is it possible to use something like packr to include (a very small amount) of files within my go binary?

I've literally just done a drop in replacement for the gin app I was working on and it's deployed fine to lambda and serves my gin site but I was hoping to be able to include a couple of css, js files with this rather than hosting those in s3 or elsewhere.

1.1 release?

Hi @tj we're relying on RequestContext, which is not yet in the 1.0 release. Can you tag current master as 1.1 or something? That way we can depend on an official release tag. Thanks!

Memory usage

With gateway a single Lambda function might handle many API Gateway requests, what happens when it exceeds the allocated memory?

It seems like AWS Lambda is somewhat flexible with the amount of memory the function may use, and I assume it will then start another if the account has concurrency available?

headers don't get written if no content or status is written

The golang http server will write out on close, just in case nothing was written. Could the End() method be changed to call Write([]byte{}) so that it will trigger the headers and status OK being written?

This is using v2.0.0 of the library.

Toggle to fall back to http.ListenAndServe

Using sam local start-api is great but

  • it's slow handling requests
  • it would be nice to have the option of running code stand alone outside Lambda

I'd like to have a toggle to fall back to net/http only:

ApexGatewayDisabled := os.Getenv("APEX_GATEWAY_DISABLED")
if ApexGatewayDisabled == "true" {
	log.Fatal(http.ListenAndServe(":3000", nil))
} else {
	log.Fatal(gateway.ListenAndServe(":3000", nil))
}

Everywhere AWS specific functionality is used above condition must also be checked.

Does this approach make sense or is there a better way?

Set request.RequestURI

Request.URL is set, but not Request.RequestURI. This causes problems with certain logging middleware.

Example in the README doesn't work

Hi,

I'm trying to get apex/gateway to work, however the provided example doesn't really work:

apex ᐅ export GO111MODULE=on
apex ᐅ cat main.go
package main

import (
        "fmt"
        "log"
        "net/http"

        "github.com/apex/gateway"
        "github.com/aws/aws-lambda-go"
)

func main() {
        http.HandleFunc("/", hello)
        log.Fatal(gateway.ListenAndServe(":3000", nil))
}

func hello(w http.ResponseWriter, r *http.Request) {
        // example retrieving values from the api gateway proxy request context.
        requestContext, ok := gateway.RequestContext(r.Context())
        if !ok || requestContext.Authorizer["sub"] == nil {
                fmt.Fprint(w, "Hello World from Go")
                return
        }

        userID := requestContext.Authorizer["sub"].(string)
        fmt.Fprintf(w, "Hello %s from Go", userID)
}
apex ᐅ go build main.go
go: finding github.com/aws/aws-lambda-go/events latest
go: finding github.com/aws/aws-lambda-go/lambda latest
build command-line-arguments: cannot load github.com/aws/aws-lambda-go: cannot find module providing package github.com/aws/aws-lambda-go

Any ideas? Thanks in advance.

BR,
Victor

API gateway resource does not pass into handler

I used this dependency in my go project for lambda function and api gateway. The api gateway do invoke the lambda function, however the api call returns 404 page not found error. And in the log, the path is / instead of the /resource. Do you have any suggestions?

Actually sniff content-type on write

It would be nice if the library would sniff the content type if it's not already explicitly set rather than just using text/plain. I would be willing to work on this if you want.

This project could use some love...

I'm looking around for a lambda adapter to use with go-chi/chi...Apex Gateway looks neat, but...unloved (trying to avoid calling this "abandoned").

  • Issues left open when they could be closed
  • Unanswered questions in issues
  • PRs sitting open for months

I know one of the maintainers left $employer, but is this of interest to Apex to maintain, or maybe add some outside maintainers? Is there a popular fork of this, perhaps that I'm not aware of?

awslabs/aws-lambda-go-api-proxy is equally un-loved (including security vulns), davyzhang/agw is interesting but lacking stars. Is there some other well-maintained way that people are integrating lambda and go http routers?

Reordering query parameters.

Ideally nothing out there should rely on query parameter ordering, but lots of things do unfortunately, so the request that is build and passed in to the handler should have the original rawquery set.

Query parameters get reencoded for GET requests

When someone makes a GET request with encoded query parameters like
?phone=%2B919999999999
It is reencoded by the NewRequest function in the package to
?phone=%252B919999999999

which cannot be decoded back to the original +919999999999 resulting in issues with go's inbuilt r.URL.Query() and other functions.

How to properly use apex/gatway ?

Hello, i'm trying to migrate this Go project to lambda : https://github.com/readium/readium-lcp-server/tree/master/lcpserver

I found Apex/gateway, and it seems to be the solution. But i have few questions because my case is a bit complex and example provided doesnt help to understand how to correctly migrate.

The lcp server is divided in 3 parts:
lcpserver.go where main have the listenAndServe:

	s := lcpserver.New(":"+parsedPort, readonly, &idx, &store, &lst, &cert, packager, authenticator)
	if readonly {
		log.Println("License server running in readonly mode on port " + parsedPort)
	} else {
		log.Println("License server running on port " + parsedPort)
	}
	log.Println("Using database " + dbURI)
	log.Println("Public base URL=" + config.Config.LcpServer.PublicBaseUrl)
	log.Println("License links:")
	for nameOfLink, link := range config.Config.License.Links {
		log.Println("  " + nameOfLink + " => " + link)
	}

	if err := s.ListenAndServe(); err != nil {
		log.Println("Error " + err.Error())
	
```}

server.go in wich we have all redirection and the new above and all handlefunc:

func New(bindAddr string, readonly bool, idx *index.Index, st *storage.Store, lst *license.Store, cert *tls.Certificate, packager *pack.Packager, basicAuth *auth.BasicAuth) *Server {

sr := api.CreateServerRouter("")

s := &Server{
	Server: http.Server{
		Handler:        sr.N,
		Addr:           bindAddr,
		WriteTimeout:   240 * time.Second,
		ReadTimeout:    5 * time.Second,
		MaxHeaderBytes: 1 << 20,
	},
	readonly: readonly,
	idx:      idx,
	st:       st,
	lst:      lst,
	cert:     cert,
	source:   pack.ManualSource{},
}

// Route.PathPrefix: http://www.gorillatoolkit.org/pkg/mux#Route.PathPrefix
// Route.Subrouter: http://www.gorillatoolkit.org/pkg/mux#Route.Subrouter
// Router.StrictSlash: http://www.gorillatoolkit.org/pkg/mux#Router.StrictSlash

// methods related to EPUB encrypted content

contentRoutesPathPrefix := "/contents"
contentRoutes := sr.R.PathPrefix(contentRoutesPathPrefix).Subrouter().StrictSlash(false)

s.handleFunc(sr.R, contentRoutesPathPrefix, apilcp.ListContents).Methods("GET")

// get encrypted content by content id (a uuid)
s.handleFunc(contentRoutes, "/{content_id}", apilcp.GetContent).Methods("GET")
// get all licenses associated with a given content
s.handlePrivateFunc(contentRoutes, "/{content_id}/licenses", apilcp.ListLicensesForContent, basicAuth).Methods("GET")

if !readonly {
	// put content to the storage
	s.handlePrivateFunc(contentRoutes, "/{content_id}", apilcp.AddContent, basicAuth).Methods("PUT")
	// generate a license for given content
	s.handlePrivateFunc(contentRoutes, "/{content_id}/license", apilcp.GenerateLicense, basicAuth).Methods("POST")
	// deprecated, from a typo in the lcp server spec
	s.handlePrivateFunc(contentRoutes, "/{content_id}/licenses", apilcp.GenerateLicense, basicAuth).Methods("POST")
	// generate a licensed publication
	s.handlePrivateFunc(contentRoutes, "/{content_id}/publication", apilcp.GenerateLicensedPublication, basicAuth).Methods("POST")
	// deprecated, from a typo in the lcp server spec
	s.handlePrivateFunc(contentRoutes, "/{content_id}/publications", apilcp.GenerateLicensedPublication, basicAuth).Methods("POST")
}

// methods related to licenses

licenseRoutesPathPrefix := "/licenses"
licenseRoutes := sr.R.PathPrefix(licenseRoutesPathPrefix).Subrouter().StrictSlash(false)

s.handlePrivateFunc(sr.R, licenseRoutesPathPrefix, apilcp.ListLicenses, basicAuth).Methods("GET")
// get a license
s.handlePrivateFunc(licenseRoutes, "/{license_id}", apilcp.GetLicense, basicAuth).Methods("GET")
s.handlePrivateFunc(licenseRoutes, "/{license_id}", apilcp.GetLicense, basicAuth).Methods("POST")
// get a licensed publication via a license id
s.handlePrivateFunc(licenseRoutes, "/{license_id}/publication", apilcp.GetLicensedPublication, basicAuth).Methods("POST")
if !readonly {
	// update a license
	s.handlePrivateFunc(licenseRoutes, "/{license_id}", apilcp.UpdateLicense, basicAuth).Methods("PATCH")
}

s.source.Feed(packager.Incoming)
return s

}

and licence.go in which we have the apis, for example

// GenerateLicense generates and returns a new license,
// for a given content identified by its id
// plus a partial license given as input
func GenerateLicense(w http.ResponseWriter, r *http.Request, s Server) {

vars := mux.Vars(r)
// get the content id from the request URL
contentID := vars["content_id"]

log.Println("Generate License for content id", contentID)

// get the input body
// note: no need to create licIn / licOut here, as the input body contains
// info that we want to keep in the full license.
var lic license.License
err := DecodeJSONLicense(r, &lic)
if err != nil {
	problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusBadRequest)
	return
}
// check mandatory information in the input body
err = checkGenerateLicenseInput(&lic)
if err != nil {
	problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusBadRequest)
	return
}
// init the license with an id and issue date
license.Initialize(contentID, &lic)

// normalize the start and end date, UTC, no milliseconds
setRights(&lic)

// build the license
err = buildLicense(&lic, s)
if err != nil {
	problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusInternalServerError)
	return
}

// store the license in the db
err = s.Licenses().Add(lic)
if err != nil {
	problem.Error(w, r, problem.Problem{Detail: err.Error()}, http.StatusInternalServerError)
	//problem.Error(w, r, problem.Problem{Detail: err.Error(), Instance: contentID}, http.StatusInternalServerError)
	return
}
// set http headers
w.Header().Add("Content-Type", api.ContentType_LCP_JSON)
w.Header().Add("Content-Disposition", `attachment; filename="license.lcpl"`)
w.WriteHeader(http.StatusCreated)
// send back the license
// do not escape characters
enc := json.NewEncoder(w)
enc.SetEscapeHTML(false)
enc.Encode(lic)

// notify the lsd server of the creation of the license.
// this is an asynchronous call.
go notifyLsdServer(lic, s)

}


If i understand well how apex/gateway works, i have just to change `ListenAndServe()` in lcpserver.go and replace it by `gateway.ListenAndServe(":3000", nil)`  ?
What about API gateway ? Should i create each ressource or use as posted in some examples on internet ?
Thanks for your answer
![image](https://user-images.githubusercontent.com/11942543/111508441-00771300-874c-11eb-97de-c8603725d023.png)

Not compatible with gateway v2

This code works just fine.

package main

import (
 "context"
 "fmt"

 "github.com/aws/aws-lambda-go/lambda"
)

func HandleRequest(ctx context.Context) (string, error) {
  return fmt.Sprintf("Hello!"), nil
}

func main() {
  lambda.Start(HandleRequest)
}

When I replace it with

package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/apex/gateway"
)

func main() {

	http.HandleFunc("/", hello)

	log.Fatal(gateway.ListenAndServe(":3000", nil))
	// log.Fatal(http.ListenAndServe(":3000", nil))
}

func hello(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello!")
}

I am getting:

curl https://dqt4t5gx.execute-api.eu-central-1.amazonaws.com/
<a href="//dqt4t5gx.execute-api.eu-central-1.amazonaws.com/">Moved Permanently</a>.

Could this be because I am using the aws_apigatewayv2_api resource?
Or any other pointers?

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.