Skip to content

Commit 4fc4787

Browse files
authored
RF: headers (#49)
1 parent 579e631 commit 4fc4787

File tree

6 files changed

+76
-41
lines changed

6 files changed

+76
-41
lines changed

checks/checks.go

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
type Checks struct {
1111
Carbon *Carbon
12+
Headers *Headers
1213
IpAddress *Ip
1314
LegacyRank *LegacyRank
1415
Rank *Rank
@@ -22,6 +23,7 @@ func NewChecks() *Checks {
2223
}
2324
return &Checks{
2425
Carbon: NewCarbon(client),
26+
Headers: NewHeaders(client),
2527
IpAddress: NewIp(NewNetIp()),
2628
LegacyRank: NewLegacyRank(legacyrank.NewInMemoryStore()),
2729
Rank: NewRank(client),

checks/headers.go

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package checks
2+
3+
import (
4+
"context"
5+
"net/http"
6+
)
7+
8+
type Headers struct {
9+
client *http.Client
10+
}
11+
12+
func NewHeaders(client *http.Client) *Headers {
13+
return &Headers{client: client}
14+
}
15+
16+
func (h *Headers) List(ctx context.Context, url string) (map[string]string, error) {
17+
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
18+
if err != nil {
19+
return nil, err
20+
}
21+
22+
resp, err := h.client.Do(req)
23+
if err != nil {
24+
return nil, err
25+
}
26+
defer resp.Body.Close()
27+
28+
responseHeaders := make(map[string]string)
29+
for k, v := range resp.Header {
30+
for _, s := range v {
31+
responseHeaders[k] = s
32+
}
33+
}
34+
35+
return responseHeaders, nil
36+
}

checks/headers_test.go

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package checks
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"testing"
7+
8+
"github.com/stretchr/testify/assert"
9+
"github.com/xray-web/web-check-api/testutils"
10+
)
11+
12+
func TestList(t *testing.T) {
13+
t.Parallel()
14+
15+
c := testutils.MockClient(&http.Response{
16+
Header: http.Header{
17+
"Cache-Control": {"private, max-age=0"},
18+
"X-Xss-Protection": {"0"},
19+
},
20+
})
21+
h := NewHeaders(c)
22+
23+
actual, err := h.List(context.Background(), "example.com")
24+
assert.NoError(t, err)
25+
26+
assert.Equal(t, "private, max-age=0", actual["Cache-Control"])
27+
assert.Equal(t, "0", actual["X-Xss-Protection"])
28+
}

handlers/headers.go

+4-14
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,21 @@ package handlers
22

33
import (
44
"net/http"
5+
6+
"github.com/xray-web/web-check-api/checks"
57
)
68

7-
func HandleGetHeaders() http.Handler {
9+
func HandleGetHeaders(h *checks.Headers) http.Handler {
810
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
911
rawURL, err := extractURL(r)
1012
if err != nil {
1113
JSONError(w, ErrMissingURLParameter, http.StatusBadRequest)
1214
return
1315
}
1416

15-
resp, err := http.Get(rawURL.String())
17+
headers, err := h.List(r.Context(), rawURL.String())
1618
if err != nil {
1719
JSONError(w, err, http.StatusInternalServerError)
18-
return
19-
}
20-
defer resp.Body.Close()
21-
22-
// Copying headers from the response
23-
headers := make(map[string]interface{})
24-
for key, values := range resp.Header {
25-
if len(values) > 1 {
26-
headers[key] = values
27-
} else {
28-
headers[key] = values[0]
29-
}
3020
}
3121

3222
JSON(w, headers, http.StatusOK)

handlers/headers_test.go

+5-26
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
package handlers
22

33
import (
4-
"encoding/json"
54
"net/http"
65
"net/http/httptest"
76
"testing"
87

98
"github.com/stretchr/testify/assert"
9+
"github.com/xray-web/web-check-api/checks"
1010
)
1111

1212
func TestHandleGetHeaders(t *testing.T) {
@@ -15,45 +15,24 @@ func TestHandleGetHeaders(t *testing.T) {
1515
t.Run("url parameter is missing", func(t *testing.T) {
1616
req := httptest.NewRequest(http.MethodGet, "/headers", nil)
1717
rec := httptest.NewRecorder()
18-
HandleGetHeaders().ServeHTTP(rec, req)
18+
HandleGetHeaders(nil).ServeHTTP(rec, req)
1919

2020
assert.Equal(t, http.StatusBadRequest, rec.Code)
2121
assert.JSONEq(t, `{"error": "missing URL parameter"}`, rec.Body.String())
2222
})
2323

2424
t.Run("invalid url format", func(t *testing.T) {
25-
req := httptest.NewRequest(http.MethodGet, "/headers?url=invalid-url", nil)
26-
rec := httptest.NewRecorder()
27-
HandleGetHeaders().ServeHTTP(rec, req)
28-
29-
assert.Equal(t, http.StatusInternalServerError, rec.Code)
30-
})
31-
32-
t.Run("valid url", func(t *testing.T) {
3325
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
3426
w.Header().Set("Content-Type", "application/json")
3527
w.Header().Set("X-Custom-Header", "value")
3628
w.WriteHeader(http.StatusOK)
3729
}))
3830
defer mockServer.Close()
3931

40-
req := httptest.NewRequest(http.MethodGet, "/headers?url="+mockServer.URL, nil)
32+
req := httptest.NewRequest(http.MethodGet, "/headers?url=invalid-url", nil)
4133
rec := httptest.NewRecorder()
42-
HandleGetHeaders().ServeHTTP(rec, req)
43-
44-
assert.Equal(t, http.StatusOK, rec.Code)
45-
46-
var responseBody map[string]interface{}
47-
err := json.Unmarshal(rec.Body.Bytes(), &responseBody)
48-
assert.NoError(t, err)
34+
HandleGetHeaders(checks.NewHeaders(mockServer.Client())).ServeHTTP(rec, req)
4935

50-
expectedHeaders := map[string]interface{}{
51-
"Content-Type": "application/json",
52-
"X-Custom-Header": "value",
53-
}
54-
55-
for key, expectedValue := range expectedHeaders {
56-
assert.Equal(t, expectedValue, responseBody[key])
57-
}
36+
assert.Equal(t, http.StatusInternalServerError, rec.Code)
5837
})
5938
}

server/server.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func (s *Server) routes() {
4040
s.mux.Handle("GET /api/dnssec", handlers.HandleDnsSec())
4141
s.mux.Handle("GET /api/firewall", handlers.HandleFirewall())
4242
s.mux.Handle("GET /api/get-ip", handlers.HandleGetIP(s.checks.IpAddress))
43-
s.mux.Handle("GET /api/headers", handlers.HandleGetHeaders())
43+
s.mux.Handle("GET /api/headers", handlers.HandleGetHeaders(s.checks.Headers))
4444
s.mux.Handle("GET /api/hsts", handlers.HandleHsts())
4545
s.mux.Handle("GET /api/http-security", handlers.HandleHttpSecurity())
4646
s.mux.Handle("GET /api/legacy-rank", handlers.HandleLegacyRank(s.checks.LegacyRank))

0 commit comments

Comments
 (0)