Skip to content

Commit 65b4a78

Browse files
committed
Setup - first commit
0 parents  commit 65b4a78

23 files changed

Lines changed: 747 additions & 0 deletions

.env.dev

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CACHE_PORT=80
2+
CACHE_TLS_PORT=443
3+
REDIS_URL=redis:6379
4+
TTL=10
5+
REVERSE_PROXY=http://traefik
6+
7+
REGEX=ARegexHere

.env.prod

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CACHE_PORT=80
2+
CACHE_TLS_PORT=443
3+
REDIS_URL=redis:6379
4+
TTL=10
5+
REVERSE_PROXY=http://traefik
6+
7+
REGEX=ARegexHere

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/cmd/*
2+
.env
3+
docker-compose.yml
4+
Dockerfile
5+
/.idea/

.travis.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
sudo: required
2+
language: go
3+
4+
addons:
5+
apt:
6+
packages:
7+
- docker-ce
8+
9+
git:
10+
depth: 1
11+
12+
notifications:
13+
email: false
14+
15+
services:
16+
- docker
17+
18+
before_install:
19+
- make create-network
20+
- make build-dev
21+
22+
script:
23+
- make validate

Dockerfile-dev

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM golang:1.13-alpine
2+
3+
RUN apk update && apk upgrade && \
4+
apk add --no-cache bash git openssh gcc libc-dev
5+
6+
RUN mkdir -p /app/src/github.com/darkweak/souin
7+
ADD ./*.go /app/src/github.com/darkweak/souin/
8+
ADD ./cache /app/src/github.com/darkweak/souin/cache
9+
ADD ./default/server.* /app/src/github.com/darkweak/souin/
10+
11+
WORKDIR /app/src/github.com/darkweak/souin
12+
ENV GOPATH /app
13+
RUN go get ./...
14+
RUN go get -u golang.org/x/lint/golint
15+
16+
EXPOSE 80
17+
18+
CMD ["go", "run", "main.go"]

Dockerfile-prod

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
FROM golang:1.13-alpine
2+
3+
RUN apk update && apk upgrade && \
4+
apk add --no-cache bash git openssh gcc libc-dev
5+
6+
RUN mkdir -p /app/src/github.com/darkweak/cmd
7+
RUN mkdir -p /app/src/github.com/darkweak/souin
8+
ADD ./*.go /app/src/github.com/darkweak/souin/
9+
ADD ./cache /app/src/github.com/darkweak/souin/cache
10+
ADD ./default/server.* /app/src/github.com/darkweak/souin/
11+
ADD ./entrypoint.sh /app/src/github.com/darkweak/souin/entrypoint.sh
12+
13+
WORKDIR /app/src/github.com/darkweak/souin
14+
ENV GOPATH /app
15+
ENV GOOS linux
16+
ENV GOARCH arm
17+
RUN go get ./...
18+
RUN go get -u golang.org/x/lint/golint
19+
RUN go install
20+
RUN chmod 755 ./entrypoint.sh
21+
22+
EXPOSE 80
23+
24+
ENTRYPOINT ["./entrypoint.sh"]

Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
.PHONY: build-app build-dev create-network down env-dev env-prod help lint tests up validate
2+
3+
DC=docker-compose
4+
DC_BUILD=$(DC) build
5+
DC_EXEC=$(DC) exec
6+
7+
build-app: env-prod ## Build containers with prod env vars
8+
$(DC_BUILD) souin
9+
$(MAKE) up
10+
11+
build-dev: env-dev ## Build containers with dev env vars
12+
$(DC_BUILD) souin
13+
$(MAKE) up
14+
15+
create-network: ## Create network
16+
docker network create your_network
17+
18+
down: ## Down containers
19+
$(DC) down --remove-orphans
20+
21+
env-dev: ## Up container with dev env vars
22+
cp Dockerfile-dev Dockerfile
23+
cp docker-compose.yml.dev docker-compose.yml
24+
cp .env.dev .env
25+
26+
env-prod: ## Up container with prod env vars
27+
cp Dockerfile-prod Dockerfile
28+
cp docker-compose.yml.prod docker-compose.yml
29+
cp .env.prod .env
30+
31+
help:
32+
@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/'
33+
34+
lint: ## Run lint
35+
$(DC_EXEC) souin /app/bin/golint ./cache
36+
37+
tests: ## Run tests
38+
$(DC_EXEC) souin go test -v ./...
39+
40+
up: ## Up containers
41+
$(DC) up -d --remove-orphans
42+
43+
validate: lint tests ## Run lint and tests

README.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<p align="center"><a href="https://github.com/darkweak/souin"><img src="docs/img/logo.svg?sanitize=true" alt="Souin logo"></a></p>
2+
3+
# Souin Table of Contents
4+
1. [Souin reverse-proxy cache](#project-description)
5+
2. [Environment variables](#environment-variables)
6+
2.1. [Required variables](#required-variables)
7+
2.2. [Optional variables](#optional-variables)
8+
3. [Cache system](#cache-system)
9+
4. [Exemples](#exemples)
10+
4.1. [Træfik container](#træfik-container)
11+
12+
[![Travis CI](https://travis-ci.com/Darkweak/Souin.svg?branch=master)](https://travis-ci.com/Darkweak/Souin)
13+
14+
# <img src="docs/img/logo.svg?sanitize=true" alt="Souin logo" width="30" height="30">ouin reverse-proxy cache
15+
16+
## Project description
17+
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.
18+
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.
19+
20+
## Environment variables
21+
22+
### Required variables
23+
| Variable | Description | Value exemple |
24+
|:---:|:---:|:---:|
25+
|`CACHE_PORT`|The HTTP port Souin will be running to|`80`|
26+
|`CACHE_TLS_PORT`|The TLS port Souin will be running to|`443`|
27+
|`REDIS_URL`|The redis instance URL|- `http://redis` (Container way)<br/>`http://localhost:6379` (Local way)|
28+
|`TTL`|Duration to cache request (in seconds)|10|
29+
|`REVERSE_PROXY`|The reverse-proxy instance URL like Apache, Nginx, Træfik, etc...|- `http://yourservice` (Container way)<br/>`http://localhost:81` (Local way)|
30+
31+
### Optional variables
32+
| Variable | Description | Value exemple |
33+
|:---:|:---:|:---:|
34+
|`REGEX`|The regex to define URL to not store in cache|`http://domain.com/mypath`|
35+
36+
## Cache system
37+
The cache is set into redis instance, because we can set, get, update and delete keys as easy as possible.
38+
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
39+
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.
40+
41+
### Cache invalidation
42+
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.
43+
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
44+
It works very well with plain [API Platform](https://api-platform.com) integration (but not custom actions for now) and CRUD routes
45+
46+
## Exemples
47+
48+
### Træfik container
49+
[Træfik](https://traefik.io) is a modern reverse-proxy and help you to manage full container architecure projects.
50+
51+
```yaml
52+
# your-traefik-instance/docker-compose.yml
53+
version: '3.4'
54+
55+
x-networks: &networks
56+
networks:
57+
- your_network
58+
59+
services:
60+
traefik:
61+
image: traefik:v2.0
62+
ports:
63+
- "81:80" # Note the 81 to 80 port declaration
64+
- "444:443" # Note the 444 to 443 port declaration
65+
command: --providers.docker
66+
volumes:
67+
- /var/run/docker.sock:/var/run/docker.sock
68+
<<: *networks
69+
70+
# your other services here...
71+
72+
networks:
73+
your_network:
74+
external: true
75+
```
76+
77+
```yaml
78+
# your-souin-instance/docker-compose.yml
79+
version: '3.4'
80+
81+
x-networks: &networks
82+
networks:
83+
- your_network
84+
85+
services:
86+
souin:
87+
build:
88+
context: .
89+
ports:
90+
- ${CACHE_PORT}:80
91+
- ${CACHE_TLS_PORT}:443
92+
depends_on:
93+
- redis
94+
environment:
95+
REDIS_URL: ${REDIS_URL}
96+
TTL: ${TTL}
97+
CACHE_PORT: ${CACHE_PORT}
98+
CACHE_TLS_PORT: ${CACHE_TLS_PORT}
99+
REVERSE_PROXY: ${REVERSE_PROXY}
100+
REGEX: ${REGEX}
101+
GOPATH: /app
102+
volumes:
103+
- ./cmd:/app/cmd
104+
<<: *networks
105+
106+
redis:
107+
image: redis:alpine
108+
<<: *networks
109+
110+
networks:
111+
your_network:
112+
external: true
113+
```

cache/error.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package cache
2+
3+
import (
4+
"testing"
5+
)
6+
7+
func generateError(t *testing.T, text string) {
8+
t.Errorf("An error occurred : %s", text)
9+
}

cache/redisConnection.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package cache
2+
3+
import (
4+
"github.com/go-redis/redis"
5+
"time"
6+
"os"
7+
"strconv"
8+
"regexp"
9+
)
10+
11+
func redisClientConnectionFactory() *redis.Client {
12+
return redis.NewClient(&redis.Options{
13+
Addr: os.Getenv("REDIS_URL"),
14+
DB: 0,
15+
Password: "",
16+
})
17+
}
18+
19+
func pathnameNotInRegex(pathname string) bool {
20+
b, _ := regexp.Match(os.Getenv("REGEX"), []byte(pathname))
21+
return !b
22+
}
23+
24+
func getRequestInCache(pathname string) ReverseResponse {
25+
client := redisClientConnectionFactory()
26+
val2, err := client.Get(pathname).Result()
27+
28+
if err != nil {
29+
return ReverseResponse{"", nil, nil}
30+
}
31+
32+
return ReverseResponse{val2, nil, nil}
33+
}
34+
35+
func deleteKey(key string) {
36+
client := redisClientConnectionFactory();
37+
client.Do("del", key)
38+
}
39+
40+
func deleteKeys(regex string) {
41+
client := redisClientConnectionFactory();
42+
for _, i := range client.Keys(regex).Val() {
43+
client.Do("del", i)
44+
}
45+
}
46+
47+
func setRequestInCache(pathname string, data []byte) {
48+
client := redisClientConnectionFactory()
49+
value, _ := strconv.Atoi(os.Getenv("TTL"))
50+
51+
err := client.Set(pathname, string(data), time.Duration(value) * time.Second).Err()
52+
if err != nil {
53+
panic(err)
54+
}
55+
}

0 commit comments

Comments
 (0)