[#149] Use chi instead of gorilla mux
Signed-off-by: Denis Kirillov <d.kirillov@yadro.com>
This commit is contained in:
parent
7be70243f7
commit
e30a452cdb
3 changed files with 136 additions and 3 deletions
133
api/router_filter.go
Normal file
133
api/router_filter.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type HandlerFilters struct {
|
||||
filters []Filter
|
||||
defaultHandler http.Handler
|
||||
}
|
||||
|
||||
type Filter struct {
|
||||
queries []Pair
|
||||
headers []Pair
|
||||
h http.Handler
|
||||
}
|
||||
|
||||
type Pair struct {
|
||||
Key string
|
||||
Value string
|
||||
}
|
||||
|
||||
func NewHandlerFilter() *HandlerFilters {
|
||||
return &HandlerFilters{}
|
||||
}
|
||||
|
||||
func NewFilter() *Filter {
|
||||
return &Filter{}
|
||||
}
|
||||
|
||||
func (hf *HandlerFilters) Add(filter *Filter) *HandlerFilters {
|
||||
hf.filters = append(hf.filters, *filter)
|
||||
return hf
|
||||
}
|
||||
|
||||
// HeadersMatch adds a matcher for header values.
|
||||
// It accepts a sequence of key/value pairs. Values may define variables.
|
||||
// Panics if number of parameters is not even.
|
||||
// Supports only exact matching.
|
||||
// If the value is an empty string, it will match any value if the key is set.
|
||||
func (f *Filter) HeadersMatch(pairs ...string) *Filter {
|
||||
length := len(pairs)
|
||||
if length%2 != 0 {
|
||||
panic(fmt.Errorf("filter headers: number of parameters must be multiple of 2, got %v", pairs))
|
||||
}
|
||||
|
||||
for i := 0; i < length; i += 2 {
|
||||
f.headers = append(f.headers, Pair{
|
||||
Key: pairs[i],
|
||||
Value: pairs[i+1],
|
||||
})
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Headers is similar to HeadersMatch but accept only header keys, set value to empty string internally.
|
||||
func (f *Filter) Headers(headers ...string) *Filter {
|
||||
for _, header := range headers {
|
||||
f.headers = append(f.headers, Pair{
|
||||
Key: header,
|
||||
Value: "",
|
||||
})
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (f *Filter) Handler(handler http.HandlerFunc) *Filter {
|
||||
f.h = handler
|
||||
return f
|
||||
}
|
||||
|
||||
// QueriesMatch adds a matcher for URL query values.
|
||||
// It accepts a sequence of key/value pairs. Values may define variables.
|
||||
// Panics if number of parameters is not even.
|
||||
// Supports only exact matching.
|
||||
// If the value is an empty string, it will match any value if the key is set.
|
||||
func (f *Filter) QueriesMatch(pairs ...string) *Filter {
|
||||
length := len(pairs)
|
||||
if length%2 != 0 {
|
||||
panic(fmt.Errorf("filter headers: number of parameters must be multiple of 2, got %v", pairs))
|
||||
}
|
||||
|
||||
for i := 0; i < length; i += 2 {
|
||||
f.queries = append(f.queries, Pair{
|
||||
Key: pairs[i],
|
||||
Value: pairs[i+1],
|
||||
})
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
// Queries is similar to QueriesMatch but accept only query keys, set value to empty string internally.
|
||||
func (f *Filter) Queries(queries ...string) *Filter {
|
||||
for _, query := range queries {
|
||||
f.queries = append(f.queries, Pair{
|
||||
Key: query,
|
||||
Value: "",
|
||||
})
|
||||
}
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func (hf *HandlerFilters) DefaultHandler(handler http.HandlerFunc) *HandlerFilters {
|
||||
hf.defaultHandler = handler
|
||||
return hf
|
||||
}
|
||||
|
||||
func (hf *HandlerFilters) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
LOOP:
|
||||
for _, filter := range hf.filters {
|
||||
for _, header := range filter.headers {
|
||||
hdrVals := r.Header.Values(header.Key)
|
||||
if len(hdrVals) == 0 || header.Value != "" && header.Value != hdrVals[0] {
|
||||
continue LOOP
|
||||
}
|
||||
}
|
||||
for _, query := range filter.queries {
|
||||
queryVal := r.URL.Query().Get(query.Key)
|
||||
if !r.URL.Query().Has(query.Key) || queryVal != "" && query.Value != queryVal {
|
||||
continue LOOP
|
||||
}
|
||||
}
|
||||
filter.h.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
hf.defaultHandler.ServeHTTP(w, r)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue