v1.0.0 #1

Merged
kor-elf merged 32 commits from develop into main 2026-03-15 20:36:00 +05:00
Showing only changes of commit cc0dc64d91 - Show all commits

93
blocklist.go Normal file
View File

@@ -0,0 +1,93 @@
package blocklist
import (
"context"
"fmt"
"net/http"
"net/url"
"time"
"git.kor-elf.net/kor-elf-shield/blocklist/parser"
)
const (
// contextTimeout defines the maximum duration for context operations before timing out.
contextTimeout = 15 * time.Second
// requestTimeout defines the maximum duration for request operations before timing out.
requestTimeout = 20 * time.Second
)
// Config defines the configuration for the blocklist.
type Config struct {
// Limit specifies the maximum number of items to process or validate.
Limit uint
// Validator specifies the IP validator to use.
Validator parser.IPValidator
// ContextTimeout defines the maximum duration for context operations before timing out.
ContextTimeout time.Duration
// RequestTimeout defines the maximum duration for request operations before timing out.
RequestTimeout time.Duration
}
// NewConfig creates a new Config with default values.
func NewConfig(limit uint) Config {
return Config{
Limit: limit,
Validator: &parser.DefaultIPValidator{},
ContextTimeout: contextTimeout,
RequestTimeout: requestTimeout,
}
}
// NewConfigWithValidator creates a new Config with the specified validator.
func NewConfigWithValidator(limit uint, validator parser.IPValidator) Config {
return Config{
Limit: limit,
Validator: validator,
ContextTimeout: contextTimeout,
RequestTimeout: requestTimeout,
}
}
// Get fetches data from the given URL, parses the response using the provided parser, and applies the given configuration.
// It returns the parsed IPs and any errors that occurred during the process.
func Get(fileUrl string, parser parser.Parser, c Config) (parser.IPs, error) {
parsedURL, err := url.Parse(fileUrl)
if err != nil {
return nil, fmt.Errorf("invalid url: %w", err)
}
if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
return nil, fmt.Errorf("invalid url scheme: %s", parsedURL.Scheme)
}
ctx, cancel := context.WithTimeout(context.Background(), c.ContextTimeout)
defer cancel()
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fileUrl, nil)
if err != nil {
return nil, fmt.Errorf("create request: %w", err)
}
client := &http.Client{
Timeout: c.RequestTimeout,
}
res, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("request failed: %w", err)
}
defer func() {
_ = res.Body.Close()
}()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("unexpected status code: %d", res.StatusCode)
}
return parser.Parse(res.Body, c.Validator, c.Limit)
}