net http – Go program exits after a connection refused-ThrowExceptions

Exception or error:

I’m Sending get requests to websites and get the statuscodes inside a loop, when the loop sends get request to a non-exist website, it breaks the program.

go version go1.12.6 darwin/amd64

func getRequest(url string) int {

    http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}

    resp, err := http.Get(url)
    if err != nil {
        log.Fatalln(err)
    }

    defer resp.Body.Close()

    return resp.StatusCode
} 

func checker(info []accountinfo) {
    var request string
    var statusCode int

    for i := range info {
        request = fmt.Sprintf("https://%s/", info[i].domain)
        statusCode = getRequest(request)
        if statusCode == 200 {
            fmt.Println("That's ok")
        } else {
            fmt.Println(info[i].domain, "not found or content is not valid")
        }

    }
}

I expect it print “something.com not found or content is not valid”.
But it throws the error below.

2019/09/05 17:19:43 Get https://something.com/: dial tcp ip:443: connect: connection refused
exit status 1

EDIT

Using Println instead of Fatalln gives another error:

2019/09/05 17:52:18 Get https://something.com/: dial tcp ip:443: connect: connection refused
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x124eebf]

goroutine 1 [running]:
main.getRequest(0xc0000ae0e0, 0x1a, 0x0)
    /Users/ozan/monitoring-development/v2/main.go:147 +0xff
main.checker(0xc000584000, 0x8d, 0x100)
    /Users/ozan/monitoring-development/v2/main.go:110 +0xd3
main.main()
    /Users/ozan/monitoring-development/v2/main.go:67 +0x4dd
exit status 2
How to solve:

log.Fatalln, as its name implies and documentation clearly states, prints the error and exits the program. If you don’t want to exit, use log.Println instead.

Your logic for the “not found or not valid” error is based on status codes, but in order to get a status code, the request must complete. A request cannot complete to a host that doesn’t exist or refuses connections. So you need to consider two types of “failure” cases:

  1. A transport-level error, like DNS failure, connection refused/timed out, etc.
  2. A protocol-level error, like HTTP status 500, etc.

Also note that you’re treating only status 200 as success; this may be what’s intended, it may not, as the entire 2xx block of status codes are success codes (e.g. 204 No Content is a common success response).

You likely want something like this:

resp, err := http.Get(url)
if err != nil {
    log.Println(err) // Assuming you want to see what the error actually was
    return -1    // Not perfect, but at least the caller will treat it as a "non-success" status code and give your expected result
}

A better implementation would be to return the status code and an error and handle both correctly in checker.

Leave a Reply

Your email address will not be published. Required fields are marked *