Skip to content

Commit a27fbbe

Browse files
prepare to v0.0.4
1 parent 921958e commit a27fbbe

46 files changed

Lines changed: 431 additions & 88 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
*.db
55
*.db-shm
66
*.db-wal
7+
httpcache.so
8+
httpcache.h
79

810
# Added by goreleaser init:
911
dist/

.goreleaser.yaml

Lines changed: 68 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ builds:
1010
- id: httpcache
1111
binary: httpcache
1212
buildmode: "c-shared"
13+
flags:
14+
- -tags=zig
1315
ldflags:
1416
- -s -w -X github.com/walterwanderley/sqlite-http-cache/extension.version={{.Version}} -X github.com/walterwanderley/sqlite-http-cache/extension.commit={{.Commit}} -X github.com/walterwanderley/sqlite-http-cache/extension.date={{.Date}}
1517
goos:
@@ -18,10 +20,13 @@ builds:
1820
- amd64
1921
env:
2022
- CGO_ENABLED=1
23+
- CC=zig cc -target x86_64-linux-gnu
2124

2225
- id: httpcache_windows
2326
binary: httpcache
2427
buildmode: "c-shared"
28+
flags:
29+
- -tags=zig
2530
ldflags:
2631
- -s -w -X github.com/walterwanderley/sqlite-http-cache/extension.version={{.Version}} -X github.com/walterwanderley/sqlite-http-cache/extension.commit={{.Commit}} -X github.com/walterwanderley/sqlite-http-cache/extension.date={{.Date}}
2732
goos:
@@ -32,19 +37,38 @@ builds:
3237
- CGO_ENABLED=1
3338
- CC=zig cc -target x86_64-windows
3439

40+
- id: httpcache_darwin
41+
binary: httpcache
42+
buildmode: "c-shared"
43+
ldflags:
44+
- -s -w -X github.com/walterwanderley/sqlite-http-cache/extension.version={{.Version}} -X github.com/walterwanderley/sqlite-http-cache/extension.commit={{.Commit}} -X github.com/walterwanderley/sqlite-http-cache/extension.date={{.Date}}
45+
goos:
46+
- darwin
47+
goarch:
48+
- amd64
49+
- arm64
50+
env:
51+
- CGO_ENABLED=1
52+
- CC=o64-clang
53+
3554
- id: sqlite-http-proxy
3655
main: ./cmd/sqlite-http-proxy
3756
binary: sqlite-http-proxy
57+
flags:
58+
- -tags=zig
3859
goos:
3960
- linux
4061
goarch:
4162
- amd64
4263
env:
4364
- CGO_ENABLED=1
65+
- CC=zig cc -target x86_64-linux-musl
4466

4567
- id: sqlite-http-proxy_windows
4668
main: ./cmd/sqlite-http-proxy
4769
binary: sqlite-http-proxy
70+
flags:
71+
- -tags=zig
4872
goos:
4973
- windows
5074
goarch:
@@ -53,15 +77,55 @@ builds:
5377
- CGO_ENABLED=1
5478
- CC=zig cc -target x86_64-windows
5579

80+
- id: sqlite-http-proxy_darwin
81+
main: ./cmd/sqlite-http-proxy
82+
binary: sqlite-http-proxy
83+
goos:
84+
- darwin
85+
goarch:
86+
- amd64
87+
- arm64
88+
env:
89+
- CGO_ENABLED=1
90+
- CC=o64-clang
91+
5692
- id: sqlite-http-refresh
5793
main: ./cmd/sqlite-http-refresh
5894
binary: sqlite-http-refresh
95+
flags:
96+
- -tags=zig
5997
goos:
6098
- linux
6199
goarch:
62100
- amd64
63101
env:
64102
- CGO_ENABLED=1
103+
- CC=zig cc -target x86_64-linux-musl
104+
105+
- id: sqlite-http-refresh_windows
106+
main: ./cmd/sqlite-http-refresh
107+
binary: sqlite-http-refresh
108+
flags:
109+
- -tags=zig
110+
goos:
111+
- windows
112+
goarch:
113+
- amd64
114+
env:
115+
- CGO_ENABLED=1
116+
- CC=zig cc -target x86_64-windows
117+
118+
- id: sqlite-http-refresh_darwin
119+
main: ./cmd/sqlite-http-refresh
120+
binary: sqlite-http-refresh
121+
goos:
122+
- darwin
123+
goarch:
124+
- amd64
125+
- arm64
126+
env:
127+
- CGO_ENABLED=1
128+
- CC=o64-clang
65129

