fetch

package
v0.0.0-...-0d1d0b3 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2025 License: BSD-3-Clause Imports: 21 Imported by: 0

README

Fetch

Each request is saved in a separaated file.

## File path

The path for scheme://host/... in base directory is base/{scheme}/{host}/{ID}.http

The ID is the SHA256 in hexadecimal of:

METHOD\n
URL\n
HEADER1: VALUE1.1\n
HEADER1: VALUE1.2\n
HEADER2: VALUE2.1\n
\n
BODY...\n

[!NOTE] A newline at end. The newline character is \n or 0x0A. The header name is Aaaa-Bbbb-Cccc.

Example

GET
https://example.com/file?a=1&b=2
Accept-Encoding: application/json

Hello World!

Result: 150ee78242120c0e38fc747a175c56068c2f07f8b0c57345a7ee6cdd5a172d05

Format

"HTTP" json_len:big_endian_uint32 json:[json_len]byte responseBody:[...]byte

The json contain meta info of the request in json:

NOTE: At end of JSON, add two \n\n only for display file. This two byte are included in the json length.

{
	"time": "yyyy-mm-ddThh:mm:ss.nnnnnnnnnZ",
	"requestMethod": "GET",
	"requestURL": "https://example.net/dir/file.txt?a=1",
	"requestHeader": {
		"header1": ["value1", "value2"]
	},
	"requestBody": "<base64 of the body>",
	"status": 200,
	"responseHeader": {
		"header1": ["value1", "value2"]
	}
}

{
	"time": "2024-11-12T22:44:59.862240355Z",
	"requestMethod": "GET",
	"requestURL": "https://example.net/dir/file.txt?a=1",
	"requestHeader": {
		"K1": ["v1"],
		"K2": ["v2"]
	},
	"requestBody": "Ym9keQ==",
	"status": 200,
	"responseHeader": {
		"H1": ["v1","v2"]
	}
}

Documentation

Overview

Make HTTP requests.

Index

Constants

View Source
const (
	DebugKeepIgnore = iota
	DebugKeepIndex
	DebugKeepData
)

Variables

This section is empty.

Functions

func ClearCache

func ClearCache(fsys writefs.CompleteFS, filters ...func(*Meta) time.Duration) error

Clear cache.

Each filter return a duration to keep the request. If meta.Time < now+maxAge => remove it. The filter should not the edit meta.

func Debug

func Debug(fsys writefs.CompleteFS, keeper func(m *Meta) int) error

Debug create cacheRoot/index.html with a index of all cache request. The keeper return a const like DebugKeepIgnore.

func SaveHTTP

func SaveHTTP(request *Request, response *Response, now time.Time, w io.Writer) error

Write meta information then response body into w writer. See README.md for format details.

Types

type Fetcher

type Fetcher interface {
	// Make a HTTP GET request and return response.
	// If response code is out of [200,299] return an error.
	// Return fs.ErrNotExist if the fetcher is a cache, and not found the response.
	Fetch(*Request) (*Response, error)
	// Static name of the fetcher: net, cache...
	// Use this for the log
	Name() string
}

func Cache

func Cache(fs writefs.Opener) Fetcher

func Net

func Net(roundTripper http.RoundTripper, cache writefs.CreateOpener, delay map[string]time.Duration) Fetcher

func Test

func Test(m ...*Meta) Fetcher

Create a Fetcher for testing. Use Request.T or Request.Ts functions for create Meta struct.

type Meta

type Meta struct {
	Time time.Time `json:"time"`

	Method        string      `json:"requestMethod"`
	RawURL        string      `json:"requestURL"`
	URL           *url.URL    `json:"-"`
	RequestHeader http.Header `json:"requestHeader"`
	RequestBody   []byte      `json:"requestBody"`

	Status         int         `json:"status"`
	ResponseHeader http.Header `json:"responseHeader"`

	// Response body used only for test
	ResponseBody []byte `json:"-"`
	// contains filtered or unexported fields
}

Information about a request and response, saved in cache file or used for the test.

func ReadMeta

func ReadMeta(r io.ReadCloser) (*Meta, error)

Read meta data and close the reader.

func ReadOnlyMeta

func ReadOnlyMeta(r io.Reader) (*Meta, error)

Read only header of the file, then you can read the body.

func (*Meta) ID

func (m *Meta) ID() string

Calculate the ID with Request.ID. Cache the id, so you must not edit m after this method call.

func (*Meta) Path

func (m *Meta) Path() string

Return the path where save the request. Use Meta.ID method, so you must not edit m after this method call.

type Request

type Request struct {
	Method string
	URL    *url.URL
	Header http.Header

	Body []byte
	// contains filtered or unexported fields
}

func Fmt

func Fmt(format string, a ...any) *Request

Like URL but call fmt.Sprintf to create the url.

func R

func R(method, rawURL string, body []byte, headers ...string) *Request

Easy way to create a request. If error, create a request with url: scheme=err, path=rawURL.

Headers is key1, value1, key2, value2 ... If headers length is odd, the last element is ignored.

func Rs

func Rs(method, rawURL, body string, headers ...string) *Request

Like R with body as string.

func URL

func URL(rawURL string) *Request

Create a GET *Request from a URL. If error, create a request with url: scheme=err, path=rawURL.

func (*Request) ID

func (r *Request) ID() string

Cononize the request and return the identifier. The ID is a hash of all fields encoded in hexadecimal.

The ID is saved in the request, so after call to this method, you must not edit the request.

func (*Request) Path

func (r *Request) Path() string

func (*Request) T

func (r *Request) T(status int, body []byte, headers ...string) *Meta

Create a Meta struct to use with Test. Headers is key1, value1, key2, value2 ... If headers length is odd, the last element is ignored.

func (*Request) Ts

func (r *Request) Ts(status int, body string, headers ...string) *Meta

Like Request.T with a string body.

type Response

type Response struct {
	Status int // e.g. 200
	Header http.Header
	Body   io.ReadCloser
}

func ReadResponse

func ReadResponse(r io.ReadCloser) (*Response, error)

Jump to

Keyboard shortcuts

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