httputil

package
v1.28.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 4, 2026 License: Apache-2.0 Imports: 19 Imported by: 0

Documentation

Overview

Package httputil은 공용 HTTP client, JSON request, response 검증 helper를 제공합니다.

패키지 개요

이 패키지는 서비스 간 HTTP 호출과 외부 API 호출에서 반복되는 client timeout, connection pool, HTTP/2 정책을 TransportProfile로 맞춥니다. 기본 transport의 proxy, keep-alive, TLS 기본값은 유지하고 호출 목적에 맞는 profile만 주입합니다.

JSON request 생성, API key header 적용, response body decode/discard, non-2xx response를 APIError로 변환하는 흐름도 이 패키지에서 제공합니다. 호출부는 error helper로 HTTP status와 API error code를 분기할 수 있습니다.

관리 HTTP surface에서 반복되는 API key 인증, fixed-window rate limiting, trusted proxy client IP 식별도 프레임워크 독립 helper로 제공합니다. gin 전용 adapter는 pkg/httputil/ginauth에 분리되어 있습니다.

주요 사용 패턴

client := httputil.NewExternalAPIClient(30 * time.Second)
resp, err := client.Get(url)
if err != nil {
    return err
}
// non-2xx 시 CheckStatus가 body를 drain+close하므로 아래 defer는 no-op이 됩니다.
// 2xx success 경로에서는 caller가 body를 읽고 닫습니다.
defer resp.Body.Close()
if err := httputil.CheckStatus(resp); err != nil {
    return err
}
if _, err := io.Copy(io.Discard, resp.Body); err != nil {
    return err
}

api := httputil.NewJSONClient(baseURL, apiKey, 10*time.Second)
req, err := api.NewJSONRequest(ctx, http.MethodPost, "/v1/jobs", payload)
if err != nil {
    return err
}
resp, err := api.Do(req)
if err != nil {
    return err
}
// non-2xx 시 CheckStatus가 body를 drain+close하므로 아래 defer는 no-op이 됩니다.
defer resp.Body.Close()
if err := api.CheckStatus(resp); err != nil {
    return err
}
var out jobResponse
if err := api.DecodeJSON(resp, &out); err != nil {
    return err
}

Index

Constants

View Source
const (
	// ContentTypeJSON은 JSON 응답 Content-Type 값이다.
	ContentTypeJSON = "application/json"
	// HeaderContentType은 HTTP Content-Type 헤더 이름이다.
	HeaderContentType = "Content-Type"
	// HeaderAPIKey는 관리 API key 인증 헤더 이름이다.
	HeaderAPIKey = "X-API-Key" //nolint:gosec // 헤더 이름 상수이며 credential 값이 아니다.
)
View Source
const DefaultMaxBodyBytes int64 = 16 << 20
View Source
const DefaultMaxRequestBodyBytes int64 = 64 << 10

DefaultMaxRequestBodyBytes는 JSON 요청 본문의 기본 최대 크기다.

Variables

View Source
var (
	// ErrRequestBodyRequired는 필수 JSON 요청 본문이 없을 때의 오류다.
	ErrRequestBodyRequired = errors.New("httputil: request body is required")
	// ErrUnsupportedJSONContentType는 JSON Content-Type이 아닐 때의 오류다.
	ErrUnsupportedJSONContentType = errors.New("httputil: content type must be application/json")
	// ErrRequestBodyTooLarge는 JSON 요청 본문이 허용 크기를 넘을 때의 오류다.
	ErrRequestBodyTooLarge = errors.New("httputil: request body exceeds limit")
	// ErrMultipleJSONValues는 JSON 요청 본문에 값이 둘 이상 있을 때의 오류다.
	ErrMultipleJSONValues = errors.New("httputil: request body must contain a single JSON value")
)
View Source
var ErrResponseBodyTooLarge = errors.New("httputil: response body exceeds limit")

Functions

func APIKeyFromRequest

func APIKeyFromRequest(r *http.Request) string

APIKeyFromRequest는 X-API-Key 또는 Bearer Authorization 값을 관리 API key로 추출한다.

