mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-06-22 04:42:48 +08:00
63 lines
1.7 KiB
Go
63 lines
1.7 KiB
Go
package httpfetch
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
)
|
|
|
|
// Doer abstracts the HTTP client used to execute requests.
|
|
type Doer interface {
|
|
Do(*http.Request) (*http.Response, error)
|
|
}
|
|
|
|
// GetBytes performs a GET request with the supplied headers, requires a
|
|
// success status, and returns the response body. When maxSize is positive
|
|
// the body is rejected once it exceeds maxSize bytes.
|
|
func GetBytes(ctx context.Context, client Doer, requestURL string, headers map[string]string, maxSize int64) ([]byte, error) {
|
|
if client == nil {
|
|
client = http.DefaultClient
|
|
}
|
|
req, errRequest := http.NewRequestWithContext(ctx, http.MethodGet, requestURL, nil)
|
|
if errRequest != nil {
|
|
return nil, fmt.Errorf("create request: %w", errRequest)
|
|
}
|
|
for key, value := range headers {
|
|
if value != "" {
|
|
req.Header.Set(key, value)
|
|
}
|
|
}
|
|
|
|
resp, errDo := client.Do(req)
|
|
if errDo != nil {
|
|
return nil, fmt.Errorf("request failed: %w", errDo)
|
|
}
|
|
defer func() {
|
|
if errClose := resp.Body.Close(); errClose != nil {
|
|
log.WithError(errClose).Debug("failed to close response body")
|
|
}
|
|
}()
|
|
|
|
if resp.StatusCode < http.StatusOK || resp.StatusCode >= http.StatusMultipleChoices {
|
|
body, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
|
return nil, fmt.Errorf("unexpected status %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
|
|
}
|
|
|
|
reader := io.Reader(resp.Body)
|
|
if maxSize > 0 {
|
|
reader = io.LimitReader(resp.Body, maxSize+1)
|
|
}
|
|
data, errRead := io.ReadAll(reader)
|
|
if errRead != nil {
|
|
return nil, fmt.Errorf("read response: %w", errRead)
|
|
}
|
|
if maxSize > 0 && int64(len(data)) > maxSize {
|
|
return nil, fmt.Errorf("response exceeds maximum allowed size of %d bytes", maxSize)
|
|
}
|
|
return data, nil
|
|
}
|