restyoops

package module
v0.0.2 Latest Latest
Warning

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

Go to latest
Published: Dec 18, 2025 License: MIT Imports: 9 Imported by: 0

README

GitHub Workflow Status (branch) GoDoc Coverage Status Supported Go Versions GitHub Release Go Report Card

restyoops

Oops! See if restyv2 response is retryable.

Structured HTTP operation fault classification with retryable semantics, designed with go-resty/resty/v2.


CHINESE README

中文说明

Main Features

🎯 Fault Classification: Categorize HTTP response outcomes into actionable categories ⚡ Retryable Detection: Determine if an operation is retryable with sensible defaults 🔄 Configurable Settings: Customize settings based on status code and kind 🔍 Content Checks: Custom content checks handling unique cases (captcha, WAF, business codes) ⏱️ Wait Time: Suggested wait duration before retrying

Installation

go get github.com/yyle88/restyoops

Quick Start

package main

import (
    "fmt"
    "github.com/go-resty/resty/v2"
    "github.com/yyle88/restyoops"
)

func main() {
    client := resty.New()

    detective := restyoops.NewDetective(restyoops.NewConfig())
    resp, oops := detective.Detect(client.R().Get("https://api.example.com/data"))

    if oops != nil {
        fmt.Printf("Kind: %s, Retryable: %v\n", oops.Kind, oops.Retryable)
        if oops.IsRetryable() {
            fmt.Printf("Wait before retrying: %v\n", oops.WaitTime)
        }
        return
    }

    fmt.Println("Request success!")
    fmt.Println("Response:", string(resp.Body()))
}

Detective wraps config and provides a convenient API that accepts resty's values without intermediate steps:

type OopsIssue = Oops

detective := restyoops.NewDetective(restyoops.NewConfig())
resp, oops := detective.Detect(client.R().Get(url))  // No need: resp, err := ...; then Detect(..., resp, err)
if oops != nil {
    // handle issue
    return
}
// success
data := resp.Body()

Advantage: Avoids the resp, err := client.R().Get(url) then Detect(cfg, resp, err) pattern.

Kind Classification

Kind Description Default Retryable
KindNetwork Network issues (timeout, DNS, TCP, TLS) true
KindHttp HTTP 4xx/5xx status codes varies
KindParse Response parsing failed false
KindBlock Request blocked (captcha, WAF) false
KindBusiness Business logic issue (HTTP 200, code!=0) false
KindUnknown Unclassified issues false

Note: Success returns nil (no oops means no problem).

Default HTTP Status Retryable

Status Code Retryable
408 Request Timeout true
429 Too Many Requests true
500 Internal Server Err true
502 Bad Gateway true
503 Service Unavailable true
504 Gateway Timeout true
400 Bad Request false
401 Unauthorized false
403 Forbidden false
404 Not Found false
409 Conflict false
422 Unprocessable Entity false
Other 5xx true
Other 4xx false

Custom Configuration

Config Precedence

When detecting, configurations are applied in the following sequence (highest to lowest):

  1. ContentChecks - Custom content check functions (checked first)
  2. StatusOptions - Status code specific configuration
  3. KindOptions - Kind specific configuration
  4. Default - Built-in default values

When a high-precedence config matches, others below it are skipped.

Customize Status Code Settings
cfg := restyoops.NewConfig().
    WithStatusRetryable(403, true, 5*time.Second).  // Make 403 retryable
    WithStatusRetryable(500, false, 0)              // Make 500 not retryable

oops := restyoops.Detect(cfg, resp, err)
Customize Kind Settings
cfg := restyoops.NewConfig().
    WithKindRetryable(restyoops.KindNetwork, true, 10*time.Second)

oops := restyoops.Detect(cfg, resp, err)
Custom Content Check
cfg := restyoops.NewConfig().
    WithContentCheck(200, func(contentType string, content []byte) *restyoops.Oops {
        if bytes.Contains(content, []byte("captcha")) {
            return restyoops.NewOops(restyoops.KindBlock, 200, errors.New("CAPTCHA DETECTED"), true).WithWaitTime(5*time.Second)
        }
        return nil // pass, continue default detection
    })

oops := restyoops.Detect(cfg, resp, err)
Set Default Wait Time
cfg := restyoops.NewConfig().
    WithDefaultWait(2 * time.Second)

oops := restyoops.Detect(cfg, resp, err)

Oops Struct

type Oops struct {
    Kind        Kind          // Classification
    StatusCode  int           // HTTP status code
    ContentType string        // Response Content-Type
    Cause       error         // Wrapped cause (never nil)
    Retryable   bool          // Can be resolved via retries
    WaitTime    time.Duration // Suggested wait time
}

Detect Function (Basic API)

func Detect(cfg *Config, resp *resty.Response, respCause error) *Oops

Usage:

resp, err := client.R().Get(url)
oops := restyoops.Detect(restyoops.NewConfig(), resp, err)

📄 License

MIT License - see LICENSE.


💬 Contact & Feedback

Contributions are welcome! Report bugs, suggest features, and contribute code:

  • 🐛 Mistake reports? Open an issue on GitHub with reproduction steps
  • 💡 Fresh ideas? Create an issue to discuss
  • 📖 Documentation confusing? Report it so we can improve
  • 🚀 Need new features? Share the use cases to help us understand requirements
  • Performance issue? Help us optimize through reporting slow operations
  • 🔧 Configuration problem? Ask questions about complex setups
  • 📢 Follow project progress? Watch the repo to get new releases and features
  • 🌟 Success stories? Share how this package improved the workflow
  • 💬 Feedback? We welcome suggestions and comments

🔧 Development

New code contributions, follow this process:

  1. Fork: Fork the repo on GitHub (using the webpage UI).
  2. Clone: Clone the forked project (git clone https://github.com/yourname/repo-name.git).
  3. Navigate: Navigate to the cloned project (cd repo-name)
  4. Branch: Create a feature branch (git checkout -b feature/xxx).
  5. Code: Implement the changes with comprehensive tests
  6. Testing: (Golang project) Ensure tests pass (go test ./...) and follow Go code style conventions
  7. Documentation: Update documentation to support client-facing changes
  8. Stage: Stage changes (git add .)
  9. Commit: Commit changes (git commit -m "Add feature xxx") ensuring backward compatible code
  10. Push: Push to the branch (git push origin feature/xxx).
  11. PR: Open a merge request on GitHub (on the GitHub webpage) with detailed description.

Please ensure tests pass and include relevant documentation updates.


🌟 Support

Welcome to contribute to this project via submitting merge requests and reporting issues.

Project Support:

  • Give GitHub stars if this project helps you
  • 🤝 Share with teammates and (golang) programming friends
  • 📝 Write tech blogs about development tools and workflows - we provide content writing support
  • 🌟 Join the ecosystem - committed to supporting open source and the (golang) development scene

Have Fun Coding with this package! 🎉🎉🎉


GitHub Stars

Stargazers

Documentation

Overview

Package restyoops: Structured HTTP operation fault classification with retryable semantics Oops! See if restyv2 response is retryable Provides Kind enum, Oops struct, and Detect function to categorize HTTP response outcomes

restyoops: 结构化 HTTP 操作故障分类,带有可重试语义 Oops! 检查 restyv2 响应是否可重试 提供 Kind 枚举、Oops 结构体和 Detect 函数来分类 HTTP 响应结果

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	StatusOptions map[int]*StatusOption
	KindOptions   map[Kind]*KindOption
	DefaultWait   time.Duration            // default wait time // 默认等待时间
	ContentChecks map[int]ContentCheckFunc // custom content checks // 自定义内容检查
}

Config holds customizable detection settings Config 保存可自定义的检测设置

func NewConfig

func NewConfig() *Config

NewConfig creates a Config with sensible defaults NewConfig 创建带有合理默认值的 Config

func (*Config) WithContentCheck

func (c *Config) WithContentCheck(statusCode int, check ContentCheckFunc) *Config

WithContentCheck adds a custom content check WithContentCheck 添加自定义内容检查

func (*Config) WithDefaultWait

func (c *Config) WithDefaultWait(d time.Duration) *Config

WithDefaultWait sets the default wait time WithDefaultWait 设置默认等待时间

func (*Config) WithKindRetryable

func (c *Config) WithKindRetryable(kind Kind, retryable bool, waitTime time.Duration) *Config

WithKindRetryable sets retryable and wait time based on Kind WithKindRetryable 基于 Kind 设置可重试和等待时间

func (*Config) WithStatusRetryable

func (c *Config) WithStatusRetryable(statusCode int, retryable bool, waitTime time.Duration) *Config

WithStatusRetryable sets retryable and wait time based on status code WithStatusRetryable 基于状态码设置可重试和等待时间

type ContentCheckFunc

type ContentCheckFunc func(contentType string, content []byte) *Oops

ContentCheckFunc checks content and returns Oops if matched, nil otherwise ContentCheckFunc 检查内容,匹配时返回 Oops,否则返回 nil

type Detective added in v0.0.1

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

Detective wraps Config and provides a convenient API Detective 封装 Config 并提供便捷的 API

func NewDetective added in v0.0.1

func NewDetective(cfg *Config) *Detective

NewDetective creates a Detective with the specified Config NewDetective 使用指定的 Config 创建 Detective

func (*Detective) Detect added in v0.0.1

func (c *Detective) Detect(resp *resty.Response, respCause error) (*resty.Response, *OopsIssue)

Detect classifies a resty response and returns both response and oops issue Detect 分类 resty 响应并返回响应和 oops 问题

type Kind

type Kind string

Kind represents the classification of an HTTP operation outcome Used to categorize outcomes into actionable groups

Kind 代表 HTTP 操作结果的分类 用于将结果分类为可操作的组

const (
	// KindUnknown indicates unclassified issues
	// KindUnknown 表示未分类的问题
	KindUnknown Kind = "UNKNOWN"

	// KindNetwork indicates network issues like timeout, DNS, TCP, TLS
	// Outcomes: connection reset, deadline exceeded, no such host
	// KindNetwork 表示网络问题,如超时、DNS、TCP、TLS
	// 结果:连接重置、截止时间超时、无此主机
	KindNetwork Kind = "NETWORK"

	// KindHttp indicates HTTP status code issues (4xx/5xx)
	// Outcomes: 429 rate limit, 500 issues, 502/503/504 upstream issues
	// KindHttp 表示 HTTP 状态码问题(4xx/5xx)
	// 结果:429 限流、500 问题、502/503/504 上游问题
	KindHttp Kind = "HTTP"

	// KindParse indicates response parsing issues
	// Outcomes: JSON unmarshal failed, unexpected content type
	// KindParse 表示响应解析问题
	// 结果:JSON 反序列化失败、意外的内容类型
	KindParse Kind = "PARSE"

	// KindBlock indicates request was blocked (captcha, WAF, login redirect)
	// Outcomes: 403 with HTML, 200 with captcha page, redirect to login
	// KindBlock 表示请求被阻止(验证码、WAF、登录重定向)
	// 结果:403 带 HTML、200 带验证码页面、重定向到登录
	KindBlock Kind = "BLOCK"

	// KindBusiness indicates business logic issues (HTTP 200 but business code != 0)
	// Outcomes: rate limited, insufficient balance, invalid params
	// KindBusiness 表示业务逻辑问题(HTTP 200 但业务码 != 0)
	// 结果:限流、余额不足、参数无效
	KindBusiness Kind = "BUSINESS"
)

func (Kind) IsBlock

func (k Kind) IsBlock() bool

IsBlock checks if Kind indicates blocked/captcha issues IsBlock 检查 Kind 是否表示被阻止/验证码问题

func (Kind) IsBusiness

func (k Kind) IsBusiness() bool

IsBusiness checks if Kind indicates business logic issues IsBusiness 检查 Kind 是否表示业务逻辑问题

func (Kind) IsHttp

func (k Kind) IsHttp() bool

IsHttp checks if Kind indicates HTTP status issues IsHttp 检查 Kind 是否表示 HTTP 状态问题

func (Kind) IsNetwork

func (k Kind) IsNetwork() bool

IsNetwork checks if Kind indicates network issues IsNetwork 检查 Kind 是否表示网络问题

func (Kind) IsParse

func (k Kind) IsParse() bool

IsParse checks if Kind indicates parsing issues IsParse 检查 Kind 是否表示解析问题

func (Kind) IsUnknown

func (k Kind) IsUnknown() bool

IsUnknown checks if Kind indicates unknown issues IsUnknown 检查 Kind 是否表示未知问题

func (Kind) String

func (k Kind) String() string

String returns the string representation of Kind String 返回 Kind 的字符串表示

type KindOption

type KindOption struct {
	Retryable bool
	WaitTime  time.Duration
}

KindOption holds retryable and wait time settings KindOption 保存可重试和等待时间设置

type Oops

type Oops struct {
	Kind        Kind          // Classification // 分类
	StatusCode  int           // HTTP status code // HTTP 状态码
	ContentType string        // Response Content-Type // 响应 Content-Type
	Cause       error         // Wrapped outcome // 被包装的结果
	Retryable   bool          // Can be resolved via retries // 是否可通过重试解决
	WaitTime    time.Duration // Suggested wait time // 建议等待时间
}

Oops represents a structured HTTP operation outcome Oops 代表结构化的 HTTP 操作结果

func Detect

func Detect(cfg *Config, resp *resty.Response, respCause error) *Oops

Detect classifies a resty response Detect 分类 resty 响应

func NewOops

func NewOops(kind Kind, statusCode int, cause error, retryable bool) *Oops

NewOops creates an Oops with the specified params NewOops 使用指定的参数创建一个 Oops

func NewUnknown

func NewUnknown() *Oops

NewUnknown creates an Oops indicating unknown issue NewUnknown 创建一个表示未知问题的 Oops

func (*Oops) IsRetryable

func (o *Oops) IsRetryable() bool

IsRetryable checks if retrying is recommended IsRetryable 检查是否建议重试

func (*Oops) WithContentType added in v0.0.1

func (o *Oops) WithContentType(contentType string) *Oops

WithContentType sets the content type and returns the Oops WithContentType 设置内容类型并返回 Oops

func (*Oops) WithWaitTime added in v0.0.1

func (o *Oops) WithWaitTime(d time.Duration) *Oops

WithWaitTime sets the suggested wait time and returns the Oops WithWaitTime 设置建议等待时间并返回 Oops

type OopsIssue added in v0.0.1

type OopsIssue = Oops

OopsIssue is an alias for Oops, for use as return type OopsIssue 是 Oops 的别名,用于作为返回类型

type StatusOption

type StatusOption struct {
	Retryable bool
	WaitTime  time.Duration
}

StatusOption holds retryable and wait time settings StatusOption 保存可重试和等待时间设置

Directories

Path Synopsis
internal
utils
Package utils provides utilities supporting the restyoops package Implements generic support functions used across different modules
Package utils provides utilities supporting the restyoops package Implements generic support functions used across different modules

Jump to

Keyboard shortcuts

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