Repository: gin-gonic/gin
File: context_test.go (Go)

Code before:

	c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})

	assert.Equal(t, http.StatusCreated, w.Code)
	assert.JSONEq(t, "{\n    \"bar\": \"foo\",\n    \"foo\": \"bar\",\n    \"nested\": {\n        \"foo\": \"bar\"\n    }\n}", w.Body.String())
	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}

// Tests that no Custom JSON is rendered if code is 204
func TestContextRenderNoContentIndentedJSON(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := CreateTestContext(w)

	c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})

	assert.Equal(t, http.StatusNoContent, w.Code)
	assert.Empty(t, w.Body.String())
	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}

func TestContextClientIPWithMultipleHeaders(t *testing.T) {
	// Create a new Gin engine
	engine := New()

	// Set trusted proxies
	engine.SetTrustedProxies([]string{"127.0.0.1"})
	engine.ForwardedByClientIP = true
	engine.RemoteIPHeaders = []string{"X-Forwarded-For"}

	// Create a test request with multiple X-Forwarded-For headers
	req := httptest.NewRequest("GET", "/test", nil)
	req.Header.Add("X-Forwarded-For", "1.2.3.4, 127.0.0.1")
	req.Header.Add("X-Forwarded-For", "5.6.7.8")
	req.RemoteAddr = "127.0.0.1:1234"

	// Create response recorder
	w := httptest.NewRecorder()

	// Create context
	c, _ := CreateTestContext(w)
	c.Request = req
	c.engine = engine

	// Test ClientIP
	clientIP := c.ClientIP()

	// Should return 5.6.7.8 (the last non-trusted IP)
	expected := "5.6.7.8"
	if clientIP != expected {
		t.Errorf("Expected ClientIP to be %s, got %s", expected, clientIP)
	}

Review comment (suggestion):
```suggestion
	engine.SetTrustedProxies([]string{localhostIP})
```

Code after:

	c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})

	assert.Equal(t, http.StatusCreated, w.Code)
	assert.JSONEq(t, "{\n    \"bar\": \"foo\",\n    \"foo\": \"bar\",\n    \"nested\": {\n        \"foo\": \"bar\"\n    }\n}", w.Body.String())
	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}

// Tests that no Custom JSON is rendered if code is 204
func TestContextRenderNoContentIndentedJSON(t *testing.T) {
	w := httptest.NewRecorder()
	c, _ := CreateTestContext(w)

	c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})

	assert.Equal(t, http.StatusNoContent, w.Code)
	assert.Empty(t, w.Body.String())
	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
}

func TestContextClientIPWithMultipleHeaders(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.Request, _ = http.NewRequest(http.MethodGet, "/test", nil)

	// Multiple X-Forwarded-For headers
	c.Request.Header.Add("X-Forwarded-For", "1.2.3.4, "+localhostIP)
	c.Request.Header.Add("X-Forwarded-For", "5.6.7.8")
	c.Request.RemoteAddr = localhostIP + ":1234"

	c.engine.ForwardedByClientIP = true
	c.engine.RemoteIPHeaders = []string{"X-Forwarded-For"}
	_ = c.engine.SetTrustedProxies([]string{localhostIP})

	// Should return 5.6.7.8 (last non-trusted IP)
	assert.Equal(t, "5.6.7.8", c.ClientIP())
}

func TestContextClientIPWithSingleHeader(t *testing.T) {
	c, _ := CreateTestContext(httptest.NewRecorder())
	c.Request, _ = http.NewRequest(http.MethodGet, "/test", nil)
	c.Request.Header.Set("X-Forwarded-For", "1.2.3.4, "+localhostIP)
	c.Request.RemoteAddr = localhostIP + ":1234"

	c.engine.ForwardedByClientIP = true
	c.engine.RemoteIPHeaders = []string{"X-Forwarded-For"}
	_ = c.engine.SetTrustedProxies([]string{localhostIP})

	// Should return 1.2.3.4
	assert.Equal(t, "1.2.3.4", c.ClientIP())
}