@@ -4,51 +4,53 @@ import (
44 "crypto/tls"
55 "crypto/x509"
66 "database/sql"
7- "flag"
87 "fmt"
98 "log"
109 "net"
1110 "net/http"
1211 "os"
12+ "path/filepath"
1313 "strings"
1414
1515 "github.com/elazarl/goproxy"
1616 _ "github.com/mattn/go-sqlite3"
17+ "github.com/peterbourgon/ff/v4"
18+ "github.com/peterbourgon/ff/v4/ffhelp"
1719
1820 "github.com/walterwanderley/sqlite-http-cache/db"
1921)
2022
21- var (
22- port uint
23- dbParams string
24- allowHTTP2 bool
25- verbose bool
26-
27- ttl uint
28-
29- caCert string
30- caCertKey string
23+ func main () {
24+ fs := ff .NewFlagSet ("sqlite-http-proxy" )
25+ port := fs .Uint ('p' , "port" , 8080 , "Server port" )
26+ dbParams := fs .StringLong ("db-params" , "_journal=WAL&_sync=NORMAL&_timeout=5000&_txlock=immediate" , "Database connection params" )
27+ verbose := fs .Bool ('v' , "verbose" , "Enable verbose mode" )
28+ allowHTTP2 := fs .BoolLong ("h2" , "Allow HTTP2" )
29+ ttl := fs .UintLong ("ttl" , 0 , "Time to Live in seconds (0 is infinite time)" )
30+ responseTables := fs .StringListLong ("response-table" , "List of database tables used to store response data" )
31+ forceCreateTables := fs .BoolLong ("force-create-tables" , "Force create response tables if not exists" )
32+ caCert := fs .StringLong ("ca-cert" , "" , "Path to CA Certificate file (required to HTTPS proxy)" )
33+ caCertKey := fs .StringLong ("ca-cert-key" , "" , "Path to CA Certificate Key file (required to HTTPS proxy)" )
34+ readOnly := fs .BoolLong ("ro" , "Read Only mode. Do not store new HTTP responses" )
35+ _ = fs .String ('c' , "config" , "" , "config file (optional)" )
36+
37+ if err := ff .Parse (fs , os .Args [1 :],
38+ ff .WithEnvVarPrefix ("SQLITE_HTTP_PROXY" ),
39+ ff .WithConfigFileFlag ("config" ),
40+ ff .WithConfigFileParser (ff .PlainParser ),
41+ ); err != nil {
42+ fmt .Printf ("%s\n " , ffhelp .Flags (fs ))
43+ fmt .Printf ("err=%v\n " , err )
44+ return
45+ }
3146
32- responseTables string
33- forceCreateTables bool
34- readOnly bool
35- )
47+ if len (fs .GetArgs ()) == 0 {
48+ log .Fatalf ("Usage: %s <FLAGS> [DatabasePath1] [DatabasePathN\n \n Example:\n \t %s example.db example2.db example3.db\n " , os .Args [0 ], os .Args [0 ])
49+ }
3650
37- func main () {
38- flag .UintVar (& port , "p" , 8080 , "Server port" )
39- flag .StringVar (& dbParams , "db-params" , "_journal=WAL&_sync=NORMAL&_timeout=5000&_txlock=immediate" , "Database connection params" )
40- flag .BoolVar (& verbose , "v" , false , "Enable verbose mode" )
41- flag .BoolVar (& allowHTTP2 , "h2" , false , "Allow HTTP2" )
42- flag .UintVar (& ttl , "ttl" , 0 , "Time to Live in seconds (0 is infinite time)" )
43- flag .StringVar (& responseTables , "response-tables" , "" , "Comma separated list of database tables used to store response data" )
44- flag .BoolVar (& forceCreateTables , "force-create-tables" , false , "Force create response tables if not exists" )
45- flag .StringVar (& caCert , "ca-cert" , "" , "Path to CA Certificate file (required to HTTPS proxy)" )
46- flag .StringVar (& caCertKey , "ca-cert-key" , "" , "Path to CA Certificate Key file (required to HTTPS proxy)" )
47- flag .BoolVar (& readOnly , "ro" , false , "Read Only mode. Do not store new HTTP responses" )
48- flag .Parse ()
49-
50- if len (flag .Args ()) == 0 {
51- log .Fatalf ("Usage: %s <flags> [DatabasePath1] [DatabasePathN\n \n Example:\n \t %s example.db example2.db example3.db\n " , os .Args [0 ], os .Args [0 ])
51+ if * verbose {
52+ fmt .Printf ("Using options: port=%d db-params=%s, h2=%v, ttl=%d, response-tables=%v, force-create-tables=%v, ca-cert=%s, ca-cert-key=%s, read-only=%v\n " ,
53+ * port , * dbParams , * allowHTTP2 , * ttl , * responseTables , * forceCreateTables , * caCert , * caCertKey , * readOnly )
5254 }
5355
5456 dbs := make ([]* sql.DB , 0 )
@@ -57,14 +59,31 @@ func main() {
5759 tableList []string
5860 err error
5961 )
60- for _ , file := range flag .Args () {
61- var dsn string
62- if file == ":memory:" {
63- dsn = file + "?cache=shared"
64- } else {
65- dsn = fmt .Sprintf ("file:%s?%s" , file , dbParams )
62+
63+ dsnList := make ([]string , 0 )
64+ for _ , pattern := range fs .GetArgs () {
65+ if pattern == ":memory:" {
66+ dsn := pattern + "?cache=shared"
67+ dsnList = append (dsnList , dsn )
68+ continue
6669 }
70+ matches , err := filepath .Glob (pattern )
71+ if err != nil {
72+ log .Fatal (err )
73+ }
74+
75+ for _ , file := range matches {
76+ dsn := fmt .Sprintf ("file:%s?%s" , file , * dbParams )
77+ dsnList = append (dsnList , dsn )
78+ }
79+ if len (matches ) == 0 && ! strings .Contains (pattern , "*" ) {
80+ dsn := fmt .Sprintf ("file:%s?%s" , pattern , * dbParams )
81+ dsnList = append (dsnList , dsn )
82+ }
83+
84+ }
6785
86+ for _ , dsn := range dsnList {
6887 sqlDB , err := sql .Open ("sqlite3" , dsn )
6988 if err != nil {
7089 log .Fatalf ("open db error: %v" , err )
@@ -73,17 +92,17 @@ func main() {
7392
7493 dbs = append (dbs , sqlDB )
7594
76- if responseTables == "" {
95+ if responseTables == nil || len ( * responseTables ) == 0 {
7796 tableList , err = db .ResponseTables (sqlDB )
7897 if err != nil {
7998 log .Fatalf ("discovery response tables: %v" , err )
8099 }
81100 } else {
82- tableList = strings . Split ( responseTables , "," )
83- if forceCreateTables {
101+ tableList = * responseTables
102+ if * forceCreateTables {
84103 err := db .CreateResponseTables (sqlDB , tableList ... )
85104 if err != nil {
86- log .Fatalf ("force create tables: %v" , err )
105+ log .Fatalf ("force create tables on DB %q : %v" , dsn , err )
87106 }
88107 }
89108 }
@@ -102,12 +121,12 @@ func main() {
102121 defer repository .Close ()
103122
104123 proxy := goproxy .NewProxyHttpServer ()
105- proxy .Verbose = verbose
106- proxy .AllowHTTP2 = allowHTTP2
124+ proxy .Verbose = * verbose
125+ proxy .AllowHTTP2 = * allowHTTP2
107126
108- if caCert != "" && caCertKey != "" {
127+ if * caCert != "" && * caCertKey != "" {
109128 proxy .Logger .Printf ("INFO: Starting HTTP/HTTPS Proxy..." )
110- cert , err := parseCA ([]byte (caCert ), []byte (caCertKey ))
129+ cert , err := parseCA ([]byte (* caCert ), []byte (* caCertKey ))
111130 if err != nil {
112131 log .Fatal (err )
113132 }
@@ -122,20 +141,24 @@ func main() {
122141 }
123142
124143 proxy .OnRequest ().Do (& requestHandler {
125- querier : repository ,
144+ querier : repository ,
145+ verbose : * verbose ,
146+ ttl : * ttl ,
147+ readOnly : * readOnly ,
126148 })
127- if ! readOnly {
149+ if ! * readOnly {
128150 proxy .OnResponse ().Do (& responseHandler {
129- writer : repository ,
151+ writer : repository ,
152+ verbose : * verbose ,
130153 })
131154 }
132155
133- lis , err := net .Listen ("tcp" , fmt .Sprintf (":%d" , port ))
156+ lis , err := net .Listen ("tcp" , fmt .Sprintf (":%d" , * port ))
134157 if err != nil {
135158 log .Fatalf ("cannot open port %d: %v" , port , err )
136159 }
137160
138- proxy .Logger .Printf ("SQLite-HTTP-Proxy listening port=%d" , port )
161+ proxy .Logger .Printf ("SQLite-HTTP-Proxy listening port=%d" , * port )
139162 log .Fatal (http .Serve (lis , proxy ))
140163}
141164
0 commit comments