mirror of
https://codeberg.org/VnPower/PixivFE
synced 2024-12-06 19:16:23 +01:00
rm go-retryablehttp
This commit is contained in:
@@ -52,11 +52,6 @@ type ServerConfig struct {
|
||||
TokenBaseTimeout time.Duration `env:"PIXIVFE_TOKEN_BASE_TIMEOUT,overwrite"`
|
||||
TokenMaxBackoffTime time.Duration `env:"PIXIVFE_TOKEN_MAX_BACKOFF_TIME,overwrite"`
|
||||
|
||||
// API request level backoff settings
|
||||
APIMaxRetries int `env:"PIXIVFE_API_MAX_RETRIES,overwrite"`
|
||||
APIBaseTimeout time.Duration `env:"PIXIVFE_API_BASE_TIMEOUT,overwrite"`
|
||||
APIMaxBackoffTime time.Duration `env:"PIXIVFE_API_MAX_BACKOFF_TIME,overwrite"`
|
||||
|
||||
AcceptLanguage string `env:"PIXIVFE_ACCEPTLANGUAGE,overwrite"`
|
||||
RequestLimit uint64 `env:"PIXIVFE_REQUESTLIMIT"` // if 0, request limit is disabled
|
||||
|
||||
@@ -135,10 +130,6 @@ func (s *ServerConfig) LoadConfig() error {
|
||||
s.TokenBaseTimeout = 1000 * time.Millisecond
|
||||
s.TokenMaxBackoffTime = 32000 * time.Millisecond
|
||||
|
||||
s.APIMaxRetries = 3
|
||||
s.APIBaseTimeout = 500 * time.Millisecond
|
||||
s.APIMaxBackoffTime = 8000 * time.Millisecond
|
||||
|
||||
s.CacheEnabled = false
|
||||
s.CacheSize = 100
|
||||
s.CacheTTL = 60 * time.Minute
|
||||
@@ -216,8 +207,6 @@ func (s *ServerConfig) LoadConfig() error {
|
||||
log.Printf("Token manager settings: Max retries: %d, Base timeout: %v, Max backoff time: %v\n", s.TokenMaxRetries, s.TokenBaseTimeout, s.TokenMaxBackoffTime)
|
||||
log.Printf("Token load balancing method: %s\n", s.TokenLoadBalancing)
|
||||
|
||||
log.Printf("API request backoff settings: Max retries: %d, Base timeout: %v, Max backoff time: %v\n", s.APIMaxRetries, s.APIBaseTimeout, s.APIMaxBackoffTime)
|
||||
|
||||
// Print cache configuration
|
||||
if s.CacheEnabled {
|
||||
log.Println("API response cache is enabled")
|
||||
|
||||
+86
-131
@@ -1,5 +1,5 @@
|
||||
// This file implements the core functionality for handling API requests,
|
||||
// including response caching, retry mechanisms, and request proxying.
|
||||
// including response caching and and request proxying.
|
||||
package core
|
||||
|
||||
import (
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"codeberg.org/vnpower/pixivfe/v2/server/token_manager"
|
||||
"codeberg.org/vnpower/pixivfe/v2/server/utils"
|
||||
|
||||
"github.com/hashicorp/go-retryablehttp"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/zeebo/xxh3"
|
||||
@@ -56,9 +55,8 @@ type CachingResult struct {
|
||||
}
|
||||
|
||||
var (
|
||||
retryClient *retryablehttp.Client
|
||||
cacheSeed uint64
|
||||
cache *lru.Cache
|
||||
cacheSeed uint64
|
||||
cache *lru.Cache
|
||||
|
||||
// shortTTLPaths lists API endpoints that require a shorter TTL for their cached responses.
|
||||
shortTTLPaths = []string{
|
||||
@@ -108,16 +106,6 @@ func InitCache() {
|
||||
cacheSeed = binary.LittleEndian.Uint64(seedBytes[:])
|
||||
}
|
||||
|
||||
// init sets up a configured retryablehttp client.
|
||||
func init() {
|
||||
retryClient = retryablehttp.NewClient()
|
||||
retryClient.RetryMax = config.GlobalConfig.APIMaxRetries
|
||||
retryClient.RetryWaitMin = config.GlobalConfig.APIBaseTimeout
|
||||
retryClient.RetryWaitMax = config.GlobalConfig.APIMaxBackoffTime
|
||||
retryClient.HTTPClient = utils.HttpClient
|
||||
retryClient.Logger = nil // Disables the default logger in go-retryablehttp
|
||||
}
|
||||
|
||||
// generateCacheKey creates a unique identifier for caching purposes by hashing
|
||||
// the combined request URL and the user's token using seeded xxhash.
|
||||
//
|
||||
@@ -131,6 +119,7 @@ func generateCacheKey(url, userToken string) string {
|
||||
}
|
||||
|
||||
// determineCachePolicy determines the caching policy for a given request.
|
||||
//
|
||||
// It returns a CachePolicy struct indicating whether to fetch from cache,
|
||||
// whether to store the response in cache, and the cached response if available.
|
||||
func determineCachePolicy(rawURL, userToken string, headers http.Header) CachePolicy {
|
||||
@@ -152,8 +141,7 @@ func determineCachePolicy(rawURL, userToken string, headers http.Header) CachePo
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the Cache-Control header from the downstream request
|
||||
// and check for "no-cache"
|
||||
// Retrieve the Cache-Control header from the downstream request and check for "no-cache"
|
||||
cacheControl := headers.Get("Cache-Control")
|
||||
lowerCacheControl := strings.ToLower(cacheControl)
|
||||
if strings.Contains(lowerCacheControl, "no-cache") {
|
||||
@@ -191,8 +179,9 @@ func determineCachePolicy(rawURL, userToken string, headers http.Header) CachePo
|
||||
}
|
||||
}
|
||||
|
||||
// manageCaching manages the caching logic during and after a request.
|
||||
// It either returns a cached response or allows the request to proceed and optionally caches the new response.
|
||||
// manageCaching manages the caching logic after receiving a response.
|
||||
//
|
||||
// It either returns a cached response or allows the response to be stored in cache.
|
||||
func manageCaching(rawURL, userToken string, headers http.Header, response *SimpleHTTPResponse) CachingResult {
|
||||
policy := determineCachePolicy(rawURL, userToken, headers)
|
||||
if policy.ShouldUseCached && policy.CachedResponse != nil {
|
||||
@@ -232,14 +221,80 @@ func manageCaching(rawURL, userToken string, headers http.Header, response *Simp
|
||||
}
|
||||
}
|
||||
|
||||
// makeRequest is a helper function that encapsulates the common logic for making HTTP requests.
|
||||
// handleRequest handles HTTP requests.
|
||||
func handleRequest(
|
||||
ctx context.Context,
|
||||
auditor *audit.Auditor,
|
||||
reqFunc func(context.Context, string) (*http.Request, error),
|
||||
userToken string,
|
||||
isPost bool,
|
||||
url string,
|
||||
incomingHeaders http.Header,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
// Retrieve the token
|
||||
tokenManager := config.GlobalConfig.TokenManager
|
||||
token, err := retrieveToken(tokenManager, userToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// For GET requests, determine if caching should be used
|
||||
var cachingResult CachingResult
|
||||
if !isPost {
|
||||
policy := determineCachePolicy(url, userToken, incomingHeaders)
|
||||
if policy.ShouldUseCached && policy.CachedResponse != nil {
|
||||
return policy.CachedResponse, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Make the HTTP request using the provided request function
|
||||
resp, err := makeRequest(ctx, auditor, reqFunc, token, url)
|
||||
if err != nil {
|
||||
// NOTE: don't mark the token provided by tokenManager as timed out if the making the request itself failed
|
||||
// tokenManager.MarkTokenStatus(token, token_manager.TimedOut)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Handle the response based on the status code
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
// Mark the token as good if the response is OK
|
||||
tokenManager.MarkTokenStatus(token, token_manager.Good)
|
||||
|
||||
if !isPost {
|
||||
// Handle caching logic after receiving an HTTP 200 response
|
||||
cachingResult = manageCaching(url, userToken, incomingHeaders, resp)
|
||||
if cachingResult.FromCache {
|
||||
return cachingResult.Response, nil
|
||||
}
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// Handle non-OK status codes
|
||||
err = i18n.Errorf("HTTP status code: %d", resp.StatusCode)
|
||||
|
||||
// Mark the token provided by tokenManager as timed out if the
|
||||
// request succeeded, but returned a non-OK response
|
||||
tokenManager.MarkTokenStatus(token, token_manager.TimedOut)
|
||||
|
||||
// Check if the context has been canceled or timed out
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// makeRequest is a helper function that encapsulates the common logic for making HTTP requests using utils.HttpClient.Do.
|
||||
//
|
||||
// It constructs the request using the provided request function, executes it using the retryable client,
|
||||
// reads the response, logs the API round trip details for auditing, and returns a simplified response.
|
||||
// It constructs the request using the provided request function, executes it using HttpClient,
|
||||
// reads the response, logs the API round trip details, and returns a SimpleHTTPResponse.
|
||||
func makeRequest(
|
||||
ctx context.Context,
|
||||
auditor *audit.Auditor,
|
||||
reqFunc func(context.Context, string) (*retryablehttp.Request, error),
|
||||
reqFunc func(context.Context, string) (*http.Request, error),
|
||||
token *token_manager.Token,
|
||||
url string,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
@@ -250,7 +305,7 @@ func makeRequest(
|
||||
}
|
||||
|
||||
start := time.Now()
|
||||
resp, err := retryClient.Do(req)
|
||||
resp, err := utils.HttpClient.Do(req)
|
||||
end := time.Now()
|
||||
|
||||
if err != nil {
|
||||
@@ -282,18 +337,6 @@ func makeRequest(
|
||||
}, nil
|
||||
}
|
||||
|
||||
// executePost handles POST requests without retries.
|
||||
func executePost(
|
||||
ctx context.Context,
|
||||
auditor *audit.Auditor,
|
||||
reqFunc func(context.Context, string) (*retryablehttp.Request, error),
|
||||
userToken string,
|
||||
url string,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
token := &token_manager.Token{Value: userToken}
|
||||
return makeRequest(ctx, auditor, reqFunc, token, url)
|
||||
}
|
||||
|
||||
// retrieveToken obtains a valid token, preferring the userToken if provided by the caller.
|
||||
func retrieveToken(tokenManager *token_manager.TokenManager, userToken string) (*token_manager.Token, error) {
|
||||
if userToken != "" {
|
||||
@@ -306,7 +349,7 @@ func retrieveToken(tokenManager *token_manager.TokenManager, userToken string) (
|
||||
return nil,
|
||||
i18n.Errorf(
|
||||
`All tokens (%d) are timed out, resetting all tokens to their initial good state.
|
||||
Consider providing additional tokens in PIXIVFE_TOKEN or reviewing API request level backoff configuration.
|
||||
Consider providing additional tokens in PIXIVFE_TOKEN or reviewing token management configuration.
|
||||
Please refer the following documentation for additional information:
|
||||
- https://pixivfe-docs.pages.dev/hosting/obtaining-pixivfe-token/
|
||||
- https://pixivfe-docs.pages.dev/hosting/environment-variables/#exponential-backoff-configuration`,
|
||||
@@ -316,82 +359,6 @@ Please refer the following documentation for additional information:
|
||||
return token, nil
|
||||
}
|
||||
|
||||
// executeGet performs GET requests with retry logic and caching.
|
||||
func executeGet(
|
||||
ctx context.Context,
|
||||
auditor *audit.Auditor,
|
||||
reqFunc func(context.Context, string) (*retryablehttp.Request, error),
|
||||
userToken, url string,
|
||||
incomingHeaders http.Header,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
tokenManager := config.GlobalConfig.TokenManager
|
||||
|
||||
// Retrieve the token
|
||||
token, err := retrieveToken(tokenManager, userToken)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Make the HTTP request
|
||||
resp, err := makeRequest(ctx, auditor, reqFunc, token, url)
|
||||
if err != nil {
|
||||
// Mark the token as timed out if the request failed
|
||||
tokenManager.MarkTokenStatus(token, token_manager.TimedOut)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Handle the response based on the status code
|
||||
if resp.StatusCode == http.StatusOK {
|
||||
// Mark the token as good if the response is OK
|
||||
tokenManager.MarkTokenStatus(token, token_manager.Good)
|
||||
|
||||
// Handle caching logic after receiving an HTTP 200 response
|
||||
cachingResult := manageCaching(url, userToken, incomingHeaders, resp)
|
||||
if cachingResult.FromCache {
|
||||
return cachingResult.Response, nil
|
||||
}
|
||||
|
||||
return cachingResult.Response, nil
|
||||
}
|
||||
|
||||
// Handle non-OK status codes
|
||||
err = i18n.Errorf("HTTP status code: %d", resp.StatusCode)
|
||||
// Mark the token as timed out for non-OK responses
|
||||
tokenManager.MarkTokenStatus(token, token_manager.TimedOut)
|
||||
|
||||
// Check if the context has been canceled or timed out
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
default:
|
||||
// Return the error without retrying
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// retryRequest handles the logic for executing HTTP requests with automatic retries and token management.
|
||||
func retryRequest(
|
||||
ctx context.Context,
|
||||
auditor *audit.Auditor,
|
||||
reqFunc func(context.Context, string) (*retryablehttp.Request, error),
|
||||
userToken string,
|
||||
isPost bool,
|
||||
url string,
|
||||
incomingHeaders http.Header,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
if isPost {
|
||||
return executePost(ctx, auditor, reqFunc, userToken, url)
|
||||
}
|
||||
|
||||
// Determine caching policy before we send a request
|
||||
policy := determineCachePolicy(url, userToken, incomingHeaders)
|
||||
if policy.ShouldUseCached && policy.CachedResponse != nil {
|
||||
return policy.CachedResponse, nil
|
||||
}
|
||||
|
||||
return executeGet(ctx, auditor, reqFunc, userToken, url, incomingHeaders)
|
||||
}
|
||||
|
||||
// API_GET performs a GET request to the Pixiv API with automatic retries and caching.
|
||||
func API_GET(
|
||||
ctx context.Context,
|
||||
@@ -400,13 +367,12 @@ func API_GET(
|
||||
userToken string,
|
||||
incomingHeaders http.Header,
|
||||
) (*SimpleHTTPResponse, error) {
|
||||
return retryRequest(ctx, auditor, func(ctx context.Context, token string) (*retryablehttp.Request, error) {
|
||||
return handleRequest(ctx, auditor, func(ctx context.Context, token string) (*http.Request, error) {
|
||||
// Create a new GET request for the specified URL.
|
||||
req, err := retryablehttp.NewRequest("GET", url, nil)
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
req.Header.Add("User-Agent", config.GetRandomUserAgent())
|
||||
req.Header.Add("Accept-Language", config.GlobalConfig.AcceptLanguage)
|
||||
@@ -488,22 +454,22 @@ func API_POST(
|
||||
return nil, i18n.Error("userToken is required for POST requests")
|
||||
}
|
||||
|
||||
resp, err := retryRequest(ctx, auditor, func(ctx context.Context, token string) (*retryablehttp.Request, error) {
|
||||
var req *retryablehttp.Request
|
||||
return handleRequest(ctx, auditor, func(ctx context.Context, token string) (*http.Request, error) {
|
||||
var req *http.Request
|
||||
var err error
|
||||
|
||||
// Determine the type of payload and construct the request accordingly.
|
||||
switch v := payload.(type) {
|
||||
case string:
|
||||
// If the payload is a string, send it as a raw byte buffer.
|
||||
req, err = retryablehttp.NewRequest("POST", url, bytes.NewBuffer([]byte(v)))
|
||||
req, err = http.NewRequestWithContext(ctx, "POST", url, bytes.NewBuffer([]byte(v)))
|
||||
case map[string]string:
|
||||
// If the payload is a map, construct multipart form data.
|
||||
body, formContentType, err := createMultipartFormData(v)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req, err = retryablehttp.NewRequest("POST", url, body)
|
||||
req, err = http.NewRequestWithContext(ctx, "POST", url, body)
|
||||
if err == nil {
|
||||
// Update the content type to reflect multipart form data.
|
||||
contentType = formContentType
|
||||
@@ -517,8 +483,6 @@ func API_POST(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req = req.WithContext(ctx)
|
||||
|
||||
req.Header.Add("User-Agent", config.GetRandomUserAgent())
|
||||
req.Header.Add("Accept", "application/json")
|
||||
req.Header.Add("x-csrf-token", csrf)
|
||||
@@ -531,15 +495,6 @@ func API_POST(
|
||||
|
||||
return req, nil
|
||||
}, userToken, true, url, incomingHeaders)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("API request failed with status code: %d, body: %s", resp.StatusCode, resp.Body)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ProxyRequest forwards an incoming HTTP request to a target server and writes the response back to the original client.
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
# Exponential backoff
|
||||
|
||||
PixivFE implements exponential backoff as a strategy for handling API request failures and managing token usage. This document outlines the implementation details of this feature across two key components of the application.
|
||||
|
||||
## Overview
|
||||
|
||||
Exponential backoff is a technique used to gradually increase the wait time between retries of a failed operation. In PixivFE, this technique is applied at two levels:
|
||||
|
||||
1. API request level
|
||||
2. Token management level
|
||||
|
||||
### Configuration
|
||||
|
||||
The `ServerConfig` struct in [`config/config.go`](https://codeberg.org/VnPower/PixivFE/src/branch/v2/config/config.go) includes fields for both API request level and token management level backoff settings.
|
||||
|
||||
The `LoadConfig` method sets default values for these settings if they are not provided through environment variables.
|
||||
|
||||
## API request level backoff
|
||||
|
||||
**Location: `core/requests.go`**
|
||||
|
||||
PixivFE uses the `retryablehttp` package to implement exponential backoff for API requests. The implementation is as follows:
|
||||
|
||||
1. A `retryablehttp.Client` is initialized in the `init` function:
|
||||
|
||||
```go
|
||||
func init() {
|
||||
retryClient = retryablehttp.NewClient()
|
||||
retryClient.RetryMax = config.GlobalConfig.APIMaxRetries
|
||||
retryClient.RetryWaitMin = config.GlobalConfig.APIBaseTimeout
|
||||
retryClient.RetryWaitMax = config.GlobalConfig.APIMaxBackoffTime
|
||||
retryClient.HTTPClient = utils.HttpClient
|
||||
}
|
||||
```
|
||||
|
||||
2. The `retryRequest` function uses this client to perform requests with automatic retries:
|
||||
|
||||
```go
|
||||
func retryRequest(ctx context.Context, reqFunc func(context.Context, string) (*retryablehttp.Request, error)) (SimpleHTTPResponse, error) {
|
||||
// ... (function implementation)
|
||||
}
|
||||
```
|
||||
|
||||
## Token management level backoff
|
||||
|
||||
**Location: `server/token_manager/token_manager.go`**
|
||||
|
||||
The `TokenManager` implements exponential backoff for individual tokens:
|
||||
|
||||
- In the `MarkTokenStatus` method, when a token is marked as `TimedOut`, it calculates a timeout duration:
|
||||
```go
|
||||
timeoutDuration := time.Duration(math.Min(
|
||||
float64(tm.baseTimeout)*math.Pow(2, float64(token.FailureCount-1)),
|
||||
float64(tm.maxBackoffTime),
|
||||
))
|
||||
```
|
||||
- This calculation uses the `math.Pow` function to implement exponential growth based on the number of consecutive failures.
|
||||
- The timeout duration is also capped at a maximum value (`tm.maxBackoffTime`).
|
||||
- The token's `TimeoutUntil` is set to the current time plus this calculated duration.
|
||||
|
||||
This approach allows tokens that repeatedly fail increasingly longer "cool-down" periods before being used again, helping to manage rate limiting of individual tokens by the Pixiv API.
|
||||
@@ -137,43 +137,13 @@ You can disable periodic checks by setting the value to `0`. Then, proxies will
|
||||
|
||||
## Exponential backoff configuration
|
||||
|
||||
PixivFE implements exponential backoff for API requests and token management to handle failures gracefully and manage rate limiting. The following environment variables can be used to configure this behavior, fine-tuning the exponential backoff behavior for both API requests and token management. If not set, the default values will be used.
|
||||
PixivFE implements exponential backoff for token management to manage rate limiting.
|
||||
|
||||
For more detailed information about the implementation of exponential backoff in PixivFE, please refer to the [Exponential Backoff documentation](../dev/features/exponential_backoff.md).
|
||||
The following environment variables control how PixivFE manages token timeouts when a token encounters repeated failures. The backoff time for a token starts at the base timeout and doubles with each failure, up to the maximum backoff time.
|
||||
|
||||
### API request level backoff
|
||||
If not set, the default values will be used.
|
||||
|
||||
These settings control how PixivFE handles retries for individual API requests. The backoff time starts at the base timeout and doubles with each retry, up to the maximum backoff time.
|
||||
|
||||
#### `PIXIVFE_API_MAX_RETRIES`
|
||||
|
||||
**Required**: No
|
||||
|
||||
**Default:** `3`
|
||||
|
||||
Maximum number of retries for API requests.
|
||||
|
||||
#### `PIXIVFE_API_BASE_TIMEOUT`
|
||||
|
||||
**Required**: No
|
||||
|
||||
**Default:** `500ms`
|
||||
|
||||
Base timeout duration for API requests.
|
||||
|
||||
#### `PIXIVFE_API_MAX_BACKOFF_TIME`
|
||||
|
||||
**Required**: No
|
||||
|
||||
**Default:** `8000ms`
|
||||
|
||||
Maximum backoff time for API requests.
|
||||
|
||||
### Token management level backoff
|
||||
|
||||
These settings control how PixivFE manages token timeouts when a token encounters repeated failures. The backoff time for a token starts at the base timeout and doubles with each failure, up to the maximum backoff time.
|
||||
|
||||
#### `PIXIVFE_TOKEN_MAX_RETRIES`
|
||||
### `PIXIVFE_TOKEN_MAX_RETRIES`
|
||||
|
||||
**Required**: No
|
||||
|
||||
@@ -181,7 +151,7 @@ These settings control how PixivFE manages token timeouts when a token encounter
|
||||
|
||||
Maximum number of retries for token management.
|
||||
|
||||
#### `PIXIVFE_TOKEN_BASE_TIMEOUT`
|
||||
### `PIXIVFE_TOKEN_BASE_TIMEOUT`
|
||||
|
||||
**Required**: No
|
||||
|
||||
@@ -189,7 +159,7 @@ Maximum number of retries for token management.
|
||||
|
||||
Base timeout duration for token management.
|
||||
|
||||
#### `PIXIVFE_TOKEN_MAX_BACKOFF_TIME`
|
||||
### `PIXIVFE_TOKEN_MAX_BACKOFF_TIME`
|
||||
|
||||
**Required**: No
|
||||
|
||||
|
||||
@@ -14,7 +14,6 @@ require (
|
||||
github.com/go-faker/faker/v4 v4.5.0
|
||||
github.com/goccy/go-json v0.10.3
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||
github.com/hashicorp/golang-lru v1.0.2
|
||||
github.com/oklog/ulid/v2 v2.1.0
|
||||
github.com/sethvargo/go-envconfig v1.1.0
|
||||
@@ -30,7 +29,6 @@ require (
|
||||
|
||||
require (
|
||||
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
|
||||
@@ -8,8 +8,6 @@ github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsVi
|
||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/go-faker/faker/v4 v4.5.0 h1:ARzAY2XoOL9tOUK+KSecUQzyXQsUaZHefjyF8x6YFHc=
|
||||
github.com/go-faker/faker/v4 v4.5.0/go.mod h1:p3oq1GRjG2PZ7yqeFFfQI20Xm61DoBDlCA8RiSyZ48M=
|
||||
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
|
||||
@@ -18,20 +16,10 @@ github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB11/k=
|
||||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/oklog/ulid/v2 v2.1.0 h1:+9lhoxAP56we25tyYETBBY1YLA2SaoLvUFgrP2miPJU=
|
||||
github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
"core/requests.go:9UmoeR3swA0": "failed to make HTTP request: %w",
|
||||
"core/requests.go:XGjPq4l3s2o": "userToken is required for POST requests",
|
||||
"core/requests.go:XdMN7Q7DY3k": "failed to proxy request: %w",
|
||||
"core/requests.go:_IJGPWU-8jE": "max retries reached for GET request. Last error: %v",
|
||||
"core/requests.go:f78uqyomFJk": "Unsupported payload type",
|
||||
"core/requests.go:fEaOk30bc9I": "failed to read response body: %w",
|
||||
"core/requests.go:lLy9SHFUtQQ": "failed to copy response body: %w",
|
||||
|
||||
Reference in New Issue
Block a user