gohttp

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Jan 11, 2025 License: MIT Imports: 5 Imported by: 0

README

gohttp

A Go library for creating and customizing HTTP clients. It provides:

  • A pluggable Transport that lets you attach multiple middlewares to process requests and responses.
  • A Middleware interface for adding reusable handlers like logging or caching.
  • Built-in caching middlewares, with options for various backends (e.g. redis, badger, text file).
  • An easy way to add request/response hooks for debugging or logging.

See example_test.go for usage examples.

Documentation

Overview

Example (Badgercache)
ts, _ := NewServer()
defer ts.Close()

// In-memory badger db
db, err := badger.Open(badger.DefaultOptions("").WithInMemory(true))
if err != nil {
	panic(err)
}
defer db.Close()

// Create a new http client with a cache middleware.
client := &http.Client{
	Transport: gohttp.NewTransport().
		Use(
			gohttp.PrintMiddleware("start\n", ""),
			cachemw.New(
				badgercache.New(db),
				cachemw.WithTTL(5*time.Minute),
			),
			gohttp.PrintMiddleware("cache miss\n", "response from server\n"),
		),
}

for i := 0; i < 3; i++ {
	req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, ts.URL, nil)
	if err != nil {
		panic(err)
	}

	fmt.Println("Request:", i)
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Response: %s\n", string(respBody))
	fmt.Println("---")
}
Output:

Request: 0
start
cache miss
response from server
Response: Hello, 0
---
Request: 1
start
Response: Hello, 0
---
Request: 2
start
Response: Hello, 0
---
Example (Rediscache)
ts, _ := NewServer()
defer ts.Close()

// a redis server for testing
rs, err := miniredis.Run()
if err != nil {
	panic(err)
}
defer rs.Close()

rCache := cache.New(&cache.Options{
	Redis: redis.NewClient(&redis.Options{
		Addr: rs.Addr(),
		DB:   0,
	}),
})

// Create a new http client with a cache middleware.
client := &http.Client{
	Transport: gohttp.NewTransport().
		Use(
			gohttp.PrintMiddleware("start\n", ""),
			cachemw.New(
				rediscache.New(rCache),
				cachemw.WithTTL(5*time.Minute),
			),
			gohttp.PrintMiddleware("cache miss\n", "response from server\n"),
		),
}

for i := 0; i < 3; i++ {
	req, err := http.NewRequestWithContext(context.TODO(), http.MethodGet, ts.URL, nil)
	if err != nil {
		panic(err)
	}

	fmt.Println("Request:", i)
	resp, err := client.Do(req)
	if err != nil {
		panic(err)
	}

	respBody, err := io.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}

	fmt.Printf("Response: %s\n", string(respBody))
	fmt.Println("---")
}
Output:

Request: 0
start
cache miss
response from server
Response: Hello, 0
---
Request: 1
start
Response: Hello, 0
---
Request: 2
start
Response: Hello, 0
---
Example (Textcache)
package main

import (
	"bytes"
	"context"
	"fmt"
	"io"
	"net/http"
	"net/http/httptest"
	"path/filepath"
	"sync"
	"time"

	"github.com/kmio11/gohttp"
	"github.com/kmio11/gohttp/cachemw"
	"github.com/kmio11/gohttp/cachemw/textcache"
)

// NewServer creates and returns a new httptest.Server for testing.
func NewServer() (testServer *httptest.Server, reset func()) {
	m := sync.RWMutex{}
	cnt := 0
	h := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		m.Lock()
		defer m.Unlock()
		fmt.Fprintf(w, "Hello, %d", cnt)
		cnt++
	})

	reset = func() {
		m.Lock()
		defer m.Unlock()
		cnt = 0
	}

	testServer = httptest.NewServer(h)
	return testServer, reset
}

func main() {
	ts, _ := NewServer()
	defer ts.Close()

	// Create a temporary directory for the cache.
	cacheBaseDir := filepath.Join("testdata", "Example_textcache", "tmp", time.Now().Format("20060102150405.999"))

	// Create a new http client with a cache middleware.
	client := &http.Client{
		Transport: gohttp.NewTransport().
			Use(
				gohttp.PrintMiddleware("start\n", ""),
				cachemw.New(
					textcache.New(
						cacheBaseDir,
						textcache.WithDumpRequest(),
					),
				),
				gohttp.PrintMiddleware("cache miss\n", "response from server\n"),
			),
	}

	for i := 0; i < 3; i++ {
		req, err := http.NewRequestWithContext(context.TODO(), http.MethodPost, ts.URL, bytes.NewBufferString("Hello, World!"))
		if err != nil {
			panic(err)
		}

		fmt.Println("Request:", i)
		resp, err := client.Do(req)
		if err != nil {
			panic(err)
		}

		respBody, err := io.ReadAll(resp.Body)
		if err != nil {
			panic(err)
		}
		fmt.Printf("Response: %s\n", string(respBody))
		fmt.Println("---")
	}

}
Output:

Request: 0
start
cache miss
response from server
Response: Hello, 0
---
Request: 1
start
Response: Hello, 0
---
Request: 2
start
Response: Hello, 0
---

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Middleware

type Middleware interface {
	RoundTripper(next http.RoundTripper) http.RoundTripper
}

type MiddlewareFunc

type MiddlewareFunc func(next http.RoundTripper) http.RoundTripper

func DumpMiddleware

func DumpMiddleware(w io.Writer) MiddlewareFunc

DumpMiddleware returns a MiddlewareFunc that logs HTTP requests and responses to the provided io.Writer.

func PrintMiddleware

func PrintMiddleware(before, after string) MiddlewareFunc

PrintMiddleware returns a MiddlewareFunc that prints the specified strings before and after the HTTP request is processed by the next RoundTripper in the chain.

func (MiddlewareFunc) RoundTripper

func (f MiddlewareFunc) RoundTripper(next http.RoundTripper) http.RoundTripper

type Option

type Option func(*Transport)

Option is a functional option for configuring the CustomTransport.

func WithBaseTransport

func WithBaseTransport(rt http.RoundTripper) Option

WithBaseTransport sets the base RoundTripper for the CustomTransport.

type RoundTripperFunc

type RoundTripperFunc func(req *http.Request) (*http.Response, error)

func (RoundTripperFunc) RoundTrip

func (f RoundTripperFunc) RoundTrip(req *http.Request) (*http.Response, error)

type Transport

type Transport struct {
	// contains filtered or unexported fields
}

func NewTransport

func NewTransport(opts ...Option) *Transport

NewTransport creates a new instance of CustomTransport.

func (*Transport) RoundTrip

func (t *Transport) RoundTrip(req *http.Request) (*http.Response, error)

RoundTrip executes a single HTTP transaction, as defined by http.RoundTripper.

func (*Transport) Use

func (t *Transport) Use(middleware ...Middleware) *Transport

Use adds the provided middleware functions to the CustomTransport's middleware chain.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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