Given a client making a HTTP request
<!DOCTYPE html>
<html>
<body>
<script>
fetch('http://localhost:3000/messages', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ data: 'foo' })
})
.then(async response => {
console.log(await response.json());
});
</script>
</body>
</html>
The API server does not handle the request, the request handler should act as a proxy and send the request to another server
import (
"net/http"
"net/http/httputil"
"net/url"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/messages", handleRequest)
http.ListenAndServe(":3000", mux)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
targetUrl, _ := url.Parse("http://localhost:3001/messages")
proxy := httputil.NewSingleHostReverseProxy(targetUrl)
proxy.ServeHTTP(w, r)
}
The target server should handle the request and send back the response
import (
"encoding/json"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.HandleFunc("/messages", handleRequest)
http.ListenAndServe(":3001", mux)
}
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
w.WriteHeader(http.StatusOK)
json.NewEncoder(w).Encode("bar")
}
I start both servers and run the .html file, I would expect a
bar
in the console. But unfortunately I get the error
Access to fetch at 'http://localhost:3000/messages' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Does someone know how to fix this?
CodePudding user response:
You need to add a different path for handling preflight requests in your proxy. this is how your proxy should look like:
func handleRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Access-Control-Allow-Headers", "*")
w.Header().Set("Access-Control-Allow-Methods", "*")
if r.Method == "OPTIONS" {
w.WriteHeader(http.StatusOK)
return
}
targetUrl, _ := url.Parse("http://localhost:3001")
proxy := httputil.NewSingleHostReverseProxy(targetUrl)
proxy.ServeHTTP(w, r)
}
Notice the changes:
OPTION
requests(preflights) are not passed to server, you just accept them by sending aOK
status.(irrelevant to CORS problem) target url should not have
/message
part. path part is already present in your request, you should not repeat it.
Also you need to change the server code and remove these headers:
// w.Header().Set("Access-Control-Allow-Origin", "*")
// w.Header().Set("Access-Control-Allow-Headers", "*")
// w.Header().Set("Access-Control-Allow-Methods", "*")
They are already set by the proxy. Server doesn't respond to the web-browser anymore.