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:
|
info:
|
||||||
title: IronFunctions
|
title: IronFunctions
|
||||||
description: The open source serverless platform.
|
description: The open source serverless platform.
|
||||||
version: "0.1.22"
|
version: "0.1.23"
|
||||||
# the domain of the service
|
# the domain of the service
|
||||||
host: "127.0.0.1:8080"
|
host: "127.0.0.1:8080"
|
||||||
# array of all schemes that your API supports
|
# 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.
|
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
|
type: string
|
||||||
headers:
|
headers:
|
||||||
type: string
|
type: object
|
||||||
description: Map of http headers that will be sent with the response
|
description: Map of http headers that will be sent with the response
|
||||||
|
additionalProperties:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
memory:
|
memory:
|
||||||
type: integer
|
type: integer
|
||||||
format: int64
|
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
|
$ fn routes delete otherapp hello # delete route
|
||||||
/hello deleted
|
/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
|
$ fn version # shows version both of client and server
|
||||||
Client version: 0.1.0
|
Client version: 0.1.0
|
||||||
Server version: 0.1.21
|
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
|
route, thus you will be able to change any of these attributes later in time
|
||||||
if necessary.
|
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
|
## Changing target host
|
||||||
|
|
||||||
`fn` is configured by default to talk http://localhost:8080.
|
`fn` is configured by default to talk http://localhost:8080.
|
||||||
|
|||||||
@@ -24,19 +24,20 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type funcfile struct {
|
type funcfile struct {
|
||||||
App *string `yaml:"app,omitempty",json:"app,omitempty"`
|
App *string `yaml:"app,omitempty",json:"app,omitempty"`
|
||||||
Name string `yaml:"name,omitempty",json:"name,omitempty"`
|
Name string `yaml:"name,omitempty",json:"name,omitempty"`
|
||||||
Version string `yaml:"version,omitempty",json:"version,omitempty"`
|
Version string `yaml:"version,omitempty",json:"version,omitempty"`
|
||||||
Runtime *string `yaml:"runtime,omitempty",json:"runtime,omitempty"`
|
Runtime *string `yaml:"runtime,omitempty",json:"runtime,omitempty"`
|
||||||
Entrypoint *string `yaml:"entrypoint,omitempty",json:"entrypoint,omitempty"`
|
Entrypoint *string `yaml:"entrypoint,omitempty",json:"entrypoint,omitempty"`
|
||||||
Route *string `yaml:"route,omitempty",json:"route,omitempty"`
|
Route *string `yaml:"route,omitempty",json:"route,omitempty"`
|
||||||
Type *string `yaml:"type,omitempty",json:"type,omitempty"`
|
Type *string `yaml:"type,omitempty",json:"type,omitempty"`
|
||||||
Memory *int64 `yaml:"memory,omitempty",json:"memory,omitempty"`
|
Memory *int64 `yaml:"memory,omitempty",json:"memory,omitempty"`
|
||||||
Format *string `yaml:"format,omitempty",json:"format,omitempty"`
|
Format *string `yaml:"format,omitempty",json:"format,omitempty"`
|
||||||
Timeout *time.Duration `yaml:"timeout,omitempty",json:"timeout,omitempty"`
|
Timeout *time.Duration `yaml:"timeout,omitempty",json:"timeout,omitempty"`
|
||||||
MaxConcurrency *int `yaml:"int,omitempty",json:"int,omitempty"`
|
MaxConcurrency *int `yaml:"int,omitempty",json:"int,omitempty"`
|
||||||
Config map[string]string `yaml:"config,omitempty",json:"config,omitempty"`
|
Headers map[string][]string `yaml:"headers,omitempty",json:"headers,omitempty"`
|
||||||
Build []string `yaml:"build,omitempty",json:"build,omitempty"`
|
Config map[string]string `yaml:"config,omitempty",json:"config,omitempty"`
|
||||||
|
Build []string `yaml:"build,omitempty",json:"build,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ff *funcfile) FullName() string {
|
func (ff *funcfile) FullName() string {
|
||||||
|
|||||||
@@ -112,11 +112,15 @@ func (p *publishcmd) route(path string, ff *funcfile) error {
|
|||||||
|
|
||||||
body := functions.RouteWrapper{
|
body := functions.RouteWrapper{
|
||||||
Route: functions.Route{
|
Route: functions.Route{
|
||||||
Path: *ff.Route,
|
Path: *ff.Route,
|
||||||
Image: ff.FullName(),
|
Image: ff.FullName(),
|
||||||
Memory: *ff.Memory,
|
AppName: *ff.App,
|
||||||
Type_: *ff.Type,
|
Memory: *ff.Memory,
|
||||||
Config: expandEnvConfig(ff.Config),
|
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: "",
|
Value: "",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
cli.IntFlag{
|
||||||
Name: "max-concurrency,m",
|
Name: "max-concurrency",
|
||||||
Usage: "maximum concurrency for hot container",
|
Usage: "maximum concurrency for hot container",
|
||||||
Value: 1,
|
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)
|
fmt.Println(appName, wrapper.Route.Path, "removed", key)
|
||||||
return nil
|
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