66130
- id: libsql-http-proxy
67131
main: ./cmd/libsql-http-proxy
@@ -76,10 +140,10 @@ builds:
76140
archives:
77141
- id: httpcache
78142
formats: [tar.gz]
79-
ids: [httpcache, httpcache_windows]
143+
ids: [httpcache, httpcache_windows, httpcache_darwin]
80144
# this name template makes the OS and Arch compatible with the results of `uname`.
81145
name_template: >-
82-
httpcache_
146+
httpcache_v
83147
{{- .Version }}_
84148
{{- title .Os }}_
85149
{{- if eq .Arch "amd64" }}x86_64
@@ -95,7 +159,7 @@ archives:
95159

96160
- id: sqlite-http-proxy
97161
formats: [tar.gz]
98-
ids: [sqlite-http-proxy, sqlite-http-proxy_windows]
162+
ids: [sqlite-http-proxy, sqlite-http-proxy_windows, sqlite-http-proxy_darwin]
99163
# this name template makes the OS and Arch compatible with the results of `uname`.
100164
name_template: >-
101165
{{- .Binary }}_
@@ -114,7 +178,7 @@ archives:
114178

115179
- id: sqlite-http-refresh
116180
formats: [tar.gz]
117-
ids: [sqlite-http-refresh]
181+
ids: [sqlite-http-refresh, sqlite-http-refresh_windows, sqlite-http-refresh_darwin]
118182
# this name template makes the OS and Arch compatible with the results of `uname`.
119183
name_template: >-
120184
{{- .Binary }}_

Dockerfile-builder

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM crazymax/osxcross:15.5-debian as osxcross
2+
3+
FROM golang:1.25-trixie
4+
5+
RUN apt update
6+
RUN apt install -y dpkg curl tar xz-utils zip gettext clang lld libc-dev
7+
8+
RUN curl https://ziglang.org/download/0.14.1/zig-x86_64-linux-0.14.1.tar.xz | tar x -J -C /opt
9+
RUN ln -s /opt/zig* /opt/zig
10+
11+
ENV PATH="$PATH:/opt/zig"
12+
13+
RUN curl -o goreleaser_amd64.tar.gz -L https://github.com/goreleaser/goreleaser/releases/download/v2.11.2/goreleaser_Linux_x86_64.tar.gz
14+
RUN tar xvf goreleaser_amd64.tar.gz -C /usr/bin
15+
16+
COPY --from=osxcross /osxcross /osxcross
17+
18+
ENV PATH="/osxcross/bin:$PATH"
19+
ENV LD_LIBRARY_PATH="/osxcross/lib:$LD_LIBRARY_PATH"
20+
21+
WORKDIR /app
22+
23+
COPY . /app

LICENSE

100644100755
File mode changed.

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
.PRONY: builder
3+
builder:
4+
docker build -f Dockerfile-builder -t builder .
5+
6+
.PHONY: snapshot
7+
snapshot: builder
8+
docker run -e GITHUB_TOKEN=${GITHUB_TOKEN} builder goreleaser release --clean --snapshot --skip publish
9+
10+
.PHONY: release
11+
release: builder
12+
docker run -e GITHUB_TOKEN=${GITHUB_TOKEN} builder goreleaser release --clean

README.md

