+ // Accept PUT as a synonym for PATCH.
+ endpointPUT := route.endpoint
+ endpointPUT.Method = "PUT"
+ rtr.addRoute(endpointPUT, route.defaultOpts, route.exec)
+ }
+ }
+ rtr.mux.NotFound = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ httpserver.Errors(w, []string{"API endpoint not found"}, http.StatusNotFound)
+ })
+ rtr.mux.MethodNotAllowed = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
+ httpserver.Errors(w, []string{"API endpoint not found"}, http.StatusMethodNotAllowed)
+ })
+}
+
+func (rtr *router) addRoute(endpoint arvados.APIEndpoint, defaultOpts func() interface{}, exec routableFunc) {
+ rtr.mux.HandlerFunc(endpoint.Method, "/"+endpoint.Path, func(w http.ResponseWriter, req *http.Request) {
+ logger := ctxlog.FromContext(req.Context())
+ params, err := rtr.loadRequestParams(req, endpoint.AttrsKey)
+ if err != nil {
+ logger.WithFields(logrus.Fields{
+ "req": req,
+ "method": endpoint.Method,
+ "endpoint": endpoint,
+ }).WithError(err).Debug("error loading request params")
+ rtr.sendError(w, err)
+ return
+ }
+ opts := defaultOpts()
+ err = rtr.transcode(params, opts)
+ if err != nil {
+ logger.WithField("params", params).WithError(err).Debugf("error transcoding params to %T", opts)
+ rtr.sendError(w, err)
+ return
+ }
+ respOpts, err := rtr.responseOptions(opts)
+ if err != nil {
+ logger.WithField("opts", opts).WithError(err).Debugf("error getting response options from %T", opts)
+ rtr.sendError(w, err)
+ return