Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Application uses default HTTP Client #48

Open
shlokgilda opened this issue Mar 13, 2018 · 8 comments
Open

Application uses default HTTP Client #48

shlokgilda opened this issue Mar 13, 2018 · 8 comments

Comments

@shlokgilda
Copy link
Contributor

The application uses Go's default HTTP client. However, Go’s http package doesn’t specify request timeouts by default, allowing services to hijack our goroutines. Shouldn't we consider the use of a custom http.Client when connecting to the external APIs?

@PratikDhanave
Copy link
Member

hi @shlokgilda can share example of it. It will give more clarification.

@shlokgilda
Copy link
Contributor Author

Sure!

Issue

Go's default http.Client configures a timeout that short-circuits long-running connections. The default for this value is 0, which is interpreted as “no timeout”. Thus, if the external API service we are calling faces an outrage, the default http.Client would fail. This would cause our connection attempt to hang and they will continue to hang for as long as the malfunctioning server decides to wait. Because API calls were being made to serve user requests, this caused the goroutines serving user requests to hang as well. Once enough users hit the API servicers page, the app fell over, most likely due to resource limits being reached.

For example:

package main

import (
  “fmt”
  “net/http”
  “net/http/httptest”
  “time”
)

func main() {
  svr := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    time.Sleep(time.Hour)
  }))
  defer svr.Close()
  fmt.Println(“making request”)
  http.Get(svr.URL)
  fmt.Println(“finished request”)
}

When we run this program, it will make a request to a server that will sleep for an hour. Consequently, the program will wait for one hour and then exit.

Solution

We could define a custom http.Client with a defined timeout for our usecase.

var netClient = &http.Client{
  Timeout: time.Second * 10,
}
response, _ := netClient.Get(url)

This sets a 10 second timeout on requests made to the endpoint. If the API server exceeds the timeout, Get() will return with an error.

All in all, a malfunctioning malicious service can hang on to our connection forever, potentially starving our application.

@PratikDhanave
Copy link
Member

okay lets work on it. lets figure it out how much time we need to set as gocloud will be used production.

@shlokgilda
Copy link
Contributor Author

All right. Does this mean refactoring the previous code as well?
Also, should any further services being developed use the default client or use a custom http.Client?

@PratikDhanave
Copy link
Member

wait we need to make sure this work for all cloud providers .

@shlokgilda
Copy link
Contributor Author

All right!
I am planning to start writing code for DigitalOcean. Should I go ahead with the default http.Client or write a custom client?

@PratikDhanave
Copy link
Member

use start with default http.Client

@shlokgilda
Copy link
Contributor Author

All right. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants