github.com/decred/politeia@v1.4.0/util/net.go (about) 1 // Copyright (c) 2017-2021 The Decred developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package util 6 7 import ( 8 "bytes" 9 "crypto/tls" 10 "crypto/x509" 11 "fmt" 12 "io" 13 "net" 14 "net/http" 15 "os" 16 "time" 17 18 pdv1 "github.com/decred/politeia/politeiad/api/v1" 19 "github.com/gorilla/schema" 20 ) 21 22 // NormalizeAddress returns addr with the passed default port appended if 23 // there is not already a port specified. 24 func NormalizeAddress(addr, defaultPort string) string { 25 _, _, err := net.SplitHostPort(addr) 26 if err != nil { 27 return net.JoinHostPort(addr, defaultPort) 28 } 29 return addr 30 } 31 32 // NewHTTPClient returns a new http Client. 33 func NewHTTPClient(skipVerify bool, certPath string) (*http.Client, error) { 34 tlsConfig := &tls.Config{ 35 InsecureSkipVerify: skipVerify, 36 } 37 38 if !skipVerify && certPath != "" { 39 cert, err := os.ReadFile(certPath) 40 if err != nil { 41 return nil, err 42 } 43 certPool, err := x509.SystemCertPool() 44 if err != nil { 45 fmt.Printf("WARN: unable to get system cert pool: %v\n", err) 46 certPool = x509.NewCertPool() 47 } 48 certPool.AppendCertsFromPEM(cert) 49 tlsConfig.RootCAs = certPool 50 } 51 52 return &http.Client{ 53 Timeout: 2 * time.Minute, 54 Transport: &http.Transport{ 55 IdleConnTimeout: 2 * time.Minute, 56 ResponseHeaderTimeout: 2 * time.Minute, 57 TLSClientConfig: tlsConfig, 58 }}, nil 59 } 60 61 // ConvertBodyToByteArray converts a response body into a byte array 62 // and optionally prints it to stdout. 63 func ConvertBodyToByteArray(r io.Reader, print bool) []byte { 64 var mw io.Writer 65 var body bytes.Buffer 66 if print { 67 mw = io.MultiWriter(&body, os.Stdout) 68 } else { 69 mw = io.MultiWriter(&body) 70 } 71 io.Copy(mw, r) 72 if print { 73 fmt.Printf("\n") 74 } 75 76 return body.Bytes() 77 } 78 79 // ParseGetParams parses the query params from the GET request into a struct. 80 // This method requires the struct type to be defined with `schema` tags. 81 func ParseGetParams(r *http.Request, dst interface{}) error { 82 err := r.ParseForm() 83 if err != nil { 84 return err 85 } 86 87 return schema.NewDecoder().Decode(dst, r.Form) 88 } 89 90 // RespBody returns the response body as a byte slice. 91 func RespBody(r *http.Response) []byte { 92 var mw io.Writer 93 var body bytes.Buffer 94 mw = io.MultiWriter(&body) 95 io.Copy(mw, r.Body) 96 return body.Bytes() 97 } 98 99 // RemoteAddr returns a string of the remote address, i.e. the address that 100 // sent the request. 101 func RemoteAddr(r *http.Request) string { 102 via := r.RemoteAddr 103 xff := r.Header.Get(pdv1.Forward) 104 if xff != "" { 105 return fmt.Sprintf("%v via %v", xff, r.RemoteAddr) 106 } 107 return via 108 }