What I want to achieve here is to create a very generic middleware called, Expects
that actually validates the current request according to the parameters provided. It will raise a Bad Request
if the required params are not present or are empty. In Python (Flask) this would be very simple like:
@app.route('/endpoint', methods=['POST'])
@expects(['param1', 'param2'])
def endpoint_handler():
return 'Hello World'
The definition of expects
would look like this (a very minimal example):
def expects(fields):
def decorator(view_function):
@wraps(view_function)
def wrapper(*args, **kwargs):
# get current request data
data = request.get_json(silent=True) or {}
for f in fields:
if f not in data.keys():
raise Exception("Bad Request")
return view_function(*args, **kwargs)
return wrapper
return decorator
I am just confused a little about how would I achieve that in Go. What I tried so far is:
type RequestParam interface {
Validate() (bool, error)
}
type EndpointParamsRequired struct {
SomeParam string `json:"some_param"`
}
func (p *EndpointParamsRequired) Validate() {
// My validation logic goes here
if len(p.SomeParam) == 0 {
return false, "Missing field"
}
}
func Expects(p RequestParam, h http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// Check if present in JSON request
// Unmarshall JSON
...
if _, err := p.Validate(); err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "Bad request: %s", err)
return
}
}
}
and from main.go
file:
func main() {
var (
endopintParams EndpointParamsRequired
)
r.HandleFunc("/endpoint", Expects(&endopintParams, EndpointHandler)).Methods("POST")
}
It actually works for the first time and validates the request, but after one valid request all the consecutive requests are successful even if the json does not contain the required param. Does that have anything to do with the global endopintParams
I'm creating?