-
Notifications
You must be signed in to change notification settings - Fork 58
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 65b4a78
Showing
23 changed files
with
747 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
CACHE_PORT=80 | ||
CACHE_TLS_PORT=443 | ||
REDIS_URL=redis:6379 | ||
TTL=10 | ||
REVERSE_PROXY=http://traefik | ||
|
||
REGEX=ARegexHere |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
CACHE_PORT=80 | ||
CACHE_TLS_PORT=443 | ||
REDIS_URL=redis:6379 | ||
TTL=10 | ||
REVERSE_PROXY=http://traefik | ||
|
||
REGEX=ARegexHere |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
/cmd/* | ||
.env | ||
docker-compose.yml | ||
Dockerfile | ||
/.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
sudo: required | ||
language: go | ||
|
||
addons: | ||
apt: | ||
packages: | ||
- docker-ce | ||
|
||
git: | ||
depth: 1 | ||
|
||
notifications: | ||
email: false | ||
|
||
services: | ||
- docker | ||
|
||
before_install: | ||
- make create-network | ||
- make build-dev | ||
|
||
script: | ||
- make validate |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
FROM golang:1.13-alpine | ||
|
||
RUN apk update && apk upgrade && \ | ||
apk add --no-cache bash git openssh gcc libc-dev | ||
|
||
RUN mkdir -p /app/src/github.com/darkweak/souin | ||
ADD ./*.go /app/src/github.com/darkweak/souin/ | ||
ADD ./cache /app/src/github.com/darkweak/souin/cache | ||
ADD ./default/server.* /app/src/github.com/darkweak/souin/ | ||
|
||
WORKDIR /app/src/github.com/darkweak/souin | ||
ENV GOPATH /app | ||
RUN go get ./... | ||
RUN go get -u golang.org/x/lint/golint | ||
|
||
EXPOSE 80 | ||
|
||
CMD ["go", "run", "main.go"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
FROM golang:1.13-alpine | ||
|
||
RUN apk update && apk upgrade && \ | ||
apk add --no-cache bash git openssh gcc libc-dev | ||
|
||
RUN mkdir -p /app/src/github.com/darkweak/cmd | ||
RUN mkdir -p /app/src/github.com/darkweak/souin | ||
ADD ./*.go /app/src/github.com/darkweak/souin/ | ||
ADD ./cache /app/src/github.com/darkweak/souin/cache | ||
ADD ./default/server.* /app/src/github.com/darkweak/souin/ | ||
ADD ./entrypoint.sh /app/src/github.com/darkweak/souin/entrypoint.sh | ||
|
||
WORKDIR /app/src/github.com/darkweak/souin | ||
ENV GOPATH /app | ||
ENV GOOS linux | ||
ENV GOARCH arm | ||
RUN go get ./... | ||
RUN go get -u golang.org/x/lint/golint | ||
RUN go install | ||
RUN chmod 755 ./entrypoint.sh | ||
|
||
EXPOSE 80 | ||
|
||
ENTRYPOINT ["./entrypoint.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
.PHONY: build-app build-dev create-network down env-dev env-prod help lint tests up validate | ||
|
||
DC=docker-compose | ||
DC_BUILD=$(DC) build | ||
DC_EXEC=$(DC) exec | ||
|
||
build-app: env-prod ## Build containers with prod env vars | ||
$(DC_BUILD) souin | ||
$(MAKE) up | ||
|
||
build-dev: env-dev ## Build containers with dev env vars | ||
$(DC_BUILD) souin | ||
$(MAKE) up | ||
|
||
create-network: ## Create network | ||
docker network create your_network | ||
|
||
down: ## Down containers | ||
$(DC) down --remove-orphans | ||
|
||
env-dev: ## Up container with dev env vars | ||
cp Dockerfile-dev Dockerfile | ||
cp docker-compose.yml.dev docker-compose.yml | ||
cp .env.dev .env | ||
|
||
env-prod: ## Up container with prod env vars | ||
cp Dockerfile-prod Dockerfile | ||
cp docker-compose.yml.prod docker-compose.yml | ||
cp .env.prod .env | ||
|
||
help: | ||
@grep -E '(^[0-9a-zA-Z_-]+:.*?##.*$$)|(^##)' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[32m%-25s\033[0m %s\n", $$1, $$2}' | sed -e 's/\[32m##/[33m/' | ||
|
||
lint: ## Run lint | ||
$(DC_EXEC) souin /app/bin/golint ./cache | ||
|
||
tests: ## Run tests | ||
$(DC_EXEC) souin go test -v ./... | ||
|
||
up: ## Up containers | ||
$(DC) up -d --remove-orphans | ||
|
||
validate: lint tests ## Run lint and tests |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
<p align="center"><a href="https://github.com/darkweak/souin"><img src="docs/img/logo.svg?sanitize=true" alt="Souin logo"></a></p> | ||
|
||
# Souin Table of Contents | ||
1. [Souin reverse-proxy cache](#project-description) | ||
2. [Environment variables](#environment-variables) | ||
2.1. [Required variables](#required-variables) | ||
2.2. [Optional variables](#optional-variables) | ||
3. [Cache system](#cache-system) | ||
4. [Exemples](#exemples) | ||
4.1. [Træfik container](#træfik-container) | ||
|
||
[![Travis CI](https://travis-ci.com/Darkweak/Souin.svg?branch=master)](https://travis-ci.com/Darkweak/Souin) | ||
|
||
# <img src="docs/img/logo.svg?sanitize=true" alt="Souin logo" width="30" height="30">ouin reverse-proxy cache | ||
|
||
## Project description | ||
Souin is a new cache system for every reverse-proxy. It will be placed on top of your reverse-proxy like Apache, NGinx or Traefik. | ||
As it's written in go, it can be deployed on any server and with docker integration, it will be easy to implement it on top of Swarm or kubernetes instance. | ||
|
||
## Environment variables | ||
|
||
### Required variables | ||
| Variable | Description | Value exemple | | ||
|:---:|:---:|:---:| | ||
|`CACHE_PORT`|The HTTP port Souin will be running to|`80`| | ||
|`CACHE_TLS_PORT`|The TLS port Souin will be running to|`443`| | ||
|`REDIS_URL`|The redis instance URL|- `http://redis` (Container way)<br/>`http://localhost:6379` (Local way)| | ||
|`TTL`|Duration to cache request (in seconds)|10| | ||
|`REVERSE_PROXY`|The reverse-proxy instance URL like Apache, Nginx, Træfik, etc...|- `http://yourservice` (Container way)<br/>`http://localhost:81` (Local way)| | ||
|
||
### Optional variables | ||
| Variable | Description | Value exemple | | ||
|:---:|:---:|:---:| | ||
|`REGEX`|The regex to define URL to not store in cache|`http://domain.com/mypath`| | ||
|
||
## Cache system | ||
The cache is set into redis instance, because we can set, get, update and delete keys as easy as possible. | ||
To perform with that, redis should be on the same network than Souin instance if you are using docker-compose, then both should be on the same server if you use binaries | ||
Asynchronously, Souin will request redis instance and the reverse-proxy to get at least one valid response and return to the client the first response caught by Souin. | ||
|
||
### Cache invalidation | ||
The cache invalidation is made for CRUD requests, if you're doing a GET HTTP request, it will serve the cached response if exists then the reverse-proxy response will be served. | ||
If you're doing a POST, PUT, PATCH or DELETE HTTP request, the related cached get request will be dropped and the list endpoint will be dropped too | ||
It works very well with plain [API Platform](https://api-platform.com) integration (but not custom actions for now) and CRUD routes | ||
|
||
## Exemples | ||
|
||
### Træfik container | ||
[Træfik](https://traefik.io) is a modern reverse-proxy and help you to manage full container architecure projects. | ||
|
||
```yaml | ||
# your-traefik-instance/docker-compose.yml | ||
version: '3.4' | ||
|
||
x-networks: &networks | ||
networks: | ||
- your_network | ||
|
||
services: | ||
traefik: | ||
image: traefik:v2.0 | ||
ports: | ||
- "81:80" # Note the 81 to 80 port declaration | ||
- "444:443" # Note the 444 to 443 port declaration | ||
command: --providers.docker | ||
volumes: | ||
- /var/run/docker.sock:/var/run/docker.sock | ||
<<: *networks | ||
|
||
# your other services here... | ||
|
||
networks: | ||
your_network: | ||
external: true | ||
``` | ||
```yaml | ||
# your-souin-instance/docker-compose.yml | ||
version: '3.4' | ||
|
||
x-networks: &networks | ||
networks: | ||
- your_network | ||
|
||
services: | ||
souin: | ||
build: | ||
context: . | ||
ports: | ||
- ${CACHE_PORT}:80 | ||
- ${CACHE_TLS_PORT}:443 | ||
depends_on: | ||
- redis | ||
environment: | ||
REDIS_URL: ${REDIS_URL} | ||
TTL: ${TTL} | ||
CACHE_PORT: ${CACHE_PORT} | ||
CACHE_TLS_PORT: ${CACHE_TLS_PORT} | ||
REVERSE_PROXY: ${REVERSE_PROXY} | ||
REGEX: ${REGEX} | ||
GOPATH: /app | ||
volumes: | ||
- ./cmd:/app/cmd | ||
<<: *networks | ||
|
||
redis: | ||
image: redis:alpine | ||
<<: *networks | ||
|
||
networks: | ||
your_network: | ||
external: true | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package cache | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func generateError(t *testing.T, text string) { | ||
t.Errorf("An error occurred : %s", text) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
package cache | ||
|
||
import ( | ||
"github.com/go-redis/redis" | ||
"time" | ||
"os" | ||
"strconv" | ||
"regexp" | ||
) | ||
|
||
func redisClientConnectionFactory() *redis.Client { | ||
return redis.NewClient(&redis.Options{ | ||
Addr: os.Getenv("REDIS_URL"), | ||
DB: 0, | ||
Password: "", | ||
}) | ||
} | ||
|
||
func pathnameNotInRegex(pathname string) bool { | ||
b, _ := regexp.Match(os.Getenv("REGEX"), []byte(pathname)) | ||
return !b | ||
} | ||
|
||
func getRequestInCache(pathname string) ReverseResponse { | ||
client := redisClientConnectionFactory() | ||
val2, err := client.Get(pathname).Result() | ||
|
||
if err != nil { | ||
return ReverseResponse{"", nil, nil} | ||
} | ||
|
||
return ReverseResponse{val2, nil, nil} | ||
} | ||
|
||
func deleteKey(key string) { | ||
client := redisClientConnectionFactory(); | ||
client.Do("del", key) | ||
} | ||
|
||
func deleteKeys(regex string) { | ||
client := redisClientConnectionFactory(); | ||
for _, i := range client.Keys(regex).Val() { | ||
client.Do("del", i) | ||
} | ||
} | ||
|
||
func setRequestInCache(pathname string, data []byte) { | ||
client := redisClientConnectionFactory() | ||
value, _ := strconv.Atoi(os.Getenv("TTL")) | ||
|
||
err := client.Set(pathname, string(data), time.Duration(value) * time.Second).Err() | ||
if err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cache | ||
|
||
import ( | ||
"testing" | ||
"time" | ||
"fmt" | ||
) | ||
|
||
const VALUE = "My first data" | ||
|
||
func populateRedisWithFakeData() { | ||
client := redisClientConnectionFactory() | ||
duration := time.Duration(120) * time.Second | ||
basePath := "/testing" | ||
domain := "domain.com" | ||
|
||
client.Set(domain+basePath, "testing value is here for "+basePath, duration) | ||
for i := 0; i < 25; i++ { | ||
client.Set(domain+basePath+"/"+string(i), "testing value is here for my first init of "+basePath+"/"+string(i), duration) | ||
} | ||
} | ||
|
||
func TestIShouldBeAbleToReadAndWriteDataInRedis(t *testing.T) { | ||
client := redisClientConnectionFactory() | ||
err := client.Set("Test", string(VALUE), time.Duration(10)*time.Second).Err() | ||
if err != nil { | ||
generateError(t, "Impossible to set redis variable") | ||
} | ||
res, err := client.Get("Test").Result() | ||
if err != nil { | ||
generateError(t, "Retrieving data from redis") | ||
} | ||
if VALUE != res { | ||
generateError(t, fmt.Sprintf("%s not corresponding to %s", res, VALUE)) | ||
} | ||
} |
Oops, something went wrong.