요청 옵션
요청 옵션은 함수형 설정 항목으로, RequestOption 타입을 통해 요청 메서드에 전달하여 세밀한 요청 제어를 구현합니다.
result, err := client.Post(url,
httpc.WithJSON(data),
httpc.WithBearerToken(token),
httpc.WithQuery("page", 1),
)모든 옵션은 자유롭게 조합할 수 있으며, 전달된 순서대로 적용됩니다.
요청 헤더
WithHeader
func WithHeader(key, value string) RequestOption단일 요청 헤더를 설정합니다. 키와 값은 보안 검증을 거칩니다 (CRLF 주입 방지).
result, err := client.Get(url,
httpc.WithHeader("X-Custom", "value"),
)WithHeaderMap
func WithHeaderMap(headers map[string]string) RequestOption요청 헤더를 일괄 설정합니다.
result, err := client.Get(url,
httpc.WithHeaderMap(map[string]string{
"Accept": "application/json",
"X-Request-ID": "abc123",
}),
)WithUserAgent
func WithUserAgent(userAgent string) RequestOptionUser-Agent 헤더를 설정합니다. WithHeader("User-Agent", ...)의 편의 래퍼입니다.
인증
WithBasicAuth
func WithBasicAuth(username, password string) RequestOptionHTTP Basic 인증을 설정합니다. 사용자 이름은 비워둘 수 없으며, 자격 증명 길이에 제한이 있습니다.
result, err := client.Get(url,
httpc.WithBasicAuth("admin", "password"),
)WithBearerToken
func WithBearerToken(token string) RequestOptionAuthorization: Bearer <token> 헤더를 설정합니다. Token 은 비워둘 수 없습니다.
result, err := client.Get(url,
httpc.WithBearerToken("eyJhbGciOiJIUzI1NiIs..."),
)요청 본문
WithJSON
func WithJSON(data any) RequestOptionJSON 요청 본문을 설정하고, 자동으로 Content-Type: application/json을 추가합니다.
result, err := client.Post(url,
httpc.WithJSON(map[string]any{
"name": "test",
"email": "[email protected]",
}),
)WithXML
func WithXML(data any) RequestOptionXML 요청 본문을 설정하고, 자동으로 Content-Type: application/xml을 추가합니다.
WithForm
func WithForm(data map[string]string) RequestOptionURL 인코딩 폼 요청 본문을 설정하고, 자동으로 Content-Type: application/x-www-form-urlencoded을 추가합니다.
result, err := client.Post(url,
httpc.WithForm(map[string]string{
"username": "admin",
"password": "secret",
}),
)WithFormData
func WithFormData(data *FormData) RequestOptionmultipart/form-data 요청 본문을 설정하며, 파일과 필드 혼합 업로드를 지원합니다.
result, err := client.Post(url,
httpc.WithFormData(&httpc.FormData{
Fields: map[string]string{"description": "upload"},
Files: map[string]*httpc.FileData{
"file": {Filename: "doc.pdf", Content: fileBytes},
},
}),
)WithFile
func WithFile(fieldName, filename string, content []byte) RequestOption편의 파일 업로드. 자동으로 multipart 요청 본문을 구성하며, 파일명은 경로 순회 방지 처리를 거칩니다.
result, err := client.Post(url,
httpc.WithFile("upload", "report.csv", csvBytes),
)WithBinary
func WithBinary(data []byte, contentType ...string) RequestOption바이너리 요청 본문을 설정합니다. 기본 Content-Type 은 application/octet-stream이며, 커스텀할 수 있습니다.
result, err := client.Post(url,
httpc.WithBinary(imageBytes, "image/png"),
)WithBody
func WithBody(data any, kind ...BodyKind) RequestOption범용 요청 본문 설정으로, 자동 감지와 명시적 타입 지정을 지원합니다.
자동 감지 규칙 (기본값 BodyAuto):
| 입력 타입 | Content-Type |
|---|---|
string | text/plain; charset=utf-8 |
[]byte | application/octet-stream |
map[string]string | application/x-www-form-urlencoded |
*FormData | multipart/form-data |
io.Reader | 설정하지 않음 (호출자가 처리) |
| 기타 타입 | application/json |
명시적 타입 지정:
// 자동 감지 (기본값)
result, _ := client.Post(url, httpc.WithBody(data))
// JSON 강제
result, _ := client.Post(url, httpc.WithBody(data, httpc.BodyJSON))
// XML 강제
result, _ := client.Post(url, httpc.WithBody(data, httpc.BodyXML))| 상수 | 의미 |
|---|---|
BodyAuto | 자동 감지 (기본값) |
BodyJSON | JSON 강제 |
BodyXML | XML 강제 |
BodyForm | 폼 강제 |
BodyBinary | 바이너리 강제 |
BodyMultipart | multipart 강제 (*FormData 필요) |
쿼리 매개변수
WithQuery
func WithQuery(key string, value any) RequestOption단일 쿼리 매개변수를 설정합니다.
result, err := client.Get(url,
httpc.WithQuery("page", 1),
httpc.WithQuery("limit", 10),
)WithQueryMap
func WithQueryMap(params map[string]any) RequestOption쿼리 매개변수를 일괄 설정합니다.
result, err := client.Get(url,
httpc.WithQueryMap(map[string]any{
"page": 1,
"limit": 10,
"sort": "created_at",
}),
)Cookie
WithCookie
func WithCookie(cookie http.Cookie) RequestOption단일 Cookie 를 추가하며, 보안 검증을 거칩니다.
result, err := client.Get(url,
httpc.WithCookie(http.Cookie{Name: "session", Value: "abc123"}),
)WithCookies
func WithCookies(cookies []http.Cookie) RequestOptionCookie 를 일괄 추가합니다. WithCookie를 여러 번 호출하는 것보다 효율적입니다 — 용량을 미리 할당하고 단일 순회에서 모든 Cookie 를 검증합니다.
cookies := []http.Cookie{
{Name: "session_id", Value: "abc123"},
{Name: "user_pref", Value: "dark_mode"},
{Name: "lang", Value: "en"},
}
result, err := client.Get("https://api.example.com",
httpc.WithCookies(cookies),
)WithCookieMap
func WithCookieMap(cookies map[string]string) RequestOption간단한 Cookie 를 일괄 추가합니다. name-value 만 필요한 시나리오에 적합합니다.
result, err := client.Get(url,
httpc.WithCookieMap(map[string]string{
"session_id": "abc123",
"lang": "zh",
}),
)WithCookieString
func WithCookieString(cookieString string) RequestOption원시 Cookie 헤더 문자열에서 Cookie 를 추가합니다.
result, err := client.Get(url,
httpc.WithCookieString("session=abc123; lang=zh"),
)WithSecureCookie
func WithSecureCookie(securityConfig *CookieSecurityConfig) RequestOption요청 Cookie 의 보안 속성 (Secure, HttpOnly, SameSite) 을 강제 검증합니다.
옵션 순서
이 옵션은 적용 시점에 이미 존재하는 Cookie 만 검증합니다. WithSecureCookie는 반드시 모든 WithCookie/WithCookies/WithCookieMap/WithCookieString 뒤에 배치해야 하며, 그렇지 않으면 나중에 추가된 Cookie 가 검증되지 않습니다. 순서에 제약받지 않는 세션 수준의 Cookie 보안 검증이 필요하다면 SessionManager.SetCookieSecurity를 사용하세요.
// 올바른 순서: 먼저 Cookie 를 추가한 후 검증
result, err := client.Get(url,
httpc.WithCookie(sessionCookie),
httpc.WithCookieMap(otherCookies),
httpc.WithSecureCookie(httpc.StrictCookieSecurityConfig()),
)요청 제어
WithContext
func WithContext(ctx context.Context) RequestOption요청 컨텍스트를 설정하여 타임아웃과 취소를 지원합니다. 컨텍스트는 nil 일 수 없습니다.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
result, err := client.Get(url, httpc.WithContext(ctx))WithTimeout
func WithTimeout(timeout time.Duration) RequestOption단일 요청 타임아웃을 설정하여 클라이언트 기본 타임아웃을 덮어씁니다. 범위: 0 ~ 30 분.
result, err := client.Get(url, httpc.WithTimeout(5*time.Second))WithMaxRetries
func WithMaxRetries(maxRetries int) RequestOption단일 요청의 최대 재시도 횟수를 설정하여 클라이언트 설정을 덮어씁니다. 범위: 0-10.
result, err := client.Get(url, httpc.WithMaxRetries(3))WithFollowRedirects
func WithFollowRedirects(follow bool) RequestOption리다이렉트 따라가기 여부를 제어합니다.
// 리다이렉트 따라가기 비활성화
result, err := client.Get(url, httpc.WithFollowRedirects(false))WithMaxRedirects
func WithMaxRedirects(maxRedirects int) RequestOption단일 요청의 최대 리다이렉트 횟수를 설정합니다. 범위: 0-50.
0 값의 의미
0은 리다이렉트를 비활성화하지 않습니다. 엔진은 0을 "명시적으로 설정되지 않음"을 나타내는 센티널 값으로 처리하여 기본 상한 (10) 으로 폴백하므로, WithMaxRedirects(0)은 이 옵션을 생략하는 것과 같습니다. 리다이렉트 따라가기를 완전히 비활성화하려면 대신 WithFollowRedirects(false)를 사용하세요.
WithAllowPrivateIPs
func WithAllowPrivateIPs(allow bool) RequestOption단일 요청에 대해 클라이언트의 SSRF 정책을 재정의합니다. allow가 true이면 해당 요청은 localhost 와 사설/예약 IP 대역 (127.0.0.0/8, 10.0.0.0/8, 192.168.0.0/16, 169.254.0.0/16 등) 에 접근할 수 있으며, 이러한 주소로의 리다이렉트를 따를 수 있습니다. false이면 클라이언트가 Security.AllowPrivateIPs=true로 설정되어 있더라도 이 요청에 대해서는 SSRF 방어를 강제로 활성화합니다.
보안 안내
이것은 SSRF 방어의 단일 요청 이스케이프 해치로, 기본적으로 안전한 클라이언트 (AllowPrivateIPs=false) 가 드물게 내부 서비스, 루프백 주소 또는 로컬 개발 서버에 접근해야 하는 시나리오를 위한 것입니다.
요청 URL 이 신뢰할 수 있고 신뢰할 수 없는 사용자 입력에서 오지 않은 경우에만 활성화하세요. 클라이언트 전체가 내부 서비스에 접근해야 한다면 Config에서 직접 Security.AllowPrivateIPs=true를 설정하세요.
// 기본 클라이언트는 사설 IP 를 차단; 이 호출은 요청별로 허용
result, err := httpc.Get("http://localhost:8080/health",
httpc.WithAllowPrivateIPs(true),
)WithStreamBody
func WithStreamBody(stream bool) RequestOption스트리밍 모드를 활성화하면 응답 본문이 메모리에 캐시되지 않습니다.
중요한 제한
스트리밍 모드는 Download를 통해서만 적용됩니다. 표준 요청 메서드 (Get/Post/Put/Patch/Delete/Head/Options/Request) 와 함께 사용하면 응답 본문이 완전히 읽혀 Result로 변환되고 그 후 기저의 스트림이 닫힙니다 — 반환된 Result의 응답 본문은 비어 있으며 호출자는 해당 스트림을 소비할 수 없습니다.
대용량 파일을 메모리에 캐시하지 않고 진정으로 스트리밍 다운로드하려면 Download를 사용하세요.
콜백
WithOnRequest
func WithOnRequest(callback func(req RequestMutator) error) RequestOption요청 전송 전 콜백을 등록합니다. 체인 등록이 가능하며, 추가된 순서대로 실행됩니다. 콜백이 오류를 반환하면 요청이 중단됩니다.
result, err := client.Get(url,
httpc.WithOnRequest(func(req httpc.RequestMutator) error {
log.Printf("전송 %s %s", req.Method(), req.URL())
return nil
}),
)WithOnResponse
func WithOnResponse(callback func(resp ResponseMutator) error) RequestOption응답 수신 후 콜백을 등록합니다. 체인 등록이 가능하며, 추가된 순서대로 실행됩니다.
result, err := client.Get(url,
httpc.WithOnResponse(func(resp httpc.ResponseMutator) error {
log.Printf("응답 수신: %d %s", resp.StatusCode(), resp.Status())
return nil
}),
)