Skip to content

Commit 7584b83

Browse files
committed
Refactor
Signed-off-by: Abdulbois <abdulbois.tursunov@dsr-corporation.com>
1 parent 014001f commit 7584b83

2 files changed

Lines changed: 60 additions & 37 deletions

File tree

utils/validator/url_liveness_test.go

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,50 @@
1717
package validator
1818

1919
import (
20+
"net/http"
21+
"net/http/httptest"
2022
"net/url"
2123
"testing"
2224

2325
"github.com/stretchr/testify/require"
2426
)
2527

26-
func TestURLLivenessCheck(t *testing.T) {
27-
negativeTests := []string{
28-
"https://dcl-test.org",
29-
"https://httpbin.org/status/404",
30-
"https://httpbin.org/status/500",
31-
}
32-
positiveTests := []string{
33-
"http://github.com/", // Redirects to https://github.com/
34-
"https://httpbin.org/status/401", // Private repo
35-
"https://httpbin.org/status/403", // Unavailable for some reason
28+
func TestIsLiveURL(t *testing.T) {
29+
tests := []struct {
30+
name string
31+
statusCode int
32+
want bool
33+
}{
34+
{"200 OK", http.StatusOK, true},
35+
{"301 redirect", http.StatusMovedPermanently, true},
36+
{"401 unauthorized", http.StatusUnauthorized, true},
37+
{"403 forbidden", http.StatusForbidden, true},
38+
{"451 unavailable for legal reasons", http.StatusUnavailableForLegalReasons, true},
39+
{"404 not found", http.StatusNotFound, false},
40+
{"500 internal server error", http.StatusInternalServerError, false},
41+
{"502 bad gateway", http.StatusBadGateway, false},
3642
}
3743

38-
for _, testUrl := range negativeTests {
39-
u, err := url.ParseRequestURI(testUrl)
40-
require.NoError(t, err)
44+
for _, tt := range tests {
45+
t.Run(tt.name, func(t *testing.T) {
46+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
47+
require.Equal(t, http.MethodHead, r.Method)
48+
require.NotEmpty(t, r.Header.Get("User-Agent"))
49+
w.WriteHeader(tt.statusCode)
50+
}))
51+
defer srv.Close()
52+
53+
u, err := url.ParseRequestURI(srv.URL)
54+
require.NoError(t, err)
4155

42-
require.False(t, _isLiveURL(u))
56+
require.Equal(t, tt.want, isLiveURL(u))
57+
})
4358
}
59+
}
4460

45-
for _, testUrl := range positiveTests {
46-
u, err := url.ParseRequestURI(testUrl)
47-
require.NoError(t, err)
61+
func TestIsLiveURLUnreachable(t *testing.T) {
62+
u, err := url.ParseRequestURI("http://192.0.2.1:1")
63+
require.NoError(t, err)
4864

49-
require.True(t, _isLiveURL(u))
50-
}
65+
require.False(t, isLiveURL(u))
5166
}

utils/validator/validations.go

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -53,23 +53,27 @@ func requiredIfBit0Set(fl validator.FieldLevel) bool {
5353
}
5454

5555
func isValidHttpOrHttpsUrl(fl validator.FieldLevel) bool { //nolint:stylecheck
56-
return _validURL(fl, "http", "https")
56+
return validURL(fl, "http", "https")
5757
}
5858

5959
func isValidHttpsUrl(fl validator.FieldLevel) bool { //nolint:stylecheck
60-
return _validURL(fl, "https")
60+
return validURL(fl, "https")
6161
}
6262

6363
var allowed4XXStatusCodes = []int{
6464
http.StatusUnauthorized,
6565
http.StatusForbidden,
6666
http.StatusUnavailableForLegalReasons,
6767
}
68-
var httpClient = &http.Client{Timeout: 10 * time.Second}
6968

70-
func _validURL(fl validator.FieldLevel, allowedSchemas ...string) bool {
69+
const (
70+
livenessCheckTimeout = 10 * time.Second
71+
)
72+
73+
var httpClient = &http.Client{Timeout: livenessCheckTimeout}
74+
75+
func validURL(fl validator.FieldLevel, allowedSchemes ...string) bool {
7176
raw := fl.Field().String()
72-
// Field is empty, or omitempty is set, skip checks
7377
if raw == "" {
7478
return true
7579
}
@@ -79,28 +83,32 @@ func _validURL(fl validator.FieldLevel, allowedSchemas ...string) bool {
7983
return false
8084
}
8185

82-
isSchemaAllowed := false
83-
for _, schema := range allowedSchemas {
84-
if u.Scheme == schema {
85-
isSchemaAllowed = true
86-
87-
break
88-
}
86+
if !isSchemeAllowed(u.Scheme, allowedSchemes) {
87+
return false
8988
}
9089

91-
if _isLiveURL(u) || !isSchemaAllowed {
92-
return isSchemaAllowed
90+
return isLiveURL(u)
91+
}
92+
93+
func isSchemeAllowed(scheme string, allowed []string) bool {
94+
for _, s := range allowed {
95+
if scheme == s {
96+
return true
97+
}
9398
}
9499

95100
return false
96101
}
97102

98-
func _isLiveURL(u *url.URL) bool {
103+
func isLiveURL(u *url.URL) bool {
99104
if config.DisableURLLivenessCheck {
100105
return true
101106
}
102-
// HEAD request only retrieves headers, not the body
103-
req, err := http.NewRequestWithContext(context.Background(), http.MethodHead, u.String(), nil)
107+
108+
ctx, cancel := context.WithTimeout(context.Background(), livenessCheckTimeout)
109+
defer cancel()
110+
111+
req, err := http.NewRequestWithContext(ctx, http.MethodHead, u.String(), nil)
104112
if err != nil {
105113
return false
106114
}
@@ -111,7 +119,7 @@ func _isLiveURL(u *url.URL) bool {
111119
}
112120
defer resp.Body.Close()
113121

114-
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
122+
if resp.StatusCode >= http.StatusOK && resp.StatusCode < http.StatusBadRequest {
115123
return true
116124
}
117125

0 commit comments

Comments
 (0)