diff --git a/docs/content/rc.md b/docs/content/rc.md index d3819c0a3..4c029bd60 100644 --- a/docs/content/rc.md +++ b/docs/content/rc.md @@ -229,6 +229,9 @@ If an error occurs then there will be an HTTP error status (usually 400) and the body of the response will contain a JSON encoded error object. +The sever implements basic CORS support and allows all origins for that. +The response to a preflight OPTIONS request will echo the requested "Access-Control-Request-Headers" back. + ### Using POST with URL parameters only ``` diff --git a/fs/rc/rc.go b/fs/rc/rc.go index 32e063367..cce537fb6 100644 --- a/fs/rc/rc.go +++ b/fs/rc/rc.go @@ -94,19 +94,7 @@ func (s *server) handler(w http.ResponseWriter, r *http.Request) { } } - if r.Method != "POST" { - writeError(errors.Errorf("method %q not allowed - POST required", r.Method), http.StatusMethodNotAllowed) - return - } - - // Find the call - call := registry.get(path) - if call == nil { - writeError(errors.Errorf("couldn't find method %q", path), http.StatusMethodNotAllowed) - return - } - - // Parse the POST and URL parameters into r.Form + // Parse the POST and URL parameters into r.Form, for others r.Form will be empty value err := r.ParseForm() if err != nil { writeError(errors.Wrap(err, "failed to parse form/URL parameters"), http.StatusBadRequest) @@ -119,7 +107,6 @@ func (s *server) handler(w http.ResponseWriter, r *http.Request) { in[k] = vs[len(vs)-1] } } - fs.Debugf(nil, "form = %+v", r.Form) // Parse a JSON blob from the input if r.Header.Get("Content-Type") == "application/json" { @@ -130,6 +117,45 @@ func (s *server) handler(w http.ResponseWriter, r *http.Request) { } } + fs.Debugf(nil, "form = %+v", r.Form) + + w.Header().Add("Access-Control-Allow-Origin", "*") + //echo back headers client needs + reqAccessHeaders := r.Header.Get("Access-Control-Request-Headers") + w.Header().Add("Access-Control-Allow-Headers", reqAccessHeaders) + + switch r.Method { + case "POST": + s.handlePost(w, r, path, in) + case "OPTIONS": + s.handleOptions(w, r, in) + default: + writeError(errors.Errorf("method %q not allowed - POST or OPTIONS required", r.Method), http.StatusMethodNotAllowed) + return + } +} + +func (s *server) handlePost(w http.ResponseWriter, r *http.Request, path string, in Params) { + writeError := func(err error, status int) { + fs.Errorf(nil, "rc: %q: error: %v", path, err) + w.WriteHeader(status) + err = WriteJSON(w, Params{ + "error": err.Error(), + "input": in, + }) + if err != nil { + // can't return the error at this point + fs.Errorf(nil, "rc: failed to write JSON output: %v", err) + } + } + + // Find the call + call := registry.get(path) + if call == nil { + writeError(errors.Errorf("couldn't find method %q", path), http.StatusMethodNotAllowed) + return + } + fs.Debugf(nil, "rc: %q: with parameters %+v", path, in) out, err := call.Fn(in) if err != nil { @@ -144,3 +170,6 @@ func (s *server) handler(w http.ResponseWriter, r *http.Request) { fs.Errorf(nil, "rc: failed to write JSON output: %v", err) } } +func (s *server) handleOptions(w http.ResponseWriter, r *http.Request, in Params) { + w.WriteHeader(http.StatusOK) +}