func AdminAuthMiddleware

func AdminAuthMiddleware(cfg AdminAuthConfig) func(http.Handler) http.Handler

AdminAuthMiddleware는 twentyq형 관리 API key 인증 middleware를 만든다.

func CheckStatus

func CheckStatus(resp *http.Response) error

func ClientIP

func ClientIP(r *http.Request, opts ClientIPOptions) string

ClientIP는 trusted proxy 경계 안에서만 forwarded header를 반영한 client IP를 반환한다.

func ConstantTimeStringEqual

func ConstantTimeStringEqual(left, right string) bool

ConstantTimeStringEqual은 두 문자열을 길이 차이까지 포함해 일정 시간 비교한다.

func DecodeJSON

func DecodeJSON(resp *http.Response, v any) error

func DecodeJSONLimited

func DecodeJSONLimited(resp *http.Response, v any, maxBytes int64) error

func DecodeJSONRequest added in v1.28.0

func DecodeJSONRequest(w http.ResponseWriter, r *http.Request, v any, opts DecodeJSONRequestOptions) error

DecodeJSONRequest는 HTTP 요청 본문에서 단일 JSON 값을 decode한다.

func DecodeJSONRequestStatus added in v1.28.0

func DecodeJSONRequestStatus(err error) int

DecodeJSONRequestStatus는 JSON 요청 오류에 대응하는 HTTP status를 반환한다.

func FixedWindowRateLimitMiddleware

func FixedWindowRateLimitMiddleware(cfg RateLimitMiddlewareConfig) func(http.Handler) http.Handler

FixedWindowRateLimitMiddleware는 fixed-window limiter를 net/http middleware로 감싼다.

func IsStatus

func IsStatus(err error, statusCode int) bool

func NewClient

func NewClient(timeout time.Duration) *http.Client

func NewExternalAPIClient

func NewExternalAPIClient(timeout time.Duration) *http.Client

func NewInternalServiceClient

func NewInternalServiceClient(timeout time.Duration) *http.Client

func NewProfiledClient

func NewProfiledClient(profile TransportProfile) *http.Client

기본 keep-alive, proxy, TLS 기본 동작은 유지하고 timeout/pool/HTTP2 정책만 profile로 주입합니다.

func ParseTrustedProxies

func ParseTrustedProxies(values []string) ([]netip.Prefix, error)

ParseTrustedProxies는 IP/CIDR 문자열을 trusted proxy prefix 목록으로 변환한다.

func ParseTrustedProxyCSV

func ParseTrustedProxyCSV(raw string) ([]netip.Prefix, error)

ParseTrustedProxyCSV는 comma-separated trusted proxy CIDR/IP 목록을 변환한다.

func RateLimitIdentity

func RateLimitIdentity(r *http.Request, apiKey string, opts ClientIPOptions) string

RateLimitIdentity는 API key가 있으면 key hash, 아니면 client IP 기반 identity를 반환한다.

func RateLimitKeyHash

func RateLimitKeyHash(value string) string

RateLimitKeyHash는 rate-limit key/log용 짧은 SHA-256 해시를 반환한다.

func WriteErrorJSON

func WriteErrorJSON(w http.ResponseWriter, status int, code, message string) error

WriteErrorJSON은 표준 관리 HTTP JSON 에러 응답을 쓴다.

func WriteRateLimitExceededJSON

func WriteRateLimitExceededJSON(w http.ResponseWriter, _ *http.Request, _ string)

WriteRateLimitExceededJSON은 twentyq형 429 JSON 응답을 쓴다.

Types

type APIError

type APIError struct {
	StatusCode int
	Code       string
	Message    string
	RequestID  string
	Details    map[string]any
	Body       string
	Err        error
}

func (*APIError) Error

func (e *APIError) Error() string

func (*APIError) Unwrap

func (e *APIError) Unwrap() error

type AdminAuthConfig

type AdminAuthConfig struct {
	APIKey   string
	Disabled bool
}

AdminAuthConfig는 관리 API key 인증 middleware 설정이다. Disabled가 false인 zero value는 인증을 강제한다.

