Middleware upgrade (#554)

* Adds root level middleware

* Added todo

* Better way for extensions to be added.

* Bad conflict merge?
This commit is contained in:
Travis Reeder
2017-12-05 08:22:03 -08:00
committed by GitHub
parent 9a17c79a3b
commit 0798f9fac8
23 changed files with 660 additions and 287 deletions

View File

@@ -0,0 +1,3 @@
# Docs for Contributors
* [Writing Extensions](extending.md)

View File

@@ -0,0 +1,95 @@
# Writing Extensions
Fn is extensible so you can add custom functionality and extend the project without needing to modify the core.
There are multiple ways to extend the functionality of Fn.
1. Listeners - listen to API events such as a route getting updated and react accordingly.
1. Middleware - a chain of middleware is executed before an API handler is called.
1. Add API Endpoints - extend the default Fn API.
To create an extension, there are just a couple of rules to follow.
* All config should be via ENV vars.
## Code
Your extension code needs to register itself with an `init()` method which states it's name and a function
to be called during setup:
```go
func init() {
server.RegisterExtension(&fnext.Extension{
Name: "logspam",
Setup: setup, // Fn will call this during startup
})
}
func setup(s *fnext.ExtServer) error {
// Add all the hooks you extension needs here
s.AddCallListener(&LogSpam{})
}
```
## Listeners
Listeners are the main way to extend Fn.
The following listener types are supported:
* App Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#AppListener)
* Call Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#CallListener)
### Creating a Listener
You can easily use add listeners by creating a struct with valid methods satisfying the interface
for the respective listener, adding it to `main.go` then compiling.
Example:
```go
package main
import (
"context"
"github.com/fnproject/fn/api/server"
"github.com/fnproject/fn/api/models"
)
type myCustomListener struct{}
func (c *myCustomListener) BeforeAppCreate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) AfterAppCreate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppUpdate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) AfterAppUpdate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil }
function main () {
srv := server.New(/* Here all required parameters to initialize the server */)
srv.AddAppListener(myCustomListener)
srv.Run()
}
```
## Middleware
Middleware enables you to add functionality to every API request. For every request, the chain of Middleware will be called
in order, allowing you to modify or reject requests, as well as write output and cancel the chain.
NOTES:
* middleware is responsible for writing output if it's going to cancel the chain.
See examples of this in [examples/middleware/main.go](../../examples/middleware/main.go).
## Adding API Endpoints
You can add API endpoints to the Fn server by using the `AddEndpoint` and `AddEndpointFunc` methods.
See examples of this in [examples/extensions/main.go](../../examples/extensions/main.go).

View File

@@ -1,73 +1,25 @@
# Extending Fn
# Building Custom Server with Extensions
FN is extensible so you can add custom functionality and extend the project without needing to modify the core.
You can easily add any number of extensions to Fn and then build your own custom image.
There are multiple ways to extend the functionality of Fn.
Simply create an `ext.yaml` file with the extensions you want added:
1. Listeners - listen to API events such as a route getting updated and react accordingly.
1. Middleware - a chain of middleware is executed before an API handler is called.
1. Add API Endpoints - extend the default Fn API.
## Listeners
Listeners are the main way to extend Fn.
The following listener types are supported:
* App Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#AppListener)
* Call Listeners - [GoDoc](https://godoc.org/github.com/fnproject/fn/api/server#CallListener)
### Creating a Listener
You can easily use add listeners by creating a struct with valid methods satisfying the interface
for the respective listener, adding it to `main.go` then compiling.
Example:
```
package main
import (
"context"
"github.com/fnproject/fn/api/server"
"github.com/fnproject/fn/api/models"
)
type myCustomListener struct{}
func (c *myCustomListener) BeforeAppCreate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) AfterAppCreate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppUpdate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) AfterAppUpdate(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil }
func (c *myCustomListener) BeforeAppDelete(ctx context.Context, app *models.App) error { return nil }
function main () {
srv := server.New(/* Here all required parameters to initialize the server */)
srv.AddAppListener(myCustomListener)
srv.Run()
}
```yaml
extensions:
- name: github.com/treeder/fn-ext-example/logspam
- name: github.com/treeder/fn-ext-example/logspam2
```
## Middleware
Build it:
Middleware enables you to add functionality to every API request. For every request, the chain of Middleware will be called
in order, allowing you to modify or reject requests, as well as write output and cancel the chain.
```sh
fn build-server -t imageuser/imagename
```
NOTES:
`-t` takes the same input as `docker build -t`, tagging your image.
* middleware is responsible for writing output if it's going to cancel the chain.
* cancel the chain by returning an error from your Middleware's Serve method.
Now run your new server:
See examples of this in [examples/middleware/main.go](../../examples/middleware/main.go).
## Adding API Endpoints
You can add API endpoints to the Fn server by using the `AddEndpoint` and `AddEndpointFunc` methods.
See examples of this in [examples/extensions/main.go](../../examples/extensions/main.go).
```sh
docker run --rm --name fnserver -it -v /var/run/docker.sock:/var/run/docker.sock -v $PWD/data:/app/data -p 8080:8080 imageuser/imagename
```