Skip to content

Commit 7ada368

Browse files
committed
Enable URL liveness check for release builds
Signed-off-by: Abdulbois <abdulbois.tursunov@dsr-corporation.com>
1 parent 14ab299 commit 7ada368

6 files changed

Lines changed: 113 additions & 5 deletions

File tree

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ on:
2424
env:
2525
BIN_NAME: dcld
2626
COSMOVISOR_VERSION: 1.5.0
27+
URL_LIVENESS_CHECK_ENABLED: true
2728

2829
jobs:
2930

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ endif
1111
NAME ?= dcl
1212
APPNAME ?= $(NAME)d
1313
LEDGER_ENABLED ?= true
14-
14+
URL_LIVENESS_CHECK_ENABLED ?= true
1515
OUTPUT_DIR ?= build
1616

1717
### Process ld flags
@@ -56,6 +56,10 @@ ifeq (cleveldb,$(findstring cleveldb,$(COSMOS_BUILD_OPTIONS)))
5656
build_tags += gcc
5757
endif
5858

59+
ifeq ($(URL_LIVENESS_CHECK_ENABLED),false)
60+
build_tags += dev
61+
endif
62+
5963
whitespace :=
6064
whitespace += $(whitespace)
6165
comma := ,
@@ -110,7 +114,7 @@ go.sum: go.mod
110114
GO111MODULE=on go mod verify
111115

112116
test:
113-
go test -v $(PACKAGES)
117+
URL_LIVENESS_CHECK_ENABLED=false go test -tags=dev -v $(PACKAGES)
114118

115119
lint:
116120
golangci-lint run ./... --timeout 5m0s

internal/config/config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//go:build !dev
2+
3+
package config
4+
5+
const DisableURLLivenessCheck = false

internal/config/config_dev.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
//go:build dev
2+
3+
package config
4+
5+
const DisableURLLivenessCheck = true

utils/validator/validations.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,13 @@
1515
package validator
1616

1717
import (
18+
"net/http"
1819
"net/url"
1920
"reflect"
21+
"time"
2022

2123
"github.com/go-playground/validator/v10"
24+
"github.com/zigbee-alliance/distributed-compliance-ledger/internal/config"
2225
)
2326

2427
func requiredIfBit0Set(fl validator.FieldLevel) bool {
@@ -56,20 +59,58 @@ func isValidHttpsUrl(fl validator.FieldLevel) bool { //nolint:stylecheck
5659
return _validURL(fl, "https")
5760
}
5861

62+
var allowed4XXStatusCodes = []int{
63+
http.StatusUnauthorized,
64+
http.StatusForbidden,
65+
http.StatusUnavailableForLegalReasons,
66+
}
67+
var httpClient = &http.Client{Timeout: 10 * time.Second}
68+
5969
func _validURL(fl validator.FieldLevel, allowedSchemas ...string) bool {
6070
raw := fl.Field().String()
61-
// Field is empty or omitempty is set, skip checks
71+
// Field is empty, or omitempty is set, skip checks
6272
if raw == "" {
6373
return true
6474
}
6575

66-
u, _ := url.Parse(raw)
67-
if u.Host == "" {
76+
u, err := url.ParseRequestURI(raw)
77+
if err != nil || u.Host == "" {
6878
return false
6979
}
7080

81+
isSchemaAllowed := false
7182
for _, schema := range allowedSchemas {
7283
if u.Scheme == schema {
84+
isSchemaAllowed = true
85+
break
86+
}
87+
}
88+
89+
if _isLiveURL(u) || !isSchemaAllowed {
90+
return isSchemaAllowed
91+
}
92+
93+
return false
94+
}
95+
96+
func _isLiveURL(u *url.URL) bool {
97+
if config.DisableURLLivenessCheck {
98+
return true
99+
}
100+
101+
// HEAD request only retrieves headers, not the body
102+
resp, err := httpClient.Head(u.String())
103+
if err != nil {
104+
return false
105+
}
106+
defer resp.Body.Close()
107+
108+
if resp.StatusCode >= 200 && resp.StatusCode < 400 {
109+
return true
110+
}
111+
112+
for _, code := range allowed4XXStatusCodes {
113+
if code == resp.StatusCode {
73114
return true
74115
}
75116
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright 2020 DSR Corporation
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
//go:build !dev
16+
17+
package validator
18+
19+
import (
20+
"net/url"
21+
"testing"
22+
23+
"github.com/stretchr/testify/require"
24+
)
25+
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
36+
}
37+
38+
for _, testUrl := range negativeTests {
39+
u, err := url.ParseRequestURI(testUrl)
40+
require.NoError(t, err)
41+
42+
require.False(t, _isLiveURL(u))
43+
}
44+
45+
for _, testUrl := range positiveTests {
46+
u, err := url.ParseRequestURI(testUrl)
47+
require.NoError(t, err)
48+
49+
require.True(t, _isLiveURL(u))
50+
}
51+
52+
}

0 commit comments

Comments
 (0)