cmd.scanConfigFromCmd   F
last analyzed

Complexity

Conditions 17

Size

Total Lines 79
Code Lines 43

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 17
eloc 43
nop 1
dl 0
loc 79
rs 1.8
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like cmd.scanConfigFromCmd often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
package cmd
2
3
import (
4
	"net/http"
5
	"net/url"
6
	"strings"
7
	"time"
8
9
	"github.com/pkg/errors"
10
	"github.com/spf13/cobra"
11
	"github.com/stefanoj3/dirstalk/pkg/scan"
12
)
13
14
const failedToReadPropertyError = "failed to read %s"
15
16
func scanConfigFromCmd(cmd *cobra.Command) (*scan.Config, error) {
17
	c := &scan.Config{}
18
19
	var err error
20
21
	c.DictionaryPath = cmd.Flag(flagScanDictionary).Value.String()
22
23
	if c.DictionaryTimeoutInMilliseconds, err = cmd.Flags().GetInt(flagScanDictionaryGetTimeout); err != nil {
24
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanDictionaryGetTimeout)
25
	}
26
27
	if c.HTTPMethods, err = cmd.Flags().GetStringSlice(flagScanHTTPMethods); err != nil {
28
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanHTTPMethods)
29
	}
30
31
	if c.HTTPStatusesToIgnore, err = cmd.Flags().GetIntSlice(flagScanHTTPStatusesToIgnore); err != nil {
32
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanHTTPStatusesToIgnore)
33
	}
34
35
	if c.Threads, err = cmd.Flags().GetInt(flagScanThreads); err != nil {
36
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanThreads)
37
	}
38
39
	if c.TimeoutInMilliseconds, err = cmd.Flags().GetInt(flagScanHTTPTimeout); err != nil {
40
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanHTTPTimeout)
41
	}
42
43
	if c.CacheRequests, err = cmd.Flags().GetBool(flagScanHTTPCacheRequests); err != nil {
44
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanHTTPCacheRequests)
45
	}
46
47
	if c.ScanDepth, err = cmd.Flags().GetInt(flagScanScanDepth); err != nil {
48
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanScanDepth)
49
	}
50
51
	socks5Host := cmd.Flag(flagScanSocks5Host).Value.String()
52
	if len(socks5Host) > 0 {
53
		if c.Socks5Url, err = url.Parse("socks5://" + socks5Host); err != nil {
54
			return nil, errors.Wrapf(err, "invalid value for %s", flagScanSocks5Host)
55
		}
56
	}
57
58
	c.UserAgent = cmd.Flag(flagScanUserAgent).Value.String()
59
60
	if c.UseCookieJar, err = cmd.Flags().GetBool(flagScanCookieJar); err != nil {
61
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanCookieJar)
62
	}
63
64
	rawCookies, err := cmd.Flags().GetStringArray(flagScanCookie)
65
	if err != nil {
66
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanCookie)
67
	}
68
69
	if c.Cookies, err = rawCookiesToCookies(rawCookies); err != nil {
70
		return nil, errors.Wrap(err, "failed to convert rawCookies to objects")
71
	}
72
73
	rawHeaders, err := cmd.Flags().GetStringArray(flagScanHeader)
74
	if err != nil {
75
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagScanHeader)
76
	}
77
78
	if c.Headers, err = rawHeadersToHeaders(rawHeaders); err != nil {
79
		return nil, errors.Wrapf(err, "failed to convert rawHeaders (%v)", rawHeaders)
80
	}
81
82
	c.Out = cmd.Flag(flagScanResultOutput).Value.String()
83
84
	c.ShouldSkipSSLCertificatesValidation, err = cmd.Flags().GetBool(flagShouldSkipSSLCertificatesValidation)
85
	if err != nil {
86
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagShouldSkipSSLCertificatesValidation)
87
	}
88
89
	c.IgnoreEmpty20xResponses, err = cmd.Flags().GetBool(flagIgnore20xWithEmptyBody)
90
	if err != nil {
91
		return nil, errors.Wrapf(err, failedToReadPropertyError, flagIgnore20xWithEmptyBody)
92
	}
93
94
	return c, nil
95
}
96
97
func rawHeadersToHeaders(rawHeaders []string) (map[string]string, error) {
98
	headers := make(map[string]string, len(rawHeaders)*2)
99
100
	for _, rawHeader := range rawHeaders {
101
		parts := strings.Split(rawHeader, ":")
102
		if len(parts) != 2 {
103
			return nil, errors.Errorf("header is in invalid format: %s", rawHeader)
104
		}
105
106
		headers[parts[0]] = parts[1]
107
	}
108
109
	return headers, nil
110
}
111
112
func rawCookiesToCookies(rawCookies []string) ([]*http.Cookie, error) {
113
	cookies := make([]*http.Cookie, 0, len(rawCookies))
114
115
	for _, rawCookie := range rawCookies {
116
		parts := strings.Split(rawCookie, "=")
117
		if len(parts) != 2 {
118
			return nil, errors.Errorf("cookie format is invalid: %s", rawCookie)
119
		}
120
121
		cookies = append(
122
			cookies,
123
			&http.Cookie{
124
				Name:    parts[0],
125
				Value:   parts[1],
126
				Expires: time.Now().AddDate(0, 0, 2),
127
			},
128
		)
129
	}
130
131
	return cookies, nil
132
}
133