mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
fn: add header configuration to route calls (#371)
This commit is contained in:
@@ -6,7 +6,7 @@ swagger: '2.0'
|
||||
info:
|
||||
title: IronFunctions
|
||||
description: The open source serverless platform.
|
||||
version: "0.1.22"
|
||||
version: "0.1.23"
|
||||
# the domain of the service
|
||||
host: "127.0.0.1:8080"
|
||||
# array of all schemes that your API supports
|
||||
@@ -326,8 +326,12 @@ definitions:
|
||||
description: Name of Docker image to use in this route. You should include the image tag, which should be a version number, to be more accurate. Can be overridden on a per route basis with route.image.
|
||||
type: string
|
||||
headers:
|
||||
type: string
|
||||
type: object
|
||||
description: Map of http headers that will be sent with the response
|
||||
additionalProperties:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
memory:
|
||||
type: integer
|
||||
format: int64
|
||||
|
||||
20
fn/README.md
20
fn/README.md
@@ -80,6 +80,9 @@ $ fn routes create otherapp /hello iron/hello # create route
|
||||
$ fn routes delete otherapp hello # delete route
|
||||
/hello deleted
|
||||
|
||||
$ fn routes headers set otherapp hello header-name value # add HTTP header to response
|
||||
otherapp /hello headers updated header-name with value
|
||||
|
||||
$ fn version # shows version both of client and server
|
||||
Client version: 0.1.0
|
||||
Server version: 0.1.21
|
||||
@@ -126,6 +129,23 @@ Repeated calls to `fn route create` will trigger an update of the given
|
||||
route, thus you will be able to change any of these attributes later in time
|
||||
if necessary.
|
||||
|
||||
## Route headers
|
||||
|
||||
You can configure a route's HTTP response to return specific headers.
|
||||
|
||||
A header configuration workflow example:
|
||||
```sh
|
||||
$ fn routes headers set otherapp hello header-name value
|
||||
otherapp /hello headers updated header-name with value
|
||||
|
||||
$ fn routes headers view otherapp hello
|
||||
otherapp /hello headers:
|
||||
header-name: [value]
|
||||
|
||||
$ fn routes headers unset otherapp hello header-name
|
||||
otherapp /hello removed header header-name
|
||||
```
|
||||
|
||||
## Changing target host
|
||||
|
||||
`fn` is configured by default to talk http://localhost:8080.
|
||||
|
||||
@@ -35,6 +35,7 @@ type funcfile struct {
|
||||
Format *string `yaml:"format,omitempty",json:"format,omitempty"`
|
||||
Timeout *time.Duration `yaml:"timeout,omitempty",json:"timeout,omitempty"`
|
||||
MaxConcurrency *int `yaml:"int,omitempty",json:"int,omitempty"`
|
||||
Headers map[string][]string `yaml:"headers,omitempty",json:"headers,omitempty"`
|
||||
Config map[string]string `yaml:"config,omitempty",json:"config,omitempty"`
|
||||
Build []string `yaml:"build,omitempty",json:"build,omitempty"`
|
||||
}
|
||||
|
||||
@@ -114,9 +114,13 @@ func (p *publishcmd) route(path string, ff *funcfile) error {
|
||||
Route: functions.Route{
|
||||
Path: *ff.Route,
|
||||
Image: ff.FullName(),
|
||||
AppName: *ff.App,
|
||||
Memory: *ff.Memory,
|
||||
Type_: *ff.Type,
|
||||
Config: expandEnvConfig(ff.Config),
|
||||
Headers: ff.Headers,
|
||||
Timeout: int32(ff.Timeout.Seconds()),
|
||||
MaxConcurrency: int32(*ff.MaxConcurrency),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
147
fn/routes.go
147
fn/routes.go
@@ -71,7 +71,7 @@ func routes() cli.Command {
|
||||
Value: "",
|
||||
},
|
||||
cli.IntFlag{
|
||||
Name: "max-concurrency,m",
|
||||
Name: "max-concurrency",
|
||||
Usage: "maximum concurrency for hot container",
|
||||
Value: 1,
|
||||
},
|
||||
@@ -126,6 +126,34 @@ func routes() cli.Command {
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Name: "headers",
|
||||
Usage: "operate a route's header configuration",
|
||||
Subcommands: []cli.Command{
|
||||
{
|
||||
Name: "view",
|
||||
Aliases: []string{"v"},
|
||||
Usage: "view all route's headers",
|
||||
ArgsUsage: "`app` /path",
|
||||
Action: r.headersList,
|
||||
},
|
||||
{
|
||||
Name: "set",
|
||||
Aliases: []string{"s"},
|
||||
Usage: "add header to a router",
|
||||
ArgsUsage: "`app` /path <key> <value>",
|
||||
Action: r.headersSet,
|
||||
},
|
||||
{
|
||||
Name: "unset",
|
||||
Aliases: []string{"u"},
|
||||
Usage: "remove a configuration key for this route",
|
||||
ArgsUsage: "`app` /path <key>",
|
||||
Action: r.headersUnset,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -458,3 +486,120 @@ func (a *routesCmd) configUnset(c *cli.Context) error {
|
||||
fmt.Println(appName, wrapper.Route.Path, "removed", key)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *routesCmd) headersList(c *cli.Context) error {
|
||||
if c.Args().Get(0) == "" || c.Args().Get(1) == "" {
|
||||
return errors.New("error: route configuration description takes two arguments: an app name and a route")
|
||||
}
|
||||
|
||||
if err := resetBasePath(a.Configuration); err != nil {
|
||||
return fmt.Errorf("error setting endpoint: %v", err)
|
||||
}
|
||||
|
||||
appName := c.Args().Get(0)
|
||||
route := c.Args().Get(1)
|
||||
wrapper, _, err := a.AppsAppRoutesRouteGet(appName, route)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading route information: %v", err)
|
||||
}
|
||||
|
||||
if msg := wrapper.Error_.Message; msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
headers := wrapper.Route.Headers
|
||||
if len(headers) == 0 {
|
||||
return errors.New("this route has no headers")
|
||||
}
|
||||
|
||||
fmt.Println(wrapper.Route.AppName, wrapper.Route.Path, "headers:")
|
||||
w := tabwriter.NewWriter(os.Stdout, 0, 8, 1, ' ', 0)
|
||||
for k, v := range headers {
|
||||
fmt.Fprint(w, k, ":\t", v, "\n")
|
||||
}
|
||||
w.Flush()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *routesCmd) headersSet(c *cli.Context) error {
|
||||
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
|
||||
return errors.New("error: route configuration setting takes four arguments: an app name, a route, a key and a value")
|
||||
}
|
||||
|
||||
if err := resetBasePath(a.Configuration); err != nil {
|
||||
return fmt.Errorf("error setting endpoint: %v", err)
|
||||
}
|
||||
|
||||
appName := c.Args().Get(0)
|
||||
route := c.Args().Get(1)
|
||||
key := c.Args().Get(2)
|
||||
value := c.Args().Get(3)
|
||||
|
||||
wrapper, _, err := a.AppsAppRoutesRouteGet(appName, route)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading route: %v", err)
|
||||
}
|
||||
|
||||
if msg := wrapper.Error_.Message; msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
headers := wrapper.Route.Headers
|
||||
|
||||
if headers == nil {
|
||||
headers = make(map[string][]string)
|
||||
}
|
||||
|
||||
headers[key] = append(headers[key], value)
|
||||
wrapper.Route.Headers = headers
|
||||
|
||||
if _, _, err := a.AppsAppRoutesRoutePut(appName, route, *wrapper); err != nil {
|
||||
return fmt.Errorf("error updating route configuration: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(wrapper.Route.AppName, wrapper.Route.Path, "headers updated", key, "with", value)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *routesCmd) headersUnset(c *cli.Context) error {
|
||||
if c.Args().Get(0) == "" || c.Args().Get(1) == "" || c.Args().Get(2) == "" {
|
||||
return errors.New("error: route configuration setting takes four arguments: an app name, a route and a key")
|
||||
}
|
||||
|
||||
if err := resetBasePath(a.Configuration); err != nil {
|
||||
return fmt.Errorf("error setting endpoint: %v", err)
|
||||
}
|
||||
|
||||
appName := c.Args().Get(0)
|
||||
route := c.Args().Get(1)
|
||||
key := c.Args().Get(2)
|
||||
|
||||
wrapper, _, err := a.AppsAppRoutesRouteGet(appName, route)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading app: %v", err)
|
||||
}
|
||||
|
||||
if msg := wrapper.Error_.Message; msg != "" {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
headers := wrapper.Route.Headers
|
||||
|
||||
if headers == nil {
|
||||
headers = make(map[string][]string)
|
||||
}
|
||||
|
||||
if _, ok := headers[key]; !ok {
|
||||
return fmt.Errorf("configuration key %s not found", key)
|
||||
}
|
||||
|
||||
delete(headers, key)
|
||||
wrapper.Route.Headers = headers
|
||||
|
||||
if _, _, err := a.AppsAppRoutesRoutePut(appName, route, *wrapper); err != nil {
|
||||
return fmt.Errorf("error updating route configuration: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println(wrapper.Route.AppName, wrapper.Route.Path, "removed header", key)
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user