Configurando timeout para requisições HTTP em Golang

Por padrão Go não tem timeout para requisições HTTP, isso pode acarretar vários problemas e vulnerabilidades, por exemplo, um ataque DOS pode simplesmente abrir várias conexões com seu servidor.

Para resolver crie uma instancia da struct http.Server e preencha os campos WriteTimeout e ReadTimeout com os tempos que achar adequados.

Veja o exemplo de código.

func main() {
    r := mux.NewRouter().StrictSlash(true)
    r.HandleFunc("/", mainHandler)
    ...

    srv := &http.Server{
        Handler:      r,
        Addr:         ":8000",
        WriteTimeout: 15 * time.Second,
        ReadTimeout:  15 * time.Second,
    }

    log.Println("Listen at port :8000")
    log.Fatal(srv.ListenAndServe())
}

Isso vai definir os tempos de timeout default para todas as requisições HTTP.

Para definir o timeout para um handler especifico é bem mais complexo, uma opção é definir um contexto com timeout e usar esse contexto para evitar que demoremos demais para retornar nas chamadas internas, efetivamente cancelando consultas muito demoraras a base de dados e outros recursos.

r.Context()
ctx, cancel := context.WithTimeout(r.Context(), 5*time.Second)
defer cancel()

Particularmente eu considero uma boa pratica passar o contexto para as funções e definir um timeout, isso pode evitar o uso desnecessário de recursos caso, por exemplo, um usuário desista de uma requisição.

Cesar Gimenes