Skip to content

Commit

Permalink
set TTL in settings
Browse files Browse the repository at this point in the history
  • Loading branch information
bashalex committed Nov 22, 2021
1 parent 914dbf8 commit 1713e72
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 62 deletions.
2 changes: 2 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
MAIN_CONTAINER_PORT=8001
CACHE_TTL=30s
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ ENV LANG C.UTF-8
ENV MAIN_CONTAINER_PORT "80"
ENV REDIS_ADDRESS "127.0.0.1:6379"
ENV REDIS_PASSWORD ""
ENV CACHE_TTL "30s"

COPY --from=builder /app/main /app/main

Expand Down
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
-include .env
export

.PHONY: run
run:
go run -v cmd/sidecache/main.go
13 changes: 7 additions & 6 deletions pkg/cache/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cache
import (
"go.uber.org/zap"
"os"
"strconv"
"time"

"github.com/go-redis/redis"
Expand All @@ -27,9 +26,8 @@ func NewRedisRepository(logger *zap.Logger) (*RedisRepository, error) {
return &RedisRepository{client: client, logger: logger}, nil
}

func (repository *RedisRepository) SetKey(key string, value []byte, ttl int) {
duration, _ := time.ParseDuration(strconv.FormatInt(int64(ttl), 10))
status := repository.client.Set(key, string(value), duration)
func (repository *RedisRepository) SetKey(key string, value []byte, ttl time.Duration) {
status := repository.client.Set(key, string(value), ttl)
_, err := status.Result()
if err != nil {
repository.logger.Error(err.Error())
Expand All @@ -40,8 +38,11 @@ func (repository *RedisRepository) Get(key string) []byte {
status := repository.client.Get(key)
stringResult, err := status.Result()

if err != nil && err != redis.Nil {
repository.logger.Error(err.Error())
if err != nil {
if err != redis.Nil {
repository.logger.Error(err.Error())
}
return nil
}

return []byte(stringResult)
Expand Down
6 changes: 5 additions & 1 deletion pkg/cache/repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package cache

import (
"time"
)

type Repository interface {
SetKey(key string, value []byte, ttl int)
SetKey(key string, value []byte, ttl time.Duration)
Get(key string) []byte
}
104 changes: 49 additions & 55 deletions pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@ import (
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
"time"

"github.com/prometheus/client_golang/prometheus/promhttp"
"github.com/zeriontech/sidecache/pkg/cache"
"go.uber.org/zap"
)

const CacheHeaderKey = "tysidecarcachable"
const CacheHeaderEnabledKey = "sidecache-headers-enabled"
const applicationDefaultPort = ":9191"

Expand Down Expand Up @@ -51,59 +50,61 @@ func NewServer(repo cache.Repository, proxy *httputil.ReverseProxy, prom *Promet

func (server CacheServer) Start(stopChan chan int) {
server.Proxy.ModifyResponse = func(r *http.Response) error {
cacheHeaderValue := r.Header.Get(CacheHeaderKey)
if cacheHeaderValue != "" {
cacheHeadersEnabled := r.Header.Get(CacheHeaderEnabledKey)
maxAgeInSecond := server.GetHeaderTTL(cacheHeaderValue)
r.Header.Del("Content-Length") // https://github.com/golang/go/issues/14975
var b []byte
var err error
if r.Header.Get("content-encoding") == "gzip" {
reader, _ := gzip.NewReader(r.Body)
b, err = ioutil.ReadAll(reader)
} else {
b, err = ioutil.ReadAll(r.Body)
}

if err != nil {
server.Logger.Error("Error while reading response body", zap.Error(err))
return err
}
cacheHeadersEnabled := r.Header.Get(CacheHeaderEnabledKey)
maxAgeInSecond, err := time.ParseDuration(os.Getenv("CACHE_TTL"))

buf := server.gzipWriter(b)
go func(reqUrl *url.URL, data []byte, ttl int, cacheHeadersEnabled string) {
hashedURL := server.HashURL(server.ReorderQueryString(reqUrl))
cacheData := CacheData{Body: data}

if cacheHeadersEnabled == "true" {
headers := make(map[string]string)
for h, v := range r.Header {
headers[h] = strings.Join(v, ";")
}
cacheData.Headers = headers
}
if err != nil {
server.Logger.Error("invalid cache TTL", zap.Error(err))
return nil
}

cacheDataBytes, _ := json.Marshal(cacheData)
server.Logger.Info(strconv.FormatBool(server.Repo == nil))
server.Repo.SetKey(hashedURL, cacheDataBytes, ttl)
}(r.Request.URL, buf.Bytes(), maxAgeInSecond, cacheHeadersEnabled)
r.Header.Del("Content-Length") // https://github.com/golang/go/issues/14975
var b []byte
if r.Header.Get("content-encoding") == "gzip" {
reader, _ := gzip.NewReader(r.Body)
b, err = ioutil.ReadAll(reader)
} else {
b, err = ioutil.ReadAll(r.Body)
}

err = r.Body.Close()
if err != nil {
server.Logger.Error("Error while closing response body", zap.Error(err))
return err
}
if err != nil {
server.Logger.Error("Error while reading response body", zap.Error(err))
return err
}

var body io.ReadCloser
if r.Header.Get("content-encoding") == "gzip" {
body = ioutil.NopCloser(buf)
} else {
body = ioutil.NopCloser(bytes.NewReader(b))
buf := server.gzipWriter(b)
go func(reqUrl *url.URL, data []byte, ttl time.Duration, cacheHeadersEnabled string) {
hashedURL := server.HashURL(server.ReorderQueryString(reqUrl))
cacheData := CacheData{Body: data}

if cacheHeadersEnabled == "true" {
headers := make(map[string]string)
for h, v := range r.Header {
headers[h] = strings.Join(v, ";")
}
cacheData.Headers = headers
}

r.Body = body
cacheDataBytes, _ := json.Marshal(cacheData)
server.Repo.SetKey(hashedURL, cacheDataBytes, ttl)
}(r.Request.URL, buf.Bytes(), maxAgeInSecond, cacheHeadersEnabled)

err = r.Body.Close()
if err != nil {
server.Logger.Error("Error while closing response body", zap.Error(err))
return err
}

var body io.ReadCloser
if r.Header.Get("content-encoding") == "gzip" {
body = ioutil.NopCloser(buf)
} else {
body = ioutil.NopCloser(bytes.NewReader(b))
}

r.Body = body

return nil
}

Expand Down Expand Up @@ -171,6 +172,8 @@ func (server CacheServer) CacheHandler(w http.ResponseWriter, r *http.Request) {
hashedURL := server.HashURL(server.ReorderQueryString(r.URL))
cachedDataBytes := server.CheckCache(hashedURL)

server.Logger.Info("serve request", zap.String("url", r.URL.String()), zap.Bool("cached", cachedDataBytes != nil))

if cachedDataBytes != nil {
w.Header().Add("X-Cache-Response-For", r.URL.String())
w.Header().Add("Content-Type", "application/json;charset=UTF-8") //todo get from cache?
Expand Down Expand Up @@ -229,15 +232,6 @@ func writeHeaders(w http.ResponseWriter, headers map[string]string) {
}
}

func (server CacheServer) GetHeaderTTL(cacheHeaderValue string) int {
cacheValues := strings.Split(cacheHeaderValue, "=")
var maxAgeInSecond = 0
if len(cacheValues) > 1 {
maxAgeInSecond, _ = strconv.Atoi(cacheValues[1])
}
return maxAgeInSecond
}

func (server CacheServer) HashURL(url string) string {
hasher := md5.New()
hasher.Write([]byte(server.CacheKeyPrefix + "/" + url))
Expand Down

0 comments on commit 1713e72

Please sign in to comment.