* api/router/registry: extract path based parameters from url to req * api/handler/rpc: fix empty body request parsing * bundle grpc-gateway util funcs Signed-off-by: Vasiliy Tolstov <v.tolstov@unistack.org>
		
			
				
	
	
		
			116 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			116 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package util
 | |
| 
 | |
| // download from https://raw.githubusercontent.com/grpc-ecosystem/grpc-gateway/master/protoc-gen-grpc-gateway/httprule/compile.go
 | |
| 
 | |
| const (
 | |
| 	opcodeVersion = 1
 | |
| )
 | |
| 
 | |
| // Template is a compiled representation of path templates.
 | |
| type Template struct {
 | |
| 	// Version is the version number of the format.
 | |
| 	Version int
 | |
| 	// OpCodes is a sequence of operations.
 | |
| 	OpCodes []int
 | |
| 	// Pool is a constant pool
 | |
| 	Pool []string
 | |
| 	// Verb is a VERB part in the template.
 | |
| 	Verb string
 | |
| 	// Fields is a list of field paths bound in this template.
 | |
| 	Fields []string
 | |
| 	// Original template (example: /v1/a_bit_of_everything)
 | |
| 	Template string
 | |
| }
 | |
| 
 | |
| // Compiler compiles utilities representation of path templates into marshallable operations.
 | |
| // They can be unmarshalled by runtime.NewPattern.
 | |
| type Compiler interface {
 | |
| 	Compile() Template
 | |
| }
 | |
| 
 | |
| type op struct {
 | |
| 	// code is the opcode of the operation
 | |
| 	code OpCode
 | |
| 
 | |
| 	// str is a string operand of the code.
 | |
| 	// operand is ignored if str is not empty.
 | |
| 	str string
 | |
| 
 | |
| 	// operand is a numeric operand of the code.
 | |
| 	operand int
 | |
| }
 | |
| 
 | |
| func (w wildcard) compile() []op {
 | |
| 	return []op{
 | |
| 		{code: OpPush},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (w deepWildcard) compile() []op {
 | |
| 	return []op{
 | |
| 		{code: OpPushM},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (l literal) compile() []op {
 | |
| 	return []op{
 | |
| 		{
 | |
| 			code: OpLitPush,
 | |
| 			str:  string(l),
 | |
| 		},
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func (v variable) compile() []op {
 | |
| 	var ops []op
 | |
| 	for _, s := range v.segments {
 | |
| 		ops = append(ops, s.compile()...)
 | |
| 	}
 | |
| 	ops = append(ops, op{
 | |
| 		code:    OpConcatN,
 | |
| 		operand: len(v.segments),
 | |
| 	}, op{
 | |
| 		code: OpCapture,
 | |
| 		str:  v.path,
 | |
| 	})
 | |
| 
 | |
| 	return ops
 | |
| }
 | |
| 
 | |
| func (t template) Compile() Template {
 | |
| 	var rawOps []op
 | |
| 	for _, s := range t.segments {
 | |
| 		rawOps = append(rawOps, s.compile()...)
 | |
| 	}
 | |
| 
 | |
| 	var (
 | |
| 		ops    []int
 | |
| 		pool   []string
 | |
| 		fields []string
 | |
| 	)
 | |
| 	consts := make(map[string]int)
 | |
| 	for _, op := range rawOps {
 | |
| 		ops = append(ops, int(op.code))
 | |
| 		if op.str == "" {
 | |
| 			ops = append(ops, op.operand)
 | |
| 		} else {
 | |
| 			if _, ok := consts[op.str]; !ok {
 | |
| 				consts[op.str] = len(pool)
 | |
| 				pool = append(pool, op.str)
 | |
| 			}
 | |
| 			ops = append(ops, consts[op.str])
 | |
| 		}
 | |
| 		if op.code == OpCapture {
 | |
| 			fields = append(fields, op.str)
 | |
| 		}
 | |
| 	}
 | |
| 	return Template{
 | |
| 		Version:  opcodeVersion,
 | |
| 		OpCodes:  ops,
 | |
| 		Pool:     pool,
 | |
| 		Verb:     t.verb,
 | |
| 		Fields:   fields,
 | |
| 		Template: t.template,
 | |
| 	}
 | |
| }
 |