Open robert-min opened 1 year ago
func fetchRemoteResource(url string) ([]byte, error) { r, err := http.Get(url) if err != nil { return nil, err } defer r.Body.Close() return io.ReadAll(r.Body) }
func main() { if len(os.Args) != 2 { fmt.Fprintf(os.Stdout, "Must specify a HTTP URL to get data from") os.Exit(1) } body, err := fetchRemoteResource(os.Args[1]) if err != nil { fmt.Fprintf(os.Stdout, "%v\n", err) os.Exit(1) } fmt.Fprintf(os.Stdout, "%s\n", body) }
func startBadTestHTTPServer() *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// delay 60 seconds befor sending response to client
time.Sleep(60 * time.Second)
fmt.Fprint(w, "Hello World")
}))
return ts
}
func TestFetchBadRemoteResource(t *testing.T) {
ts := startBadTestHTTPServer()
defer ts.Close()
data, err := fetchRemoteResource(ts.URL)
if err != nil {
t.Fatal(err)
}
expected := "Hello World"
got := string(data)
if expected != got {
t.Errorf("Expected response to be: %s, Got: %s", expected, got)
}
}
createHTTPClientWithTimeout
함수로 client의 Timeout 설정fetchRemoteResource
에서 http로 GET 함수를 사용했던 것을 생성한 client로 GET 함수 사용하도록 수정
func fetchRemoteResource(client *http.Client, url string) ([]byte, error) {
r, err := client.Get(url)
if err != nil {
return nil, err
}
defer r.Body.Close()
return io.ReadAll(r.Body)
}
func createHTTPClientWithTimeout(d time.Duration) *http.Client {
client := http.Client{Timeout: d}
return &client
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stdout, "Must specify a HTTP URL to get data from")
os.Exit(1)
}
// set client timeout
client := createHTTPClientWithTimeout(15 * time.Second)
body, err := fetchRemoteResource(client, os.Args[1])
if err != nil {
fmt.Fprintf(os.Stdout, "%#v\n", err)
os.Exit(1)
}
fmt.Fprintf(os.Stdout, "%s\n", body)
}
shutdownServer
라는 버퍼 없는 채널을 생성하고 해당 핸들러에서 매개변수로 전달
func startBadTestHTTPServerV2(shutdownServer chan struct{}) *httptest.Server {
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
<-shutdownServer
fmt.Fprint(w, "Hello World")
}))
return ts
}
func TestFetchBadRemoteResourceV2(t *testing.T) {
shutdownServer := make(chan struct{})
ts := startBadTestHTTPServerV2(shutdownServer)
defer ts.Close()
defer func() {
shutdownServer <- struct{}{}
}()
client := createHTTPClientWithTimeout(200 * time.Millisecond)
_, err := fetchRemoteResource(client, ts.URL)
if err == nil {
t.Fatal("Expected non-nil error")
}
if !strings.Contains(err.Error(), "Client.Timeout exceeded while awaiting headers") {
t.Fatalf("Expected error to contain: Client.Timeout exceeded while awaiting headers, Got: %v", err.Error())
}
}
http.Client
객체의 CheckRedirect
필드 설정func redirectPolicyFunc(req *http.Request, via []*http.Request) error {
if len(via) >= 1 {
return errors.New(fmt.Sprintf("Attempted redirect to %s", req.URL))
}
return nil
}
func createHTTPClientWithTimeout(d time.Duration) *http.Client {
client := http.Client{
Timeout: d,
CheckRedirect: redirectPolicyFunc,
}
return &client
}
과부화 상태의 서버에서 다운로드 예시