robert-min / handson-go

Go-lang hands on guide
0 stars 0 forks source link

Chapter4. HTTP Client - 과부화 서버, Custom timout, redirect #11

Open robert-min opened 1 year ago

robert-min commented 1 year ago

과부화 상태의 서버에서 다운로드 예시

robert-min commented 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) }

robert-min commented 1 year ago

60초 지연 테스트 코드


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)
    }
}
robert-min commented 1 year ago

Custom timeout 코드


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)
}
robert-min commented 1 year ago

Custom time out test 코드


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())
    }
}
robert-min commented 1 year ago

Redirect 동작 설정

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
}