2

I'm implementing REST API's in Go and for that I want to allow cross origin requests to be served.

What I am currently doing:

Go server code:

//handleCrossO ... This function will handle CROS
func handleCrossO(w *http.ResponseWriter) {
(*w).Header().Set("Content-Type", "application/json")
(*w).Header().Set("Access-Control-Allow-Origin", "*")
(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, 
     OPTIONS, PUT, DELETE")
(*w).Header().Set("Access-Control-Allow-Headers", "Accept, 
     Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, 
     Authorization, Auth")
}

//Response ... This function will create response
func Response(w http.ResponseWriter, message string, statusCode int) 
{
handleCrossO(&w)
w.WriteHeader(statusCode)
w.Write([]byte("{\"message\":\"" + message + "\"}"))
}

I am getting the following error on browser console:

Access to XMLHttpRequest at 'http://ip:8080/config' from origin 'http://ip:4200' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I have also tried the following code to check OPTIONS method:

// CheckAuthorization function check if the User is autrhorized to make calls or not
// if ssid is mising then give unauthorized error otherwise call next
func CheckAuthorization(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
    if r.Method == "OPTIONS" {
        //handle preflight in here
        response.Response(w, "success", 200)
    }else {
            store := session.SessionStore()
        session, _ := store.Get(r, utils.SessionName)
        ssid := r.Header.Get("Auth")
        if _, ok := session.Values[ssid]; ok {
            next.ServeHTTP(w, r)
        } else {
        var getTokenRes = GetTokenRes{}
        sendResponse(w, getTokenRes, 1, "Invalid 
                     SSID", 400)
        }
    }

}
}

But it is not working.

I have also tried allow OPTIONS method:

router.HandleFunc("/network", authmiddleware.CheckAuthorization(createConfiguration)).Methods("POST", "OPTIONS")
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Aman Jain
  • 59
  • 6
  • I had issues with CORS and i implemented my own library. But it did not work. Chrome kept blocking mine. I used https://github.com/rs/cors and it it did the job for me. Also I was creating cookies from server side. Unless you have https or same origins server side cookies will not be accepted by chrome. However you can create cookie from the client. – Prajval M Dec 31 '18 at 08:35
  • my code for CORS https://github.com/26prajval98/GetMaid-Server/blob/master/src/GetMaid/handlers/middlewares/enableCORS.go – Prajval M Dec 31 '18 at 08:39
  • You seem to be using gorilla/mux, if that's the case I'd recommend you use their [CORS](http://www.gorillatoolkit.org/pkg/handlers#CORS) middleware with the [AllowedOrigins option](http://www.gorillatoolkit.org/pkg/handlers#AllowedOrigins) passing in `"*"` and if that doesn't work, then passing in a list of the allowed origins, eg `"http://ip:4200", "http://ip:8080", ...`. – mkopriva Dec 31 '18 at 09:29
  • ... and also take a look at this [SO question](https://stackoverflow.com/questions/40985920/making-golang-gorilla-cors-handler-work), you may find the answers useful. – mkopriva Dec 31 '18 at 09:31
  • @mkopriva I have already tried that way but still not my problem is not resolved. – Aman Jain Dec 31 '18 at 10:56
  • You're passing a pointer to an interface `w *http.ResponseWriter` which is almost never the behavior you want, and is why your code is littered with `(*w).MethodCall` junk. Consider changing it to accept a parameter `w http.ResponseWriter` like every other function that takes a `ResponseWriter`. – Adrian Dec 31 '18 at 14:23

1 Answers1

2

Preflight request should return success and headers. Try to use like following

func setupResponse(w *http.ResponseWriter, req *http.Request) {
    (*w).Header().Set("Access-Control-Allow-Origin", "*")
    (*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
    (*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

func indexHandler(w http.ResponseWriter, req *http.Request) {
    setupResponse(&w, req)
    if (*req).Method == "OPTIONS" {
        return
    }

    // process the request...
}

Also you can use https://github.com/rs/cors

package main

import (
    "net/http"

    "github.com/rs/cors"
)

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Content-Type", "application/json")
        w.Write([]byte("{\"hello\": \"world\"}"))
    })

    // cors.Default() setup the middleware with default options being
    // all origins accepted with simple methods (GET, POST). See
    // documentation below for more options.
    handler := cors.Default().Handler(mux)
    http.ListenAndServe(":8080", handler)
}
Maxim
  • 2,233
  • 6
  • 16