func ProcessRequestFirstMatchOf(r *http.Request, keywordSets [][]string) (map[string]string, []string, error) {
	blob, err := readRequestBlob(r)
	if err != nil {
		return nil, nil, err
	}
	for _, set := range keywordSets {
		if matchKeywords(blob, set) {
			return blob, set, nil
		}
	}
	return nil, nil, errors.NewBadRequestString("no valid parameter sets found")
}
ProcessRequestFirstMatchOf reads a JSON blob for the request and returns
the first match of a set of keywords. For example, a request
might have one of the following combinations: (foo=1, bar=2), (foo=1), and (bar=2)
By giving a specific ordering of those combinations, we could decide how to accept
the request.
package api
import (
	"encoding/json"
	"io/ioutil"
	"net/http"
	"github.com/cloudflare/cfssl/errors"
	"github.com/cloudflare/cfssl/log"
)
type Handler interface {
	Handle(w http.ResponseWriter, r *http.Request) error
}
type HTTPHandler struct {
	Handler           
	Methods []string  
}
type HandlerFunc func(http.ResponseWriter, *http.Request) error
func (f HandlerFunc) Handle(w http.ResponseWriter, r *http.Request) error {
	w.Header().Set("Content-Type", "application/json")
	return f(w, r)
}
func HandleError(w http.ResponseWriter, err error) (code int) {
	if err == nil {
		return http.StatusOK
	}
	msg := err.Error()
	httpCode := http.StatusInternalServerError
	switch err := err.(type) {
	case *errors.HTTPError:
		httpCode = err.StatusCode
		code = err.StatusCode
	case *errors.Error:
		httpCode = http.StatusBadRequest
		code = err.ErrorCode
		msg = err.Message
	}
	response := NewErrorResponse(msg, code)
	jsonMessage, err := json.Marshal(response)
	if err != nil {
		log.Errorf("Failed to marshal JSON: %v", err)
	} else {
		msg = string(jsonMessage)
	}
	http.Error(w, msg, httpCode)
	return code
}
func (h HTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	var err error
	var match bool
	for _, m := range h.Methods {
		if m == r.Method {
			match = true
		}
	}
	if match {
		err = h.Handle(w, r)
	} else {
		err = errors.NewMethodNotAllowed(r.Method)
	}
	status := HandleError(w, err)
	log.Infof("%s - \"%s %s\" %d", r.RemoteAddr, r.Method, r.URL, status)
}
func readRequestBlob(r *http.Request) (map[string]string, error) {
	var blob map[string]string
	body, err := ioutil.ReadAll(r.Body)
	if err != nil {
		return nil, err
	}
	r.Body.Close()
	err = json.Unmarshal(body, &blob)
	if err != nil {
		return nil, err
	}
	return blob, nil
}
func ProcessRequestOneOf(r *http.Request, keywordSets [][]string) (map[string]string, []string, error) {
	blob, err := readRequestBlob(r)
	if err != nil {
		return nil, nil, err
	}
	var matched []string
	for _, set := range keywordSets {
		if matchKeywords(blob, set) {
			if matched != nil {
				return nil, nil, errors.NewBadRequestString("mismatched parameters")
			}
			matched = set
		}
	}
	if matched == nil {
		return nil, nil, errors.NewBadRequestString("no valid parameter sets found")
	}
	return blob, matched, nil
}