func ExampleRoute() {
	code := `
		ajaxRouteV3: PathRegexp(/^\/api\/v3\/.*/) -> ajaxHeader("v3") -> "https://api.example.org"`

	routes, err := eskip.Parse(code)
	if err != nil {
		log.Println(err)
		return
	}

	r := routes[0]

	fmt.Println("Parsed a route:")
	fmt.Printf("id: %v\n", r.Id)
	fmt.Printf("match regexp: %s\n", r.PathRegexps[0])
	fmt.Printf("# of filters: %v\n", len(r.Filters))
	fmt.Printf("is shunt: %v\n", r.Shunt)
	fmt.Printf("backend address: \"%v\"\n", r.Backend)

	// output:
	// Parsed a route:
	// id: ajaxRouteV3
	// match regexp: ^/api/v3/.*
	// # of filters: 1
	// is shunt: false
	// backend address: "https://api.example.org"
}
Example #2
0
func (r *inlineReader) LoadAndParseAll() ([]*eskip.RouteInfo, error) {
	routes, err := eskip.Parse(r.routes)
	if err != nil {
		return nil, err
	}
	return routesToRouteInfos(routes), nil
}
Example #3
0
// Converts a set of Innkeeper route definitions to their eskip representation.
func convertJsonToEskip(data []*routeData, prependFilters, appendFilters []*eskip.Filter) ([]*eskip.Route, []string, string) {
	var (
		routes      []*eskip.Route
		deleted     []string
		lastChanged string
	)

	for _, d := range data {
		if d.Timestamp > lastChanged {
			lastChanged = d.Timestamp
		}

		if d.Action.Delete() {
			deleted = append(deleted, d.Name)
		} else {
			r, err := eskip.Parse(d.Eskip)
			if err == nil {
				for _, ri := range r {
					ri.Filters = append(prependFilters, append(ri.Filters, appendFilters...)...)
				}

				routes = append(routes, r...)
			} else {
				log.Error("error while parsing routes, innkeeper ", d.Name, err)
			}
		}
	}

	return routes, deleted, lastChanged
}
Example #4
0
func TestTeeEndToEndBody(t *testing.T) {
	shadowHandler := &MyHandler{name: "shadow"}
	shadowServer := httptest.NewServer(shadowHandler)
	shadowUrl := shadowServer.URL
	defer shadowServer.Close()

	originalHandler := &MyHandler{name: "original"}
	originalServer := httptest.NewServer(originalHandler)
	originalUrl := originalServer.URL
	defer originalServer.Close()

	routeStr := fmt.Sprintf(`route1: * -> tee("%v") -> "%v";`, shadowUrl, originalUrl)

	route, _ := eskip.Parse(routeStr)
	registry := make(filters.Registry)
	registry.Register(NewTee())
	p := proxytest.New(registry, route...)
	defer p.Close()

	testingStr := "TESTEST"
	req, _ := http.NewRequest("GET", p.URL, strings.NewReader(testingStr))
	req.Host = "www.example.org"
	req.Header.Set("X-Test", "true")
	req.Close = true
	rsp, _ := (&http.Client{}).Do(req)
	rsp.Body.Close()
	if shadowHandler.body != testingStr && originalHandler.body != testingStr {
		t.Error("Bodies are not equal")
	}
}
Example #5
0
// Creates a Client with an initial set of route definitions in eskip
// format. If parsing the eskip document fails, returns an error.
func NewDoc(doc string) (*Client, error) {
	routes, err := eskip.Parse(doc)
	if err != nil {
		return nil, err
	}

	return New(routes), nil
}
// parse a routing doc and process it to runtime routes
func docToRoutes(doc string) ([]*Route, error) {
	defs, err := eskip.Parse(doc)
	if err != nil {
		return nil, err
	}

	return processRouteDefs([]PredicateSpec{&truePredicate{}}, nil, defs), nil
}
Example #7
0
// Updates the current set of routes with new/modified and deleted
// route definitions in eskip format. In case the parsing of the
// document fails, it returns an error.
func (c *Client) UpdateDoc(upsertDoc string, deletedIds []string) error {
	routes, err := eskip.Parse(upsertDoc)
	if err != nil {
		return err
	}

	c.Update(routes, deletedIds)
	return nil
}
Example #8
0
// Parses a single route expression, fails if more than one
// expressions in the data.
func parseOne(data string) (*eskip.Route, error) {
	r, err := eskip.Parse(data)
	if err != nil {
		return nil, err
	}

	if len(r) != 1 {
		return nil, errors.New("invalid route entry: multiple route expressions")
	}

	return r[0], nil
}
Example #9
0
// Opens an eskip file and parses it, returning a DataClient implementation.
// If reading or parsing the file fails, returns an error.
func Open(path string) (*Client, error) {
	content, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}

	routes, err := eskip.Parse(string(content))
	if err != nil {
		return nil, err
	}

	return &Client{routes}, nil
}
Example #10
0
// load and parse routes from a reader (used for stdin).
func loadReader(r io.Reader) (loadResult, error) {

	// this pretty much disables continuous piping,
	// but since the reset command first upserts all
	// and deletes the diff only after, it may not
	// even be consistent to do continous piping.
	// May change in the future.
	doc, err := ioutil.ReadAll(r)
	if err != nil {
		return loadResult{}, err
	}

	routes, err := eskip.Parse(string(doc))
	return loadResult{routes: routes}, err
}
Example #11
0
func ExampleParse() {
	code := `
		PathRegexp(/\.html$/) && Header("Accept", "text/html") ->
		modPath(/\.html$/, ".jsx") ->
		requestHeader("X-Type", "page") ->
		"https://render.example.org"`

	routes, err := eskip.Parse(code)
	if err != nil {
		log.Println(err)
		return
	}

	fmt.Printf("Parsed route with backend: %s\n", routes[0].Backend)

	// output: Parsed route with backend: https://render.example.org
}
Example #12
0
func Example() {
	code := `

		// Skipper - Eskip:
		// a routing table document, containing multiple route definitions

		// route definition to a jsx page renderer

		route0:
			PathRegexp(/\.html$/) && HeaderRegexp("Accept", "text/html") ->
			modPath(/\.html$/, ".jsx") ->
			requestHeader("X-Type", "page") ->
			"https://render.example.org";
		
		route1: Path("/some/path") -> "https://backend-0.example.org"; // a simple route

		// route definition with a shunt (no backend address)
		route2: Path("/some/other/path") -> static("/", "/var/www") -> <shunt>;
		
		// route definition directing requests to an api endpoint
		route3:
			Method("POST") && Path("/api") ->
			requestHeader("X-Type", "ajax-post") ->
			"https://api.example.org"
		`

	routes, err := eskip.Parse(code)
	if err != nil {
		log.Println(err)
		return
	}

	format := "%v: [match] -> [%v filter(s) ->] <%v> \"%v\"\n"
	fmt.Println("Parsed routes:")
	for _, r := range routes {
		fmt.Printf(format, r.Id, len(r.Filters), r.Shunt, r.Backend)
	}

	// output:
	// Parsed routes:
	// route0: [match] -> [2 filter(s) ->] <false> "https://render.example.org"
	// route1: [match] -> [0 filter(s) ->] <false> "https://backend-0.example.org"
	// route2: [match] -> [1 filter(s) ->] <true> ""
	// route3: [match] -> [1 filter(s) ->] <false> "https://api.example.org"
}
Example #13
0
func (r *stdinReader) LoadAndParseAll() ([]*eskip.RouteInfo, error) {
	// this pretty much disables continuous piping,
	// but since the reset command first upserts all
	// and deletes the diff only after, it may not
	// even be consistent to do continous piping.
	// May change in the future.
	doc, err := ioutil.ReadAll(r.reader)
	if err != nil {
		return nil, err
	}

	routes, err := eskip.Parse(string(doc))

	if err != nil {
		return nil, err
	}

	return routesToRouteInfos(routes), nil
}
Example #14
0
func ExampleFilter() {
	code := `
		Method("GET") -> helloFilter("Hello, world!", 3.14) -> "https://backend.example.org"`

	routes, err := eskip.Parse(code)
	if err != nil {
		log.Println(err)
		return
	}

	f := routes[0].Filters[0]

	fmt.Println("Parsed a route with a filter:")
	fmt.Printf("filter name: %v\n", f.Name)
	fmt.Printf("filter arg 0: %v\n", f.Args[0].(string))
	fmt.Printf("filter arg 1: %v\n", f.Args[1].(float64))

	// output:
	// Parsed a route with a filter:
	// filter name: helloFilter
	// filter arg 0: Hello, world!
	// filter arg 1: 3.14
}
Example #15
0
// parse routes from a string.
func loadString(doc string) (loadResult, error) {
	routes, err := eskip.Parse(doc)
	return loadResult{routes: routes}, err
}