100644100755
Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ Download **httpcache** extension from the [releases page](https://github.com/wal
99

1010
### Compiling from source
1111

12+
- [Go 1.24+](https://go.dev) is required.
13+
1214
```sh
1315
go build -ldflags="-s -w" -buildmode=c-shared -o httpcache.so
1416
```
@@ -21,9 +23,6 @@ sqlite3
2123
# Load the extension
2224
.load ./httpcache
2325

24-
# Check extension info
25-
SELECT cache_info();
26-
2726
# Insert URL into the temp.http_request virtual table to trigger the HTTP Request
2827
INSERT INTO temp.http_request VALUES('https://swapi.tech/api/films/1');
2928

@@ -34,28 +33,68 @@ INSERT INTO temp.http_request VALUES('https://swapi.tech/api/films/1');
3433
SELECT JSON_EXTRACT(body, '$.result.properties.title') AS title,
3534
JSON_EXTRACT(body, '$.result.properties.release_date') AS release_date
3635
FROM http_response;
36+
┌──────────────┬──────────────┐
37+
│ title │ release_date │
38+
├──────────────┼──────────────┤
39+
'A New Hope''1977-05-25'
40+
└──────────────┴──────────────┘
3741

3842
# Use cache_age, cache_lifetime or cache_expired function to check cache validity based on RFC9111
3943
SELECT url, cache_age(header, request_time, response_time) AS age,
4044
cache_lifetime(header, response_time) AS lifetime,
4145
cache_expired(header, request_time, response_time, false) AS expired,
4246
cache_expired_ttl(header, request_time, response_time, false, 3600) AS expiredTTLFallback
4347
FROM http_response;
48+
┌──────────────────────────────────┬─────┬──────────┬─────────┬────────────────────┐
49+
│ url │ age │ lifetime │ expired │ expiredTTLFallback │
50+
├──────────────────────────────────┼─────┼──────────┼─────────┼────────────────────┤
51+
'https://swapi.tech/api/films/1' │ 37 │ 0 │ 1 │ 0 │
52+
└──────────────────────────────────┴─────┴──────────┴─────────┴────────────────────┘
4453
```
4554

4655
All HTTP responses are stored in tables using the following schema:
4756

4857
```sql
49-
CREATE TABLE IF NOT EXISTS http_response(
50-
url TEXT PRIMARY KEY,
51-
status INTEGER,
52-
body BLOB,
53-
header JSONB,
54-
request_time DATETIME,
55-
response_time DATETIME
58+
TABLE http_response(
59+
url TEXT PRIMARY KEY,
60+
status INTEGER,
61+
body BLOB,
62+
header JSONB,
63+
request_time DATETIME,
64+
response_time DATETIME
5665
)
5766
```
5867

68+
If you want to customize the persisted data, just create an another table and create triggers for "http_response".
69+
70+
```sql
71+
CREATE TABLE movies(
72+
ID INTEGER PRIMARY KEY AUTOINCREMENT,
73+
title TEXT,
74+
release_date DATETIME
75+
);
76+
77+
CREATE TRIGGER insert_http_response
78+
AFTER INSERT ON http_response
79+
BEGIN
80+
INSERT INTO movies(title, release_date)
81+
VALUES(
82+
JSON_EXTRACT(NEW.body, '$.result.properties.title'),
83+
JSON_EXTRACT(NEW.body, '$.result.properties.release_date')
84+
);
85+
END;
86+
87+
INSERT INTO temp.http_request VALUES('https://swapi.tech/api/films/2');
88+
89+
SELECT * FROM movies;
90+
┌────┬───────────────────────────┬──────────────┐
91+
│ ID │ title │ release_date │
92+
├────┼───────────────────────────┼──────────────┤
93+
1'The Empire Strikes Back''1980-05-17'
94+
└────┴───────────────────────────┴──────────────┘
95+
96+
```
97+
5998
## Configuring
6099

61100
You can configure the behaviour by passing parameters to a VIRTUAL TABLE.
@@ -143,7 +182,7 @@ WHERE unixepoch() - unixepoch(response_time) > :ttl ;
143182

144183
## SQLite Proxy Cache
145184

146-
The sqlite-http-proxy is an HTTP proxy cache that can store data in multiple sqlite databases and query concurrently to get the faster response. The cache imlements the RFC9111 (except the vary header).
185+
The sqlite-http-proxy is an HTTP proxy cache that can store data in multiple sqlite databases and query concurrently to get the faster response. The cache implements [RFC9111](https://www.rfc-editor.org/rfc/rfc9111.html) (except for the Vary header).
147186

148187
1. Installation:
149188

@@ -166,6 +205,33 @@ time curl -x http://127.0.0.1:9090 http://swapi.tech/api/films/1
166205
time curl -x http://127.0.0.1:9090 http://swapi.tech/api/films/1
167206
```
168207

208+
### Proxing HTTPS Requests
209+
210+
To proxy https requests you need to pass CA Certificate and CA Certificate key to the sqlite-http-proxy.
211+
212+
```sh
213+
sqlite-http-proxy --ca-cert=/path/to/ca.crt --ca-cert-key=/path/to/ca.key proxyN.db
214+
```
215+
216+
Use the command line flag --help for more info.
217+
169218
```sh
170219
sqlite-http-proxy --help
220+
```
221+
222+
## Go HTTP Client
223+
224+
This repository has an http.Transport implementation to use sqlite as cache of HTTP requests from golang.
225+
226+
```go
227+
package main
228+
229+
import httpcache "github.com/walterwanderley/sqlite-http-cache/http"
230+
231+
func main() {
232+
233+
}
234+
235+
236+
171237
```

cmd/libsql-http-proxy/main.go

100644100755
Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"time"
1616

1717
"github.com/elazarl/goproxy"
18+
"github.com/elazarl/goproxy/ext/auth"
1819
"github.com/peterbourgon/ff/v4"
1920
"github.com/peterbourgon/ff/v4/ffhelp"
2021
"github.com/tursodatabase/go-libsql"
@@ -31,6 +32,7 @@ func main() {
3132
dbSyncInterval := fs.DurationLong("db-sync-interval", 30*time.Second, "Database sync interval")
3233
dbAuthToken := fs.StringLong("db-token", "", "Database authorization token")
3334
dbEncryptionKey := fs.StringLong("db-key", "", "Database encryption key")
35+
dbCleanupInterval := fs.DurationLong("db-cleanup-interval", 0, "Database cleanup interval. Data is deleted using --ttl as reference")
3436
verbose := fs.Bool('v', "verbose", "Enable verbose mode")
3537
allowHTTP2 := fs.BoolLong("h2", "Allow HTTP2")
3638
statusCodes := fs.StringListLong("status-code", fmt.Sprintf("List of cacheable status code. Defaults to the heuristically cacheable codes: %v", config.DefaultStatusCodes()))
@@ -41,6 +43,8 @@ func main() {
4143
readOnly := fs.BoolLong("ro", "Read Only mode. Do not store new HTTP responses")
4244
rfc9111 := fs.BoolLong("rfc9111", "Use RFC9111 spec")
4345
shared := fs.BoolLong("shared", "Enable shared cache mode")
46+
authUser := fs.StringLong("auth-user", "", "Username for proxy basic authentication")
47+
authPass := fs.StringLong("auth-pass", "", "Password for proxy basic authentication")
4448
_ = fs.String('c', "config", "", "config file (optional)")
4549

4650
if err := ff.Parse(fs, os.Args[1:],
@@ -141,12 +145,12 @@ func main() {
141145

142146
}
143147
if len(dbs) == 1 {
144-
repository, err = db.NewRepository(dbs[0], tableList...)
148+
repository, err = db.NewRepository(dbs[0], time.Duration(*ttl)*time.Second, *dbCleanupInterval, tableList...)
145149
if err != nil {
146150
log.Fatalf("new repository: %v", err)
147151
}
148152
} else {
149-
repository, err = db.NewMultiDatabaseRepository(dbs)
153+
repository, err = db.NewMultiDatabaseRepositoryWithTTL(time.Duration(*ttl)*time.Second, *dbCleanupInterval, dbs)
150154
if err != nil {
151155
log.Fatalf("new multi database repository: %v", err)
152156
}
@@ -157,6 +161,12 @@ func main() {
157161
proxy.Verbose = *verbose
158162
proxy.AllowHTTP2 = *allowHTTP2
159163

164+
if *authUser != "" {
165+
auth.ProxyBasic(proxy, "Auth", func(user, passwd string) bool {
166+
return user == *authUser && *authPass == passwd
167+
})
168+
}
169+
160170
if *caCert != "" && *caCertKey != "" {
161171
proxy.Logger.Printf("INFO: Starting HTTP/HTTPS Proxy...")
162172
cert, err := parseCA([]byte(*caCert), []byte(*caCertKey))

0 commit comments

Comments
 (0)