2

I'm trying to write a test that validates the CORS for my API are setup correctly. The API is written in Go and uses GIN. I have different CORS settings depending on router group. It looks like:

router := gin.New()
router.Use(gin.Recovery())

domainOneCORS := cors.New(cors.Config{
  AllowOrigins:  []string{"https://domainone.com"},
  AllowMethods:  []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
  AllowHeaders:  []string{"Authorization", "Content-Length", "Content-Type", "Origin"},
  ExposeHeaders: []string{"Content-Length"},
  MaxAge:        12 * time.Hour,
})
domainTwoCORS := cors.New(cors.Config{
  AllowOrigins:  []string{"https://domaintwo.com"},
  AllowMethods:  []string{"GET", "POST", "PUT", "DELETE", "PATCH"},
  AllowHeaders:  []string{"Authorization", "Content-Length", "Content-Type", "Origin"},
  ExposeHeaders: []string{"Content-Length"},
  MaxAge:        12 * time.Hour,
})

domainOneAPI := router.Group("/one")
domainOneAPI.Use(domainOneCORS)
{
  domainOneAPI.GET("", handler.DomainOneHealth)
}

domainTwoAPI := router.Group("/two")
domainTwoAPI.Use(domainTwoCORS)
{
  domainTwoAPI.GET("", handler.DomainTwoHealth)
}

I'm trying to figure out the best way to test my configuration. Most tests I've found use the handler and skip the router middleware portion. Does it make sense to test it? Even if I can mock out the router and response, it's only confirming a HTTP client can hit the endpoint. Not validating a web app on a different domain is able to hit the API. I found this issue which is similar but for echo.

David Buck
  • 3,752
  • 35
  • 31
  • 35
Keith
  • 23
  • 4
  • 1
    CORS is mostly client-side. Your server only sets some headers in the response and its the client's job to block the request or not. So to test your configuration, simply check the headers present in your server responses. – SystemGlitch May 07 '20 at 21:24

1 Answers1

1

To test a CORS configuration, you can simply create an http.Client and check for headers. Since gin.Engine implements http.Handler, you can leverage httptest.Server and something like this:

func TestCors(t *testing.T) {
    r := // create your GIN router with middleware config here
    origin := // The allowed origin that you want to check

    server := httptest.NewServer(r)
    defer server.Close()

    client := &http.Client{}
    req, _ := http.NewRequest(
        "GET",
        "http://"+server.Listener.Addr().String()+"/api",
        nil,
    )
    req.Header.Add("Origin", origin)

    get, err := client.Do(req)
    if err != nil {
        t.Fatal(err)
    }

    // You should get your origin (or a * depending on your config) if the
    // passed origin is allowed.
    o := get.Header.Get("Access-Control-Allow-Origin")
    if o != origin {
        t.Errorf("Got '%s' ; expecting origin '%s'", o, origin)
    }
}

Keeping a similar testing strategy as the base, you can even write a table-test to check against multiple origins and the expected value of Access-Control-Allow-Origin.

Jay
  • 1,089
  • 12
  • 29