Skip to content

요청과 응답

요청 전송

패키지 함수

클라이언트를 생성할 필요 없이 직접 요청을 전송합니다:

go
result, err := httpc.Get("https://api.example.com/data")
if err != nil {
    log.Fatal(err)
}

fmt.Println(result.StatusCode())
fmt.Println(result.Body())

지원하는 HTTP 메서드: Get, Post, Put, Patch, Delete, Head, Options.

클라이언트 인스턴스

go
client, err := httpc.New()
if err != nil {
    log.Fatal(err)
}
defer client.Close()

result, err := client.Get("https://api.example.com/data")

범용 요청 메서드

go
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

result, err := httpc.Request(ctx, "GET", "https://api.example.com/data")

요청 옵션

요청 헤더

go
result, err := client.Get(url,
    httpc.WithHeader("Authorization", "Bearer token"),
    httpc.WithHeader("X-Custom", "value"),
    httpc.WithHeaderMap(map[string]string{
        "Accept":        "application/json",
        "X-Request-ID":  "123",
    }),
    httpc.WithUserAgent("my-app/1.0"),
)

요청 본문

go
// JSON
result, err := client.Post(url, httpc.WithJSON(map[string]any{
    "name": "test",
}))

// XML
result, err := client.Post(url, httpc.WithXML(data))

// 폼
result, err := client.Post(url, httpc.WithForm(map[string]string{
    "username": "admin",
    "password": "secret",
}))

// 바이너리 (기본 application/octet-stream)
result, err := client.Post(url, httpc.WithBinary(data))
// 타입 지정
result, err := client.Post(url, httpc.WithBinary(data, "image/png"))

// 자동 타입 감지
result, err := client.Post(url, httpc.WithBody(data))
// string → text/plain; charset=utf-8, []byte → application/octet-stream,
// map[string]string → application/x-www-form-urlencoded,
// *FormData → multipart/form-data, io.Reader → passed through,
// 기타 → application/json
// 명시적 지정 가능: httpc.WithBody(data, httpc.BodyJSON)

쿼리 매개변수

go
result, err := client.Get(url,
    httpc.WithQuery("page", 1),
    httpc.WithQuery("limit", 10),
)

// 또는 Map 사용
result, err := client.Get(url,
    httpc.WithQueryMap(map[string]any{
        "page":  1,
        "limit": 10,
    }),
)

인증

go
// Bearer Token
result, err := client.Get(url, httpc.WithBearerToken("my-token"))

// Basic Auth
result, err := client.Get(url, httpc.WithBasicAuth("user", "pass"))
go
result, err := client.Get(url,
    httpc.WithCookie(http.Cookie{Name: "session", Value: "abc"}),
    httpc.WithCookieMap(map[string]string{"session": "abc", "lang": "zh"}),
    httpc.WithCookieString("session=abc; lang=zh"),
)

요청 제어

go
// 타임아웃
result, err := client.Get(url, httpc.WithTimeout(10*time.Second))

// 재시도
result, err := client.Get(url, httpc.WithMaxRetries(5))

// 리다이렉트
result, err := client.Get(url,
    httpc.WithFollowRedirects(false),    // 리다이렉트 비활성화
)

WithMaxRedirects(0) 는 비활성화가 아님

WithMaxRedirects(0)는 리다이렉트를 비활성화하지 않습니다 — 엔진은 0을 "설정되지 않음"으로 간주하고 기본값 10 으로 폴백합니다. 리다이렉트 따라가기를 완전히 비활성화하려면 WithFollowRedirects(false)를 사용하세요.

콜백

go
result, err := client.Get(url,
    httpc.WithOnRequest(func(req httpc.RequestMutator) error {
        log.Printf("요청 전송: %s %s", req.Method(), req.URL())
        return nil
    }),
    httpc.WithOnResponse(func(resp httpc.ResponseMutator) error {
        log.Printf("응답 수신: %d", resp.StatusCode())
        return nil
    }),
)

응답 처리

go
result, err := client.Get("https://api.example.com/users/1")
if err != nil {
    log.Fatal(err)
}

// 상태 확인
result.StatusCode()     // 200
result.IsSuccess()      // true (2xx)
result.IsRedirect()     // false (3xx)
result.IsClientError()  // false (4xx)
result.IsServerError()  // false (5xx)

// 응답 읽기
result.Body()           // 문자열
result.RawBody()        // []byte
result.Proto()          // "HTTP/1.1"

// JSON 파싱
var user User
if err := result.Unmarshal(&user); err != nil {
    log.Fatal(err)
}

// Cookie
cookie := result.GetCookie("session")
if cookie != nil {
    fmt.Println(cookie.Value)
}

// 요청 메타데이터
fmt.Println(result.Meta.Duration)       // 요청 소요 시간
fmt.Println(result.Meta.Attempts)       // 재시도 횟수
fmt.Println(result.Meta.RedirectCount)  // 리다이렉트 횟수

컨텍스트 제어

go
// 타임아웃 제어
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
result, err := httpc.Request(ctx, "GET", url)

// 취소 제어
ctx, cancel := context.WithCancel(context.Background())
go func() {
    time.Sleep(5 * time.Second)
    cancel() // 5 초 후 취소
}()
result, err := httpc.Request(ctx, "GET", url)

스트리밍 응답

WithStreamBody(true)는 내부 메커니즘으로, 파일 다운로드 시 전체 응답 본문을 메모리에 캐시하지 않기 위해 사용됩니다. 활성화하면 응답 본문이 Result에 읽히지 않습니다 (Body()RawBody()가 빈 값을 반환).

WARNING

WithStreamBody(true)는 파일 다운로드 API 에서 내부적으로 사용됩니다. 응답 내용을 스트리밍으로 가져오려면 파일 다운로드 API를 사용하세요.

대용량 파일을 다운로드하려면 다운로드 API 를 사용하세요:

go
cfg := httpc.DefaultDownloadConfig()
cfg.FilePath = "/path/to/file"
result, err := client.Download(context.Background(), url, cfg)

응답 압축 해제

HTTPC 은 gzip, deflate 등 콘텐츠 인코딩의 압축 해제를 자동으로 처리합니다. 보안 설정을 통해 압축 해제 후 크기를 제한하여 압축 폭탄 공격을 방지할 수 있습니다:

go
cfg := httpc.DefaultConfig()
cfg.Security.MaxResponseBodySize = 10 * 1024 * 1024      // 응답 본문 상한: 스트리밍 다운로드 시 강제; 비스트리밍 시 압축 해제 후 상한의 폴백
cfg.Security.MaxDecompressedBodySize = 100 * 1024 * 1024  // 압축 해제 후 최대 100MB
설정 항목기본값설명
MaxResponseBodySize10MB스트리밍 다운로드 응답 본문 상한; 비스트리밍 시 압축 해제 후 상한의 폴백
MaxDecompressedBodySize100MB압축 해제 후 응답 본문 크기 상한

압축된 응답 본문의 바이트 수에는 별도의 100MB 하드 캡 (maxCompressedSize, 설정 불가) 이 있으며, 압축 폭탄 방어용으로 MaxResponseBodySize와 독립적으로 작동합니다.

한도를 초과하면 "exceeds limit" 정보가 포함된 오류가 반환되며, ClientError 타입으로 확인할 수 있습니다. ErrResponseBodyTooLargeResult.Unmarshal()에서 50MB JSON 크기 제한을 초과하는 응답 본문을 파싱할 때 반환됩니다 (MaxResponseBodySize와 별개).

다음 단계