func (h *ClientHandler) ServeHTTP(reqCtx *fasthttp.RequestCtx) {
	if !h.rule.Claim(reqCtx) {
		h.bodyHandler(reqCtx)
		return
	}
	uri := &uri.URIBuilder{}
	uri.ServerAddr(h.remoteHandlerURL).ClientURI(string(reqCtx.URI().RequestURI())).ClientMethod(string(reqCtx.Method()))
	req := fasthttp.AcquireRequest()
	defer fasthttp.ReleaseRequest(req)
	req.URI().Update(uri.String())
	req.Header.SetMethodBytes(methodGetBytes)
	res := fasthttp.AcquireResponse()
	defer fasthttp.ReleaseResponse(res)
	err := ClientFasthttp.Do(req, res)
	if err != nil || res.StatusCode() == cfg.FailStatus {
		h.bodyHandler(reqCtx)
		if !h.rule.Valid(reqCtx) {
			return
		}
		body := reqCtx.Response.Body()[0:]
		if len(body) == 0 {
			return  
		}
		req.Reset()
		uri.StatusCode(reqCtx.Response.StatusCode())
		uri.Lifetime(h.life)
		uri.ContentType(string(reqCtx.Response.Header.Peek(cfg.ContentTypeHeader)))
		req.URI().Update(uri.String())
		req.Header.SetMethodBytes(methodPostBytes)
		req.SetBody(body)
		ClientFasthttp.Do(req, res)
	} else {
		statusCode := res.StatusCode()
		cType := res.Header.ContentType()
		reqCtx.SetStatusCode(statusCode)
		reqCtx.Response.Header.SetContentTypeBytes(cType)
		reqCtx.Write(res.Body())
	}
}
ServeHTTP , or remote cache client whatever you like, it's the client-side function of the ServeHTTP
sends a request to the server-side remote cache Service and sends the cached response to the frontend client
it is used only when you achieved something like horizontal scaling (separate machines)
look ../remote/remote.ServeHTTP for more

if cache din't find then it sends a POST request and save the bodyHandler's body to the remote cache.

It takes 3 parameters
the first is the remote address (it's the address you started your http server which handled by the Service.ServeHTTP)
the second is the handler (or the mux) you want to cache
and the  third is the, optionally, cache expiration,
which is used to set cache duration of this specific cache entry to the remote cache service
if <=minimumAllowedCacheDuration then the server will try to parse from "cache-control" header

client-side function
package fhttp
import (
	"time"
	"github.com/geekypanda/httpcache/cfg"
	"github.com/geekypanda/httpcache/fhttp/rule"
	"github.com/geekypanda/httpcache/uri"
	"github.com/valyala/fasthttp"
)
type ClientHandler struct {
	bodyHandler fasthttp.RequestHandler
	rule rule.Rule
	life time.Duration
	remoteHandlerURL string
}
func NewClientHandler(bodyHandler fasthttp.RequestHandler, life time.Duration, remote string) *ClientHandler {
	return &ClientHandler{
		bodyHandler:      bodyHandler,
		rule:             DefaultRuleSet,
		life:             life,
		remoteHandlerURL: remote,
	}
}
func (h *ClientHandler) Rule(r rule.Rule) *ClientHandler {
	if r == nil {
		r = rule.Satisfied()
	}
	h.rule = r
	return h
}
func (h *ClientHandler) AddRule(r rule.Rule) *ClientHandler {
	if r == nil {
		return h
	}
	h.rule = rule.Chained(h.rule, r)
	return h
}
var ClientFasthttp = &fasthttp.Client{WriteTimeout: cfg.RequestCacheTimeout, ReadTimeout: cfg.RequestCacheTimeout}
var (
	methodGetBytes  = []byte("GET")
	methodPostBytes = []byte("POST")
)