func (b *Backend) Route(path string) *Path {
	result, _ := b.route(path)
	return result
}
Route looks up the path that would be used for a given path string.
package framework
import (
	"fmt"
	"io/ioutil"
	"regexp"
	"sort"
	"strings"
	"sync"
	"time"
	log "github.com/mgutz/logxi/v1"
	"github.com/hashicorp/go-multierror"
	"github.com/hashicorp/vault/helper/errutil"
	"github.com/hashicorp/vault/helper/logformat"
	"github.com/hashicorp/vault/logical"
)
type Backend struct {
	Help string
	Paths        []*Path
	PathsSpecial *logical.Paths
	Secrets []*Secret
	PeriodicFunc periodicFunc
	WALRollback       WALRollbackFunc
	WALRollbackMinAge time.Duration
	Clean CleanupFunc
	AuthRenew OperationFunc
	logger  log.Logger
	system  logical.SystemView
	once    sync.Once
	pathsRe []*regexp.Regexp
}
type periodicFunc func(*logical.Request) error
type OperationFunc func(*logical.Request, *FieldData) (*logical.Response, error)
type WALRollbackFunc func(*logical.Request, string, interface{}) error
type CleanupFunc func()
func (b *Backend) HandleExistenceCheck(req *logical.Request) (checkFound bool, exists bool, err error) {
	b.once.Do(b.init)
	switch req.Operation {
	case logical.CreateOperation:
	case logical.UpdateOperation:
	default:
		return false, false, fmt.Errorf("incorrect operation type %v for an existence check", req.Operation)
	}
	path, captures := b.route(req.Path)
	if path == nil {
		return false, false, logical.ErrUnsupportedPath
	}
	if path.ExistenceCheck == nil {
		return false, false, nil
	}
	checkFound = true
	raw := make(map[string]interface{}, len(path.Fields))
	for k, v := range req.Data {
		raw[k] = v
	}
	for k, v := range captures {
		raw[k] = v
	}
	fd := FieldData{
		Raw:    raw,
		Schema: path.Fields}
	err = fd.Validate()
	if err != nil {
		return false, false, errutil.UserError{Err: err.Error()}
	}
	exists, err = path.ExistenceCheck(req, &fd)
	return
}
func (b *Backend) HandleRequest(req *logical.Request) (*logical.Response, error) {
	b.once.Do(b.init)
	switch req.Operation {
	case logical.RenewOperation:
		fallthrough
	case logical.RevokeOperation:
		return b.handleRevokeRenew(req)
	case logical.RollbackOperation:
		return b.handleRollback(req)
	}
	if req.Path == "" && req.Operation == logical.HelpOperation {
		return b.handleRootHelp()
	}
	path, captures := b.route(req.Path)
	if path == nil {
		return nil, logical.ErrUnsupportedPath
	}
	raw := make(map[string]interface{}, len(path.Fields))
	for k, v := range req.Data {
		raw[k] = v
	}
	for k, v := range captures {
		raw[k] = v
	}
	var callback OperationFunc
	var ok bool
	if path.Callbacks != nil {
		callback, ok = path.Callbacks[req.Operation]
	}
	if !ok {
		if req.Operation == logical.HelpOperation {
			callback = path.helpCallback
			ok = true
		}
	}
	if !ok {
		return nil, logical.ErrUnsupportedOperation
	}
	fd := FieldData{
		Raw:    raw,
		Schema: path.Fields}
	if req.Operation != logical.HelpOperation {
		err := fd.Validate()
		if err != nil {
			return nil, err
		}
	}
	return callback(req, &fd)
}
func (b *Backend) SpecialPaths() *logical.Paths {
	return b.PathsSpecial
}
func (b *Backend) Setup(config *logical.BackendConfig) (logical.Backend, error) {
	b.logger = config.Logger
	b.system = config.System
	return b, nil
}
func (b *Backend) Cleanup() {
	if b.Clean != nil {
		b.Clean()
	}
}
func (b *Backend) Logger() log.Logger {
	if b.logger != nil {
		return b.logger
	}
	return logformat.NewVaultLoggerWithWriter(ioutil.Discard, log.LevelOff)
}
func (b *Backend) System() logical.SystemView {
	return b.system
}
func (b *Backend) SanitizeTTLStr(ttlStr, maxTTLStr string) (ttl, maxTTL time.Duration, err error) {
	if len(ttlStr) == 0 || ttlStr == "0" {
		ttl = 0
	} else {
		ttl, err = time.ParseDuration(ttlStr)
		if err != nil {
			return 0, 0, fmt.Errorf("Invalid ttl: %s", err)
		}
	}
	if len(maxTTLStr) == 0 || maxTTLStr == "0" {
		maxTTL = 0
	} else {
		maxTTL, err = time.ParseDuration(maxTTLStr)
		if err != nil {
			return 0, 0, fmt.Errorf("Invalid max_ttl: %s", err)
		}
	}
	ttl, maxTTL, err = b.SanitizeTTL(ttl, maxTTL)
	return
}
func (b *Backend) SanitizeTTL(ttl, maxTTL time.Duration) (time.Duration, time.Duration, error) {
	sysMaxTTL := b.System().MaxLeaseTTL()
	if ttl > sysMaxTTL {
		return 0, 0, fmt.Errorf("\"ttl\" value must be less than allowed max lease TTL value '%s'", sysMaxTTL.String())
	}
	if maxTTL > sysMaxTTL {
		return 0, 0, fmt.Errorf("\"max_ttl\" value must be less than allowed max lease TTL value '%s'", sysMaxTTL.String())
	}
	if ttl > maxTTL && maxTTL != 0 {
		ttl = maxTTL
	}
	return ttl, maxTTL, nil
}