package uri import ( "net/url" "strconv" "strings" "time" "github.com/kataras/iris/v12/cache/cfg" ) // URIBuilder is the requested url builder // which keeps all the information the server // should know to save or retrieve a cached entry's response // used on client-side only // both from net/http and valyala/fasthttp type URIBuilder struct { serverAddr, clientMethod, clientURI string cacheLifetime time.Duration cacheStatuscode int cacheContentType string } // ServerAddr sets the server address for the final request url func (r *URIBuilder) ServerAddr(s string) *URIBuilder { r.serverAddr = s return r } // ClientMethod sets the method which the client should call the remote server's handler // used to build the final request url too func (r *URIBuilder) ClientMethod(s string) *URIBuilder { r.clientMethod = s return r } // ClientURI sets the client path for the final request url func (r *URIBuilder) ClientURI(s string) *URIBuilder { r.clientURI = s return r } // Lifetime sets the cache lifetime for the final request url func (r *URIBuilder) Lifetime(d time.Duration) *URIBuilder { r.cacheLifetime = d return r } // StatusCode sets the cache status code for the final request url func (r *URIBuilder) StatusCode(code int) *URIBuilder { r.cacheStatuscode = code return r } // ContentType sets the cache content type for the final request url func (r *URIBuilder) ContentType(s string) *URIBuilder { r.cacheContentType = s return r } // String returns the full url which should be passed to get a cache entry response back // (it could be set by server too but we need some client-freedom on the requested key) // in order to be sure that the registered cache entries are unique among different clients with the same key // note1: we do it manually*, // note2: on fasthttp that is not required because the query args added as expected but we will use it there too to be align with net/http func (r URIBuilder) String() string { return r.build() } func (r URIBuilder) build() string { remoteURL := r.serverAddr // fasthttp appends the "/" in the last uri (with query args also, that's probably a fasthttp bug which I'll fix later) // for now lets make that check: if !strings.HasSuffix(remoteURL, "/") { remoteURL += "/" } scheme := "http://" // validate the remoteURL, should contains a scheme, if not then check if the client has given a scheme and if so // use that for the server too if !strings.Contains(remoteURL, "://") { if strings.Contains(remoteURL, ":443") || strings.Contains(remoteURL, ":https") { remoteURL = "https://" + remoteURL } else { remoteURL = scheme + "://" + remoteURL } } var cacheDurationStr, statusCodeStr string if r.cacheLifetime.Seconds() > 0 { cacheDurationStr = strconv.Itoa(int(r.cacheLifetime.Seconds())) } if r.cacheStatuscode > 0 { statusCodeStr = strconv.Itoa(r.cacheStatuscode) } s := remoteURL + "?" + cfg.QueryCacheKey + "=" + url.QueryEscape(r.clientMethod+scheme+r.clientURI) if cacheDurationStr != "" { s += "&" + cfg.QueryCacheDuration + "=" + url.QueryEscape(cacheDurationStr) } if statusCodeStr != "" { s += "&" + cfg.QueryCacheStatusCode + "=" + url.QueryEscape(statusCodeStr) } if r.cacheContentType != "" { s += "&" + cfg.QueryCacheContentType + "=" + url.QueryEscape(r.cacheContentType) } return s }