### Create a Builder with requests.URL or requests.New Source: https://context7.com/earthboundkid/requests/llms.txt Use `requests.URL` to start from a base URL string or `requests.New` with configuration functions to create a new Builder. This is useful for setting up shared API client configurations. ```go import "github.com/carlmjohnson/requests" // Start from a base URL b := requests.URL("https://api.example.com/v1") // Start from Config functions (useful for shared API clients) apiClient := requests.New(func(rb *requests.Builder) { rb.BaseURL("https://api.example.com/v1"). Bearer("my-api-token"). Accept("application/json") }) ``` -------------------------------- ### Simple GET Request to String in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Compares the verbose net/http approach with the concise requests.Builder for fetching a URL's content into a string. ```go req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://example.com", nil) if err != nil { // ... } res, err := http.DefaultClient.Do(req) if err != nil { // ... } deferr res.Body.Close() b, err := io.ReadAll(res.Body) if err != nil { // ... } s := string(b) ``` ```go var s string err := requests. URL("http://example.com"). ToString(&s). Fetch(ctx) ``` -------------------------------- ### HTTP Method Shortcuts Source: https://context7.com/earthboundkid/requests/llms.txt Shows how to explicitly set HTTP methods like PUT, DELETE, and HEAD. By default, GET is used for requests without a body, and POST for requests with a body. Use these methods to override the default behavior. ```go ctx := context.Background() // PUT err := requests. URL("https://jsonplaceholder.typicode.com/posts/1"). Put(). BodyJSON(map[string]any{"title": "updated", "body": "content", "userId": 1}). CheckStatus(200). Fetch(ctx) // DELETE err = requests. URL("https://jsonplaceholder.typicode.com/posts/1"). Delete(). CheckStatus(200). Fetch(ctx) // HEAD — capture response headers headers := make(map[string][]string) err = requests. URL("https://example.com"). ToHeaders(headers). Fetch(ctx) fmt.Println(headers["Content-Type"]) ``` -------------------------------- ### Bearer Token Authentication Example Source: https://github.com/earthboundkid/requests/blob/main/testdata/httpbin bearer good ZmpvxtBj.res.txt This example demonstrates how to make a request to an HTTPBin endpoint that requires bearer token authentication. The response indicates whether the authentication was successful. ```APIDOC ## GET /bearer ### Description This endpoint tests bearer token authentication. It returns information about the authentication status. ### Method GET ### Endpoint /bearer ### Parameters #### Query Parameters None #### Request Body None ### Request Example ```bash curl -H "Authorization: Bearer ZmpvxtBj" https://httpbin.org/bearer ``` ### Response #### Success Response (200) - **authenticated** (boolean) - Indicates if the request was successfully authenticated. - **token** (string) - The token that was provided in the request. #### Response Example ```json { "authenticated": true, "token": "ZmpvxtBj" } ``` ``` -------------------------------- ### GET Response Body as String Source: https://github.com/earthboundkid/requests/wiki/Home Fetches the response body of a GET request and stores it as a string. Ensure the URL is valid and accessible. ```go var s string err := requests. URL("http://example.com"). ToString(&s). Fetch(context.Background()) ``` -------------------------------- ### GET JSON Object Request in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Shows how to fetch a JSON object from an API and unmarshal it into a Go struct, comparing net/http with requests. ```go var post placeholder u, err := url.Parse("https://jsonplaceholder.typicode.com") if err != nil { // ... } u.Path = fmt.Sprintf("/posts/%d", 1) req, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil) if err != nil { // ... } res, err := http.DefaultClient.Do(req) if err != nil { // ... } deferr res.Body.Close() b, err := io.ReadAll(res.Body) if err != nil { // ... } err := json.Unmarshal(b, &post) if err != nil { // ... } ``` ```go var post placeholder err := requests. URL("https://jsonplaceholder.typicode.com"). Pathf("/posts/%d", 1). ToJSON(&post). Fetch(ctx) ``` -------------------------------- ### Get Cookies Source: https://github.com/earthboundkid/requests/blob/main/testdata/httpbin cookies set SMVCLa3m.req.txt This endpoint demonstrates how to send cookies in an HTTP request and have them echoed back. ```APIDOC ## GET /cookies HTTP/0.0 ### Description This endpoint echoes back any cookies sent in the request. ### Method GET ### Endpoint /cookies ### Request Headers - **Host**: httpbin.org - **Cookie**: chocolate=chip - **Referer**: http://httpbin.org/cookies/set/chocolate/chip ### Response #### Success Response (200) - **cookies** (object) - A dictionary of cookies sent in the request. ``` -------------------------------- ### POST JSON Object and Parse Response in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Example of sending a JSON object in the request body and parsing the JSON response into a Go struct using the requests library. ```go var res placeholder req := placeholder{ Title: "foo", Body: "baz", UserID: 1, } err := requests. URL("/posts"). Host("jsonplaceholder.typicode.com"). BodyJSON(&req). ToJSON(&res). Fetch(ctx) // net/http equivalent left as an exercise for the reader ``` -------------------------------- ### HTTP Method Shortcuts Source: https://context7.com/earthboundkid/requests/llms.txt Provides explicit methods for common HTTP methods (PUT, DELETE, HEAD) to override the default GET or POST behavior. ```APIDOC ## HTTP Method Shortcuts — `Post`, `Put`, `Patch`, `Delete`, `Head` Explicit method setters. By default, a Builder without a body issues a `GET`; a Builder with any body setter automatically uses `POST`. Use these methods to override. ```go ctx := context.Background() // PUT err := requests. URL("https://jsonplaceholder.typicode.com/posts/1"). Put(). BodyJSON(map[string]any{"title": "updated", "body": "content", "userId": 1}). CheckStatus(200). Fetch(ctx) // DELETE err = requests. URL("https://jsonplaceholder.typicode.com/posts/1"). Delete(). CheckStatus(200). Fetch(ctx) // HEAD — capture response headers headers := make(map[string][]string) err = requests. URL("https://example.com"). ToHeaders(headers). Fetch(ctx) fmt.Println(headers["Content-Type"]) ``` ``` -------------------------------- ### GET JSON Object Source: https://github.com/earthboundkid/requests/wiki/Home Retrieves a JSON object from a URL and decodes it into a Go struct. The struct must be defined to match the JSON structure. ```go var data SomeDataType err := requests. URL("https://example.com/my-json"). ToJSON(&data). Fetch(context.Background()) ``` -------------------------------- ### Setting Common HTTP Headers Source: https://context7.com/earthboundkid/requests/llms.txt Demonstrates setting various common HTTP headers like User-Agent, Accept, Bearer token, custom headers, Cache-Control, and Cookies using convenience methods. Ensure all necessary headers are set before fetching. ```go ctx := context.Background() var resp struct{ JSON struct{ Foo string } } err := requests. URL("https://postman-echo.com/post"). UserAgent("my-app/1.0"). Accept("application/json"). Bearer("secret-token"). Header("X-Request-ID", "abc-123"). CacheControl("no-cache"). Cookie("session", "xyz"). BodyJSON(map[string]string{"foo": "bar"}). ToJSON(&resp). Fetch(ctx) if err != nil { log.Fatal(err) } ``` -------------------------------- ### requests.URL and requests.New - Create a Builder Source: https://context7.com/earthboundkid/requests/llms.txt Demonstrates how to create a new Builder instance using either a base URL string or a series of configuration functions. ```APIDOC ## `requests.URL` / `requests.New` — Create a Builder `requests.URL(baseurl)` creates a new `Builder` from a base URL string. `requests.New(cfgs...)` creates a blank Builder and applies one or more `Config` functions to it. ```go import "github.com/carlmjohnson/requests" // Start from a base URL b := requests.URL("https://api.example.com/v1") // Start from Config functions (useful for shared API clients) apiClient := requests.New(func(rb *requests.Builder) { rb.BaseURL("https://api.example.com/v1"). Bearer("my-api-token"). Accept("application/json") }) ``` ``` -------------------------------- ### Define and Apply Reusable Configs with Builder.Config Source: https://context7.com/earthboundkid/requests/llms.txt Use `Config` callbacks to bundle multiple `Builder` options for reuse. Define custom functions that accept a `*Builder` and apply options like authentication or timeouts. ```go // Define reusable configs func WithAuth(token string) requests.Config { return func(rb *requests.Builder) { rb.Bearer(token).Header("X-Client", "my-app/1.0") } } func WithTimeout(d time.Duration) requests.Config { return func(rb *requests.Builder) { cl := &http.Client{Timeout: d} rb.Client(cl) } } ``` ```go var result map[string]any err := requests. URL("https://api.example.com/data"). Config( WithAuth(os.Getenv("TOKEN")), WithTimeout(10*time.Second), ). ToJSON(&result). Fetch(context.Background()) ``` -------------------------------- ### URL Building Methods: Path, Param, Params Source: https://context7.com/earthboundkid/requests/llms.txt Methods like `Path`, `Pathf`, `Param`, `ParamInt`, and `Params` allow for flexible construction of the request URL. `Param` overwrites existing values, while `ParamOptional` sets a parameter only if it's not already set and the value is non-blank. ```go ctx := context.Background() var posts []struct { ID int `json:"id"` UserID int `json:"userId"` Title string `json:"title"` } err := requests. URL("https://jsonplaceholder.typicode.com"). Path("/posts"). Param("userId", "1"). ParamInt("_limit", 5). Params(map[string][]string{"_sort": {"id"}, "_order": {"desc"}}). ToJSON(&posts). Fetch(ctx) if err != nil { log.Fatal(err) } // Fetches: https://jsonplaceholder.typicode.com/posts?userId=1&_limit=5&_sort=id&_order=desc fmt.Println(len(posts)) // 5 ``` -------------------------------- ### Fetch: Build, Send, and Handle HTTP Requests Source: https://context7.com/earthboundkid/requests/llms.txt The `Fetch` method combines request building, sending, and response handling into a single call. It's the primary entry point for issuing requests and automatically handles response body deserialization into a provided struct. ```go ctx := context.Background() var result struct { ID int `json:"id"` Title string `json:"title"` } err := requests. URL("https://jsonplaceholder.typicode.com"). Pathf("/posts/%d", 1). ToJSON(&result). Fetch(ctx) if err != nil { log.Fatal(err) } fmt.Println(result.Title) // "sunt aut facere repellat provident occaecati..." ``` -------------------------------- ### URL Building - Path, Pathf, Host, Hostf, Scheme, Param, ParamInt, Params Source: https://context7.com/earthboundkid/requests/llms.txt Explains the various methods available for composing the request URL, including setting paths, hosts, schemes, and query parameters. ```APIDOC ## URL Building — `Path`, `Pathf`, `Host`, `Hostf`, `Scheme`, `Param`, `ParamInt`, `Params` Methods for composing the request URL. `Path` joins paths per RFC 3986 (absolute paths override, relative paths resolve). `Param` overwrites existing values for a key; `ParamOptional` sets a param only if not already set and the value is non-blank. ```go ctx := context.Background() var posts []struct { ID int `json:"id"` UserID int `json:"userId"` Title string `json:"title"` } err := requests. URL("https://jsonplaceholder.typicode.com"). Path("/posts"). Param("userId", "1"). ParamInt("_limit", 5). Params(map[string][]string{"_sort": {"id"}, "_order": {"desc"}}). ToJSON(&posts). Fetch(ctx) if err != nil { log.Fatal(err) } // Fetches: https://jsonplaceholder.typicode.com/posts?userId=1&_limit=5&_sort=id&_order=desc fmt.Println(len(posts)) // 5 ``` ``` -------------------------------- ### Separate Request Building and Execution with Request/Do Source: https://context7.com/earthboundkid/requests/llms.txt Use `Request(ctx)` to build an `*http.Request` without sending it, and `Do(req)` to execute a pre-built request. This is useful for inspecting the request before sending or for testing purposes. ```go ctx := context.Background() b := requests.URL("https://api.example.com/data"). Bearer("token123"). ToJSON(&result) req, err := b.Request(ctx) if err != nil { log.Fatal(err) } log.Printf("About to call: %s %s", req.Method, req.URL) if err = b.Do(req); err != nil { log.Fatal(err) } ``` -------------------------------- ### Builder.Fetch - Build, Send, and Handle in One Call Source: https://context7.com/earthboundkid/requests/llms.txt Explains how to use the Fetch method to combine request building, sending, validation, and response handling into a single operation. ```APIDOC ## `Builder.Fetch` — Build, Send, and Handle in One Call `Fetch(ctx)` combines `Request` (build the `http.Request`) and `Do` (execute, validate, handle) into a single call. It is the primary entry point for issuing requests. ```go ctx := context.Background() var result struct { ID int `json:"id"` Title string `json:"title"` } err := requests. URL("https://jsonplaceholder.typicode.com"). Pathf("/posts/%d", 1). ToJSON(&result). Fetch(ctx) if err != nil { log.Fatal(err) } fmt.Println(result.Title) // "sunt aut facere repellat provident occaecati..." ``` ``` -------------------------------- ### Headers Source: https://context7.com/earthboundkid/requests/llms.txt Demonstrates setting common HTTP headers using convenience methods like UserAgent, Accept, Bearer, Header, CacheControl, and Cookie. ```APIDOC ## Headers — `Header`, `HeaderOptional`, `Accept`, `ContentType`, `UserAgent`, `Bearer`, `BasicAuth`, `CacheControl`, `Cookie` Convenience methods for common HTTP headers. `HeaderOptional` sets a header only if not already assigned, which is useful for defaults in shared builders. `Cookie` accumulates cookies without overwriting. ```go ctx := context.Background() var resp struct{ JSON struct{ Foo string } } err := requests. URL("https://postman-echo.com/post"). UserAgent("my-app/1.0"). Accept("application/json"). Bearer("secret-token"). Header("X-Request-ID", "abc-123"). CacheControl("no-cache"). Cookie("session", "xyz"). BodyJSON(map[string]string{"foo": "bar"}). ToJSON(&resp). Fetch(ctx) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Set Custom Headers for a Request in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Demonstrates setting custom headers, including User-Agent and Content-Type, for an HTTP request using the requests library. ```go // Set headers var headers postman err := requests. URL("https://postman-echo.com/get"). UserAgent("bond/james-bond"). ContentType("secret"). Header("martini", "shaken"). Fetch(ctx) ``` -------------------------------- ### Clone Builder for Shared Configuration Source: https://context7.com/earthboundkid/requests/llms.txt Use Clone() to create an independent copy of a Builder. This allows sharing base configurations while making request-specific modifications safely, including for concurrent use. ```go // Define a shared API client once apiBase := requests.URL("https://api.example.com/v2"). Bearer(os.Getenv("API_TOKEN")), Accept("application/json"), UserAgent("my-service/1.0") // Clone and extend per request var user struct{ Name string } err := apiBase.Clone(). Pathf("/users/%d", 42), ToJSON(&user). Fetch(ctx) var posts []struct{ Title string } err = apiBase.Clone(). Path("/posts"), ParamInt("user_id", 42), ToJSON(&posts). Fetch(ctx) ``` -------------------------------- ### POST Raw Body Request in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Demonstrates sending a raw byte slice as a POST request body, contrasting net/http with the requests library. ```go body := bytes.NewReader(([]byte(`hello, world`)) req, err := http.NewRequestWithContext(ctx, http.MethodPost, "https://postman-echo.com/post", body) if err != nil { // ... } req.Header.Set("Content-Type", "text/plain") res, err := http.DefaultClient.Do(req) if err != nil { // ... } deferr res.Body.Close() _, err := io.ReadAll(res.Body) if err != nil { // ... } ``` ```go err := requests. URL("https://postman-echo.com/post"). BodyBytes([]byte(`hello, world`)). ContentType("text/plain"). Fetch(ctx) ``` -------------------------------- ### Create Progress Bar Response Handler Source: https://github.com/earthboundkid/requests/wiki/Home Implements a custom ResponseHandler to display a progress bar during file downloads using the 'schollz/progressbar' library. This handler manages temporary files and renames them upon successful download. ```go func withProgbar(dstFile string) requests.ResponseHandler { return func(res *http.Response) error { absFile, err := filepath.Abs(dstFile) if err != nil { return err } dir, file := filepath.Split(absFile) _ = os.MkdirAll(dir, 0744) tmpFile, err := os.CreateTemp(dir, ".*. "+file) if err != nil { return err } defer os.Remove(tmpFile.Name()) defer tmpFile.Close() fmt.Println("downloading to", tmpFile.Name()) bar := progressbar.DefaultBytes( res.ContentLength, fmt.Sprintf("downloading %s", file), ) if _, err = io.Copy( io.MultiWriter(bar, tmpFile), res.Body, ); err != nil { return err } if err = tmpFile.Close(); err != nil { return err } fmt.Println("download succeeded") if err = os.Rename(tmpFile.Name(), absFile); err != nil { return err } fmt.Println("moved to", absFile) return nil } } ``` -------------------------------- ### Manipulate URLs and Query Parameters in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Shows how to dynamically build and modify URLs, including hostnames and query parameters, using the requests library's fluent API. ```go u, err := requests. URL("https://prod.example.com/get?a=1&b=2"). Hostf("%s.example.com", "dev1"). Param("b", "3"). ParamInt("c", 4). URL() if err != nil { /* ... */ } fmt.Println(u.String()) // https://dev1.example.com/get?a=1&b=3&c=4 ``` -------------------------------- ### Replay Recorded HTTP Responses with reqtest.Replay Source: https://context7.com/earthboundkid/requests/llms.txt Employ reqtest.Replay in unit tests for fast, offline, and deterministic execution. It reads previously recorded responses from the filesystem. ```go // Replay in unit tests (fast, offline, deterministic) func TestFetch(t *testing.T) { var result string err := requests. URL("https://example.com"). Transport(reqtest.Replay("testdata/fixtures")). ToString(&result). Fetch(context.Background()) if err != nil { t.Fatal(err) } // result matches the recorded response } ``` -------------------------------- ### Replay HTTP Responses from Embedded FS with reqtest.ReplayFS Source: https://context7.com/earthboundkid/requests/llms.txt Utilize reqtest.ReplayFS with an embedded filesystem (go:embed) for self-contained test binaries. This avoids external file dependencies. ```go // Use an embedded FS for self-contained test binaries //go:embed testdata/fixtures var fixtures embed.FS func TestFetchEmbedded(t *testing.T) { subFS, _ := fs.Sub(fixtures, "testdata/fixtures") err := requests. URL("https://example.com"). Transport(reqtest.ReplayFS(subFS)). Fetch(context.Background()) if err != nil { t.Fatal(err) } } ``` -------------------------------- ### Record and Replay HTTP Requests in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Record outgoing HTTP requests to the file system for later replay. Useful for testing and mocking external services. Ensure the directory exists before recording. ```go // record a request to the file system var s1, s2 string err := requests.URL("http://example.com"). Transport(reqtest.Record(nil, "somedir")), ToString(&s1). Fetch(ctx) check(err) // now replay the request in tests err = requests.URL("http://example.com"). Transport(reqtest.Replay("somedir")), ToString(&s2). Fetch(ctx) check(err) assert(s1 == s2) // true ``` -------------------------------- ### Gzip-Compressed Request Body Source: https://context7.com/earthboundkid/requests/llms.txt Shows how to send a gzip-compressed request body using `Config` and `GzipConfig`. This automatically sets the `Content-Encoding: gzip` header. Ensure the `gzip.Writer` is properly closed. ```go ctx := context.Background() err := requests. URL("https://postman-echo.com/post"). Config(requests.GzipConfig( gzip.BestSpeed, func(gw *gzip.Writer) error { _, err := gw.Write([]byte(`{"message":"compressed payload"}`)) return err }, )). ContentType("application/json"). Fetch(ctx) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Record HTTP Responses with reqtest.Record Source: https://context7.com/earthboundkid/requests/llms.txt Use reqtest.Record to capture live HTTP responses during development. Run this code once to generate fixture files in the specified directory. ```go // Record real responses during development (run once) var live string err := requests. URL("https://example.com"). Transport(reqtest.Record(nil, "testdata/fixtures")). ToString(&live). Fetch(ctx) ``` -------------------------------- ### GzipConfig Source: https://context7.com/earthboundkid/requests/llms.txt Explains how to use `GzipConfig` to send a gzip-compressed request body, automatically setting the `Content-Encoding: gzip` header. ```APIDOC ## `GzipConfig` — Gzip-Compressed Request Body A `Config` that writes a gzip-compressed body using a callback, automatically setting `Content-Encoding: gzip`. ```go ctx := context.Background() err := requests. URL("https://postman-echo.com/post"). Config( requests.GzipConfig( gzip.BestSpeed, func(gw *gzip.Writer) error { _, err := gw.Write([]byte(`{"message":"compressed payload"}`)) return err }, ), ). ContentType("application/json"). Fetch(ctx) if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Capture All Response Headers with HEAD Request Source: https://context7.com/earthboundkid/requests/llms.txt Use ToHeaders to issue a HEAD request and capture all response headers into a map. This is efficient for retrieving metadata without downloading the body. ```go ctx := context.Background() // HEAD request to capture headers only headers := make(map[string][]string) err := requests. URL("https://example.com"). ToHeaders(headers). Fetch(ctx) fmt.Println(headers["Content-Type"]) ``` -------------------------------- ### Builder.Request and Builder.Do - Separate Build and Execute Source: https://context7.com/earthboundkid/requests/llms.txt Details how to use Request to build an http.Request without sending it, and Do to execute a pre-built request. ```APIDOC ## `Builder.Request` / `Builder.Do` — Separate Build and Execute `Request(ctx)` builds an `*http.Request` without sending it. `Do(req)` executes a pre-built request through the validators and handler. Useful when you need the raw `*http.Request` for logging or testing. ```go ctx := context.Background() b := requests.URL("https://api.example.com/data"). Bearer("token123"). ToJSON(&result) req, err := b.Request(ctx) if err != nil { log.Fatal(err) } log.Printf("About to call: %s %s", req.Method, req.URL) if err = b.Do(req); err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### Create Post Request to JSONPlaceholder Source: https://github.com/earthboundkid/requests/blob/main/testdata/jsonplaceholder-posts POST pe7QRLxL.req.txt This snippet shows the HTTP request details for creating a new post. Ensure the Host and Content-Type headers are correctly set. ```http POST /posts HTTP/1.1 Host: jsonplaceholder.typicode.com Content-Type: application/json {"title":"foo","body":"baz","userId":1} ``` -------------------------------- ### Configure Requests for httptest.Server with reqtest.Server Source: https://context7.com/earthboundkid/requests/llms.txt Use reqtest.Server to adapt an httptest.Server into a requests.Config. This helper configures the Builder's base URL and client to target the test server, including TLS certificates for HTTPS. ```go func TestHandler(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") fmt.Fprintln(w, `{"status":"ok"}`) })) defer srv.Close() var result struct{ Status string `json:"status"` } err := requests. New(reqtest.Server(srv)). Path("/api/check"). ToJSON(&result). Fetch(context.Background()) if err != nil { t.Fatal(err) } if result.Status != "ok" { t.Errorf("unexpected status: %s", result.Status) } } ``` -------------------------------- ### Save Response to File in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Save the response body directly to a file on disk. This is suitable for most cases requiring file atomicity and buffering. ```go err := requests. URL("http://example.com"). ToFile("myfile.txt"). Fetch(ctx) ``` -------------------------------- ### Capture Response Body as String Source: https://context7.com/earthboundkid/requests/llms.txt Use ToString to capture the response body as a string. Ensure a variable is passed to store the content. ```go ctx := context.Background() // Capture as string var body string err := requests.URL("https://example.com").ToString(&body).Fetch(ctx) fmt.Println(len(body)) ``` -------------------------------- ### Mock JSON API Responses with reqtest.ReplayJSON Source: https://context7.com/earthboundkid/requests/llms.txt Implement reqtest.ReplayJSON for fast unit tests by mocking API responses. It returns a specified Go object serialized as JSON with a given HTTP status code, without filesystem I/O. ```go func TestAPIClient(t *testing.T) { type Post struct { ID int `json:"id"` Title string `json:"title"` } mock := reqtest.ReplayJSON(200, Post{ID: 1, Title: "Test Post"}) var got Post err := requests. URL("https://api.example.com/posts/1"). Transport(mock). ToJSON(&got). Fetch(context.Background()) if err != nil { t.Fatal(err) } if got.Title != "Test Post" { t.Errorf("got %q, want %q", got.Title, "Test Post") } } ``` -------------------------------- ### Save Response to String in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Read the response body and store it as a string. This is a common way to handle small to medium-sized responses. ```go var s string err := requests. URL("http://example.com"). ToString(&s). Fetch(ctx) ``` -------------------------------- ### Send XML Request Body with reqxml.BodyConfig and reqxml.Body Source: https://context7.com/earthboundkid/requests/llms.txt The reqxml sub-package supports sending XML data. Use reqxml.BodyConfig or reqxml.Body to serialize Go structs into XML for request bodies. ```go type Person struct { XMLName xml.Name `xml:"person"` Name string `xml:"name"` Age int `xml:"age"` } ctx := context.Background() // POST XML body err := requests. URL("https://api.example.com/people"). Config(reqxml.BodyConfig(Person{Name: "Alice", Age: 30})). Fetch(ctx) ``` ```go // Or use the BodyGetter directly err = requests. URL("https://api.example.com/people"). Body(reqxml.Body(Person{Name: "Bob", Age: 25})). HeaderOptional("Content-Type", "application/xml"). Fetch(ctx) ``` -------------------------------- ### Share Base Configuration Across Requests Source: https://context7.com/earthboundkid/requests/llms.txt `Clone()` creates an independent copy of a Builder. Changes to the clone do not affect the original, making it safe for concurrent use and for building request-specific builders from a shared template. ```APIDOC ## `Builder.Clone` — Share Base Configuration Across Requests `Clone()` creates an independent copy of a Builder. Changes to the clone do not affect the original, making it safe for concurrent use and for building request-specific builders from a shared template. ```go // Define a shared API client once apiBase := requests.URL("https://api.example.com/v2"). Bearer(os.Getenv("API_TOKEN")), Accept("application/json"). UserAgent("my-service/1.0") // Clone and extend per request var user struct{ Name string } err := apiBase.Clone(). Pathf("/users/%d", 42). ToJSON(&user). Fetch(ctx) var posts []struct{ Title string } err = apiBase.Clone(). Path("/posts"). ParamInt("user_id", 42). ToJSON(&posts). Fetch(ctx) ``` ``` -------------------------------- ### Save Response to File Source: https://github.com/earthboundkid/requests/wiki/Home Downloads the response body from a URL and saves it directly to a specified file. Ensure the file path is valid. ```go // Save a file err := requests. URL("http://example.com"). ToFile("myfile.txt"). Fetch(context.Background()) ``` -------------------------------- ### Multipart Form Data Request Body Source: https://context7.com/earthboundkid/requests/llms.txt Demonstrates sending `multipart/form-data` requests using `Config` and `BodyMultipart`. This method handles boundary generation and the content type header automatically. It allows adding text fields and file uploads. ```go ctx := context.Background() err := requests. URL("https://postman-echo.com/post"). Config(requests.BodyMultipart("", func(w *multipart.Writer) error { // Add a text field if err := w.WriteField("author", "Alice"); err != nil { return err } // Add a file field fw, err := w.CreateFormFile("upload", "hello.txt") if err != nil { return err } _, err = io.WriteString(fw, "Hello, world!") return err })). Fetch(ctx) ``` -------------------------------- ### Save Response Body Directly to File Source: https://context7.com/earthboundkid/requests/llms.txt Use ToFile to save the response body directly to a specified file path. Parent directories are created automatically. ```go // Save directly to file (creates parent directories automatically) err = requests.URL("https://example.com/data.csv").ToFile("./downloads/data.csv").Fetch(ctx) ``` -------------------------------- ### Set Custom Headers Source: https://github.com/earthboundkid/requests/wiki/Home Adds custom headers to an HTTP request. This includes setting User-Agent, Content-Type, and arbitrary headers. ```go // Set headers var headers postman err := requests. URL("https://postman-echo.com/get"). UserAgent("bond/james-bond"). ContentType("secret"). Header("martini", "shaken"). Fetch(context.Background()) ``` -------------------------------- ### Builder.URL - Construct a url.URL Without Sending Source: https://context7.com/earthboundkid/requests/llms.txt Shows how to use the URL method to construct a *url.URL object from accumulated options without making an HTTP request. ```APIDOC ## `Builder.URL()` — Construct a `url.URL` Without Sending Returns a `*url.URL` built from the accumulated URL options. Useful for inspecting or logging the final URL before sending, or for building URLs independently of HTTP requests. ```go u, err := requests. URL("https://prod.example.com/search?q=existing"). Hostf("%s.example.com", "staging"). Param("q", "gophers"). ParamInt("page", 2). ParamOptional("debug", ""). // ignored because value is blank URL() if err != nil { log.Fatal(err) } fmt.Println(u.String()) // https://staging.example.com/search?page=2&q=gophers ``` ``` -------------------------------- ### Cache HTTP Responses with reqtest.Caching Source: https://context7.com/earthboundkid/requests/llms.txt Use reqtest.Caching for integration tests to cache responses on disk. It fetches from the network on the first run and replays from the cache on subsequent runs, reducing network hits. ```go func TestWithCaching(t *testing.T) { var data map[string]any err := requests. URL("https://httpbin.org/json"). Transport(reqtest.Caching(nil, "testdata/cache")). ToJSON(&data). Fetch(context.Background()) if err != nil { t.Fatal(err) } // First run: fetches from network and saves to testdata/cache/ // Subsequent runs: reads from testdata/cache/ without network access } ``` -------------------------------- ### Stream Response Line by Line with bufio.Scanner Source: https://context7.com/earthboundkid/requests/llms.txt Use ToBufioScanner to process newline-delimited responses line by line. The callback function receives a bufio.Scanner. ```go ctx := context.Background() // Process a newline-delimited response line by line err := requests. URL("https://example.com/stream"). Handle(requests.ToBufioScanner(func(s *bufio.Scanner) error { for s.Scan() { fmt.Println(s.Text()) } return s.Err() })). Fetch(ctx) ``` -------------------------------- ### Send File as Request Body Source: https://github.com/earthboundkid/requests/wiki/Home Sends the content of a local file as the request body. Specify the ContentType for the file being sent. ```go // Send a file err := requests. URL("http://example.com"). BodyFile("myfile.txt"). ContentType("text/plain"). Fetch(context.Background()) ``` -------------------------------- ### Create Post Source: https://github.com/earthboundkid/requests/blob/main/testdata/jsonplaceholder-posts POST pe7QRLxL.req.txt Allows users to create a new post by sending a POST request with post details in the request body. ```APIDOC ## POST /posts ### Description Creates a new post. ### Method POST ### Endpoint /posts ### Request Body - **title** (string) - Required - The title of the post. - **body** (string) - Required - The content of the post. - **userId** (integer) - Required - The ID of the user who created the post. ### Request Example ```json { "title": "foo", "body": "baz", "userId": 1 } ``` ### Response #### Success Response (201 Created) - **id** (integer) - The ID of the newly created post. - **title** (string) - The title of the post. - **body** (string) - The content of the post. - **userId** (integer) - The ID of the user who created the post. #### Response Example ```json { "id": 101, "title": "foo", "body": "baz", "userId": 1 } ``` ``` -------------------------------- ### Streaming Response Handlers Source: https://context7.com/earthboundkid/requests/llms.txt For line-by-line or streaming responses, wrap the body in a `bufio.Reader` or `bufio.Scanner` via callback. ```APIDOC ## `ToBufioReader` / `ToBufioScanner` — Streaming Response Handlers For line-by-line or streaming responses, wrap the body in a `bufio.Reader` or `bufio.Scanner` via callback. ```go ctx := context.Background() // Process a newline-delimited response line by line err := requests. URL("https://example.com/stream"). Handle(requests.ToBufioScanner(func(s *bufio.Scanner) error { for s.Scan() { fmt.Println(s.Text()) } return s.Err() })). Fetch(ctx) ``` ``` -------------------------------- ### BodyMultipart Source: https://context7.com/earthboundkid/requests/llms.txt Details how to construct `multipart/form-data` request bodies using the `BodyMultipart` configuration, including adding text fields and files. ```APIDOC ## `BodyMultipart` — Multipart Form Data A `Config` for building `multipart/form-data` request bodies. Automatically handles boundary generation and content type header. ```go ctx := context.Background() err := requests. URL("https://postman-echo.com/post"). Config(requests.BodyMultipart("", func(w *multipart.Writer) error { // Add a text field if err := w.WriteField("author", "Alice"); err != nil { return err } // Add a file field fw, err := w.CreateFormFile("upload", "hello.txt") if err != nil { return err } _, err = io.WriteString(fw, "Hello, world!") return err })). Fetch(ctx) ``` ``` -------------------------------- ### Implement Custom HTTP Transport with Builder.Transport Source: https://context7.com/earthboundkid/requests/llms.txt Set a custom `http.RoundTripper` using `Builder.Transport`. `RoundTripFunc` allows defining inline transport logic, such as rate limiting. ```go // Rate-limiting transport limiter := rate.NewLimiter(rate.Every(time.Second/10), 10) rateLimited := requests.RoundTripFunc(func(req *http.Request) (*http.Response, error) { if err := limiter.Wait(req.Context()); err != nil { return nil, err } return http.DefaultTransport.RoundTrip(req) }) ``` ```go var data map[string]any err := requests. URL("https://api.example.com/endpoint"). Transport(rateLimited). ToJSON(&data). Fetch(context.Background()) ``` -------------------------------- ### Compose Multiple Response Handlers with ChainHandlers Source: https://context7.com/earthboundkid/requests/llms.txt Use ChainHandlers to combine multiple ResponseHandler functions into a single handler that executes them sequentially. ```go ctx := context.Background() var parsed map[string]any capturedHeaders := make(map[string][]string) combined := requests.ChainHandlers( requests.CopyHeaders(capturedHeaders), requests.ToJSON(&parsed), ) err := requests. URL("https://httpbin.org/json"). AddValidator(requests.DefaultValidator). Handle(combined). Fetch(ctx) ``` -------------------------------- ### Control Redirects with MaxFollow and NoFollow Policies Source: https://context7.com/earthboundkid/requests/llms.txt Manage HTTP redirects using `MaxFollow(n)` to limit redirects or `NoFollow` to prevent them entirely. Assign these policies to `http.Client.CheckRedirect`. ```go ctx := context.Background() cl := &http.Client{ CheckRedirect: requests.MaxFollow(2), // follow at most 2 redirects } var body string err := requests. URL("https://httpbingo.org/redirect/5"). Client(cl). ToString(&body). Fetch(ctx) // Returns error after 2 redirects ``` ```go // Capture redirect location without following noFollowClient := &http.Client{CheckRedirect: requests.NoFollow} headers := make(map[string][]string) err = requests. URL("https://httpbingo.org/redirect/1"). Client(noFollowClient). AddValidator(requests.CheckStatus(302, 301)). CopyHeaders(headers). Fetch(ctx) fmt.Println(headers["Location"]) ``` -------------------------------- ### Request Bodies: Bytes, JSON, Form, File Source: https://context7.com/earthboundkid/requests/llms.txt Illustrates different ways to send request bodies: raw bytes with a specified content type, JSON marshaling, URL-encoded form data, and streaming a file. `BodyJSON` automatically sets `Content-Type: application/json`. ```go ctx := context.Background() // Raw bytes err := requests. URL("https://postman-echo.com/post"). BodyBytes([]byte(`hello, world`)). ContentType("text/plain"). Fetch(ctx) // JSON body + JSON response type Post struct { Title string `json:"title"` Body string `json:"body"` UserID int `json:"userId"` } var created Post err = requests. URL("https://jsonplaceholder.typicode.com/posts"). BodyJSON(Post{Title: "foo", Body: "bar", UserID: 1}). ToJSON(&created). Fetch(ctx) fmt.Println(created.ID) // 101 // Form body err = requests. URL("https://postman-echo.com/post"). BodyForm(url.Values{"username": {"alice"}, "password": {"secret"}}). Fetch(ctx) // Stream a file as body err = requests. URL("https://example.com/upload"). Put(). BodyFile("./data.bin"). ContentType("application/octet-stream"). Fetch(ctx) ``` -------------------------------- ### Add Query Parameters Source: https://github.com/earthboundkid/requests/wiki/Home Appends query parameters to a URL. Existing parameters in the URL are preserved, and new ones are added or updated. ```go var params postman err := requests. URL("https://example.com/get?a=1&b=2"). Param("b", "3"). Param("c", "4"). Fetch(context.Background()) // URL is https://example.com/get?a=1&b=3&c=4 ``` -------------------------------- ### Post JSON and Read Response JSON in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Send JSON data in the request body and parse the JSON response into a Go struct. Both `MyRequestType` and `MyResponseType` must be defined. ```go body := MyRequestType{} var resp MyResponseType err := requests. URL("https://example.com/my-json"). BodyJSON(&body). ToJSON(&resp). Fetch(ctx) ``` -------------------------------- ### Manage Cookies with NewCookieJar Source: https://context7.com/earthboundkid/requests/llms.txt Utilize `NewCookieJar` to create an `http.CookieJar` that persists cookies across requests. This jar uses the public suffix list and can be assigned to `http.Client.Jar`. ```go ctx := context.Background() jar := requests.NewCookieJar() cl := &http.Client{Jar: jar} // First request sets a cookie err := requests. URL("https://httpbin.org/cookies/set/session/abc123"). Client(cl). Fetch(ctx) ``` ```go // Second request sends the cookie automatically var cookies struct { Cookies map[string]string `json:"cookies"` } err = requests. URL("https://httpbin.org/cookies"). Client(cl). ToJSON(&cookies). Fetch(ctx) fmt.Println(cookies.Cookies["session"]) // abc123 ``` -------------------------------- ### Fetch JSON Data in Go Source: https://github.com/earthboundkid/requests/blob/main/README.md Fetch JSON data from a URL and unmarshal it into a Go struct. Ensure `SomeDataType` is defined and the URL returns valid JSON. ```go var data SomeDataType err := requests. URL("https://example.com/my-json"). ToJSON(&data). Fetch(ctx) ``` -------------------------------- ### POST Raw Bytes Source: https://github.com/earthboundkid/requests/wiki/Home Sends raw bytes as the request body in a POST request. Specify the ContentType for the raw bytes. ```go err := requests. URL("https://postman-echo.com/post"). BodyBytes([]byte(`hello, world`)). ContentType("text/plain"). Fetch(context.Background()) ``` -------------------------------- ### Handle Non-Canonical Header Capitalization with Custom Transport Source: https://github.com/earthboundkid/requests/wiki/Home Creates a custom HTTP transport that forces all request headers to be lowercase before sending. This addresses issues with non-compliant servers that expect specific header capitalization. ```go basetransport := http.DefaultTransport lowercaseHeaders := requests.RoundTripFunc(func(req *http.Request) (res *http.Response, err error) { // Custom transports should clone a request before modifying it req2 := *req req2.Header = make(http.Header, len(req.Header)) for k, v := range req.Header { // Make each header key in the clone request lowercase req2.Header[strings.ToLower(k)] = v } // Send clone request using the real transport return basetransport.RoundTrip(&req2) }) rb := requests. URL("https://example.com"). Transport(lowercaseHeaders) ``` -------------------------------- ### Write Response Body to io.Writer Source: https://context7.com/earthboundkid/requests/llms.txt Use ToWriter to stream the response body directly to any io.Writer implementation, such as os.Stdout. ```go // Write to io.Writer (e.g. os.Stdout) err = requests.URL("https://example.com").ToWriter(os.Stdout).Fetch(ctx) ``` -------------------------------- ### Compose Multiple Response Handlers Source: https://context7.com/earthboundkid/requests/llms.txt `ChainHandlers` combines multiple `ResponseHandler` functions into one, running them sequentially. ```APIDOC ## `ChainHandlers` — Compose Multiple Response Handlers Combines multiple `ResponseHandler` functions into one, running them sequentially. ```go ctx := context.Background() var parsed map[string]any capturedHeaders := make(map[string][]string) combined := requests.ChainHandlers( requests.CopyHeaders(capturedHeaders), requests.ToJSON(&parsed), ) err := requests. URL("https://httpbin.org/json"). AddValidator(requests.DefaultValidator). Handle(combined). Fetch(ctx) ``` ``` -------------------------------- ### Construct URL without Sending with Builder.URL() Source: https://context7.com/earthboundkid/requests/llms.txt The `URL()` method on a Builder constructs a `*url.URL` from the accumulated options without sending an HTTP request. This is useful for inspecting or logging the final URL before it's sent. ```go u, err := requests. URL("https://prod.example.com/search?q=existing"). Hostf("%s.example.com", "staging"). Param("q", "gophers"). ParamInt("page", 2). ParamOptional("debug", ""). // ignored because value is blank URL() if err != nil { log.Fatal(err) } fmt.Println(u.String()) // https://staging.example.com/search?page=2&q=gophers ```