type ClientIPOptions

type ClientIPOptions struct {
	TrustForwarded bool
	TrustedProxies []netip.Prefix
	ForwardedMode  ForwardedHeaderMode
}

ClientIPOptions는 forwarded header 신뢰 경계를 지정한다.

type DecodeJSONRequestOptions added in v1.28.0

type DecodeJSONRequestOptions struct {
	// MaxBodyBytes는 요청 본문 최대 크기다.
	MaxBodyBytes int64
	// Strict는 알 수 없는 JSON field를 거부한다.
	Strict bool
	// RequireContentType은 application/json Content-Type을 필수로 한다.
	RequireContentType bool
}

DecodeJSONRequestOptions는 JSON 요청 decode 동작을 조정한다.

type ErrorResponse

type ErrorResponse struct {
	Error   string `json:"error"`
	Message string `json:"message"`
}

ErrorResponse는 관리 HTTP JSON 에러 응답 본문이다.

type FixedWindowOptions

type FixedWindowOptions struct {
	MaxIdentities int
	EntryTTL      time.Duration
	Now           func() time.Time
}

FixedWindowOptions는 fixed-window limiter 선택 동작을 지정한다. MaxIdentities와 EntryTTL의 zero value는 안전 기본값을 사용한다.

type FixedWindowRateLimiter

type FixedWindowRateLimiter struct {
	// contains filtered or unexported fields
}

FixedWindowRateLimiter는 identity별 fixed-window 요청 수를 제한한다.

func NewFixedWindowRateLimiter

func NewFixedWindowRateLimiter(limit int, window time.Duration, opts FixedWindowOptions) *FixedWindowRateLimiter

NewFixedWindowRateLimiter는 fixed-window limiter를 생성한다.

func (*FixedWindowRateLimiter) Allow

func (l *FixedWindowRateLimiter) Allow(identity string) bool

Allow는 identity가 현재 window에서 허용되는지 반환한다.

type ForwardedHeaderMode

type ForwardedHeaderMode int

ForwardedHeaderMode는 trusted proxy에서 전달된 client IP 선택 방식을 지정한다.

const (
	// ForwardedHeaderLeftmost는 X-Forwarded-For의 첫 유효 IP를 선택한다.
	ForwardedHeaderLeftmost ForwardedHeaderMode = iota
	// ForwardedHeaderRightmostNonTrusted는 오른쪽에서 첫 비신뢰 hop을 선택한다.
	ForwardedHeaderRightmostNonTrusted
)

type IdentityFunc

type IdentityFunc func(*http.Request) string

IdentityFunc는 요청에서 rate-limit identity를 만든다.

type JSONClient

type JSONClient struct {
	// contains filtered or unexported fields
}

JSONClient는 내부 서비스 간 JSON API 호출용 공통 HTTP 클라이언트입니다.

func NewJSONClient

func NewJSONClient(baseURL, apiKey string, timeout time.Duration) *JSONClient

NewJSONClient는 공통 internal service client를 생성합니다.

func NewJSONClientWithHTTPClient

func NewJSONClientWithHTTPClient(baseURL, apiKey string, httpClient *http.Client) *JSONClient

NewJSONClientWithHTTPClient는 caller가 준비한 http.Client로 JSONClient를 생성합니다.

func (*JSONClient) CheckStatus

func (c *JSONClient) CheckStatus(resp *http.Response) error

func (*JSONClient) DecodeJSON

func (c *JSONClient) DecodeJSON(resp *http.Response, out any) error

func (*JSONClient) DiscardBody

func (c *JSONClient) DiscardBody(resp *http.Response) error

func (*JSONClient) Do

func (c *JSONClient) Do(req *http.Request) (*http.Response, error)

func (*JSONClient) NewJSONRequest

func (c *JSONClient) NewJSONRequest(ctx context.Context, method, path string, payload any) (*http.Request, error)

NewJSONRequest는 JSON body 요청을 생성합니다.

func (*JSONClient) NewRequest

func (c *JSONClient) NewRequest(ctx context.Context, method, path string) (*http.Request, error)

NewRequest는 body 없는 요청을 생성합니다.

type JSONRequestError added in v1.28.0

type JSONRequestError struct {
	// StatusCode는 응답해야 할 HTTP status code다.
	StatusCode int
	// Code는 machine-readable 오류 code다.
	Code string
	// Message는 응답에 사용할 오류 message다.
	Message string
	// Err는 원래 decode 또는 validation 오류다.
	Err error
}

JSONRequestError는 JSON 요청 decode 실패의 HTTP taxonomy다.

func (*JSONRequestError) Error added in v1.28.0

func (e *JSONRequestError) Error() string

Error는 JSON 요청 오류를 문자열로 반환한다.

func (*JSONRequestError) Unwrap added in v1.28.0

func (e *JSONRequestError) Unwrap() error

Unwrap은 원래 JSON 요청 decode 오류를 반환한다.

type LoginFailureRateLimiter

type LoginFailureRateLimiter struct {
	// contains filtered or unexported fields
}

LoginFailureRateLimiter는 로그인 실패 횟수 기반 lockout limiter다.

func NewDefaultLoginFailureRateLimiter

func NewDefaultLoginFailureRateLimiter() *LoginFailureRateLimiter

NewDefaultLoginFailureRateLimiter는 admin-dashboard와 같은 기본 lockout 값을 사용한다.

func NewLoginFailureRateLimiter

func NewLoginFailureRateLimiter(opts LoginFailureRateLimiterOptions) *LoginFailureRateLimiter

NewLoginFailureRateLimiter는 로그인 실패 기반 lockout limiter를 생성한다.

func (*LoginFailureRateLimiter) IsAllowed

func (l *LoginFailureRateLimiter) IsAllowed(identity string) (bool, time.Duration)

IsAllowed는 identity가 현재 로그인 시도를 할 수 있는지와 retry-after를 반환한다.

func (*LoginFailureRateLimiter) RecordFailure

func (l *LoginFailureRateLimiter) RecordFailure(identity string) int

RecordFailure는 identity의 실패 횟수를 기록하고 현재 window count를 반환한다.

func (*LoginFailureRateLimiter) RecordSuccess

func (l *LoginFailureRateLimiter) RecordSuccess(identity string)

RecordSuccess는 identity의 실패 기록을 삭제한다.

func (*LoginFailureRateLimiter) Start

func (l *LoginFailureRateLimiter) Start()

Start는 stale attempt cleanup loop를 시작한다.

func (*LoginFailureRateLimiter) Stop

func (l *LoginFailureRateLimiter) Stop()

Stop은 cleanup loop를 정지한다.

type LoginFailureRateLimiterOptions

type LoginFailureRateLimiterOptions struct {
	MaxAttempts     int
	Window          time.Duration
	Lockout         time.Duration
	CleanupInterval time.Duration
	Now             func() time.Time
}

LoginFailureRateLimiterOptions는 로그인 실패 lockout limiter 설정이다.

type RateLimitMiddlewareConfig

type RateLimitMiddlewareConfig struct {
	Limiter  *FixedWindowRateLimiter
	Identity IdentityFunc
	Reject   RateLimitRejectFunc
	Skip     func(*http.Request) bool
}

RateLimitMiddlewareConfig는 fixed-window HTTP middleware 설정이다.

type RateLimitRejectFunc

type RateLimitRejectFunc func(http.ResponseWriter, *http.Request, string)

RateLimitRejectFunc는 rate-limit 초과 응답을 쓴다.

type TransportProfile

type TransportProfile struct {
	Timeout               time.Duration
	DialTimeout           time.Duration
	TLSHandshakeTimeout   time.Duration
	ResponseHeaderTimeout time.Duration
	IdleConnTimeout       time.Duration
	MaxIdleConns          int
	MaxConnsPerHost       int
	MaxIdleConnsPerHost   int
	DisableHTTP2          bool
}

Directories

Path Synopsis
Package ginauth는 gin 기반 관리 API key 인증 middleware를 제공합니다.
Package ginauth는 gin 기반 관리 API key 인증 middleware를 제공합니다.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL