@@ -11,10 +11,13 @@ import (
11
11
com "github.com/sqlitebrowser/dbhub.io/common"
12
12
)
13
13
14
- // collectInfo is an internal function which checks the authentication of incoming requests, extracts
15
- // the database owner, name, & commitID, then fetches the Minio bucket and ID for the database file.
14
+ // collectInfo is an internal function which:
15
+ // 1. Authenticates incoming requests
16
+ // 2. Extracts the database owner, name, & commitID from the request
17
+ // 3. Fetches the database from Minio (with appropriate permission checks)
18
+ // 4. Opens the database, returning the connection handle
16
19
// This function exists purely because this code is commonly to most of the handlers
17
- func collectInfo (w http.ResponseWriter , r * http.Request ) (bucket , id string , err error , httpStatus int ) {
20
+ func collectInfo (w http.ResponseWriter , r * http.Request ) (sdb * sqlite. Conn , err error , httpStatus int ) {
18
21
var loggedInUser string
19
22
loggedInUser , err = checkAuth (w , r )
20
23
if err != nil {
@@ -32,6 +35,7 @@ func collectInfo(w http.ResponseWriter, r *http.Request) (bucket, id string, err
32
35
dbFolder := "/"
33
36
34
37
// Check if the user has access to the requested database
38
+ var bucket , id string
35
39
bucket , id , _ , err = com .MinioLocation (dbOwner , dbFolder , dbName , commitID , loggedInUser )
36
40
if err != nil {
37
41
httpStatus = http .StatusInternalServerError
@@ -46,9 +50,61 @@ func collectInfo(w http.ResponseWriter, r *http.Request) (bucket, id string, err
46
50
httpStatus = http .StatusNotFound
47
51
return
48
52
}
53
+
54
+ // Retrieve database file from Minio, using locally cached version if it's already there
55
+ newDB , err := com .RetrieveDatabaseFile (bucket , id )
56
+ if err != nil {
57
+ httpStatus = http .StatusNotFound
58
+ return
59
+ }
60
+
61
+ // Open the SQLite database in read only mode
62
+ sdb , err = sqlite .Open (newDB , sqlite .OpenReadOnly )
63
+ if err != nil {
64
+ log .Printf ("Couldn't open database in viewsHandler(): %s" , err )
65
+ httpStatus = http .StatusInternalServerError
66
+ return
67
+ }
68
+ if err = sdb .EnableExtendedResultCodes (true ); err != nil {
69
+ log .Printf ("Couldn't enable extended result codes in viewsHandler(): %v\n " , err .Error ())
70
+ httpStatus = http .StatusInternalServerError
71
+ return
72
+ }
49
73
return
50
74
}
51
75
76
+ // indexesHandler returns the list of indexes present in a SQLite database
77
+ // This can be run from the command line using curl, like this:
78
+ // $ curl -F apikey="YOUR_API_KEY_HERE" -F dbowner="justinclift" -F dbname="Join Testing.sqlite" https://api.dbhub.io/v1/indexes
79
+ // * "apikey" is one of your API keys. These can be generated from your Settings page once logged in
80
+ // * "dbowner" is the owner of the database being queried
81
+ // * "dbname" is the name of the database being queried
82
+ func indexesHandler (w http.ResponseWriter , r * http.Request ) {
83
+ // Do auth check, grab request info, open the database
84
+ sdb , err , httpStatus := collectInfo (w , r )
85
+ if err != nil {
86
+ jsonErr (w , err .Error (), httpStatus )
87
+ return
88
+ }
89
+ defer sdb .Close ()
90
+
91
+ // Retrieve the list of indexes
92
+ idx , err := sdb .Indexes ("" )
93
+ if err != nil {
94
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
95
+ return
96
+ }
97
+
98
+ // Return the results
99
+ jsonData , err := json .Marshal (idx )
100
+ if err != nil {
101
+ log .Printf ("Error when JSON marshalling returned data in indexesHandler(): %v\n " , err )
102
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
103
+ return
104
+ }
105
+ fmt .Fprintf (w , string (jsonData ))
106
+ }
107
+
52
108
// queryHandler executes a SQL query on a SQLite database, returning the results to the caller
53
109
// This can be run from the command line using curl, like this:
54
110
// $ curl -kD headers.out -F apikey="YOUR_API_KEY_HERE" -F dbowner="justinclift" -F dbname="Join Testing.sqlite" \
@@ -61,14 +117,14 @@ func collectInfo(w http.ResponseWriter, r *http.Request) (bucket, id string, err
61
117
func queryHandler (w http.ResponseWriter , r * http.Request ) {
62
118
loggedInUser , err := checkAuth (w , r )
63
119
if err != nil {
64
- w . WriteHeader ( http .StatusUnauthorized )
120
+ jsonErr ( w , err . Error (), http .StatusUnauthorized )
65
121
return
66
122
}
67
123
68
124
// Extract the database owner name, database name, and (optional) commit ID for the database from the request
69
125
dbOwner , dbName , commitID , err := com .GetFormODC (r )
70
126
if err != nil {
71
- w . WriteHeader ( http .StatusInternalServerError )
127
+ jsonErr ( w , err . Error (), http .StatusInternalServerError )
72
128
return
73
129
}
74
130
dbFolder := "/"
@@ -77,39 +133,35 @@ func queryHandler(w http.ResponseWriter, r *http.Request) {
77
133
rawInput := r .FormValue ("sql" )
78
134
decodedStr , err := com .CheckUnicode (rawInput )
79
135
if err != nil {
80
- w .WriteHeader (http .StatusBadRequest )
81
- fmt .Fprint (w , err )
136
+ jsonErr (w , err .Error (), http .StatusBadRequest )
82
137
return
83
138
}
84
139
85
140
// Check if the requested database exists
86
141
exists , err := com .CheckDBExists (loggedInUser , dbOwner , dbFolder , dbName )
87
142
if err != nil {
88
- w .WriteHeader (http .StatusInternalServerError )
89
- fmt .Fprint (w , err )
143
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
90
144
return
91
145
}
92
146
if ! exists {
93
- w . WriteHeader ( http . StatusNotFound )
94
- fmt . Fprintf ( w , "Database '%s%s%s' doesn't exist" , dbOwner , dbFolder , dbName )
147
+ jsonErr ( w , fmt . Sprintf ( "Database '%s%s%s' doesn't exist" , dbOwner , dbFolder , dbName ),
148
+ http . StatusNotFound )
95
149
return
96
150
}
97
151
98
152
// Run the query
99
153
var data com.SQLiteRecordSet
100
154
data , err = com .SQLiteRunQueryDefensive (w , r , com .API , dbOwner , dbFolder , dbName , commitID , loggedInUser , decodedStr )
101
155
if err != nil {
102
- w .WriteHeader (http .StatusInternalServerError )
103
- fmt .Fprint (w , err )
156
+ jsonErr (w , err .Error (), http .StatusInternalServerError )
104
157
return
105
158
}
106
159
107
160
// Return the results
108
161
jsonData , err := json .Marshal (data .Records )
109
162
if err != nil {
110
- errMsg := fmt .Sprintf ("Error when JSON marshalling the returned data: %v\n " , err )
111
- log .Print (errMsg )
112
- http .Error (w , errMsg , http .StatusBadRequest )
163
+ jsonErr (w , fmt .Sprintf ("Error when JSON marshalling the returned data: %v\n " , err ),
164
+ http .StatusBadRequest )
113
165
return
114
166
}
115
167
fmt .Fprintf (w , string (jsonData ))
@@ -148,46 +200,23 @@ func rootHandler(w http.ResponseWriter, r *http.Request) {
148
200
// * "dbowner" is the owner of the database being queried
149
201
// * "dbname" is the name of the database being queried
150
202
func tablesHandler (w http.ResponseWriter , r * http.Request ) {
151
- // Do auth check, database existence check, and grab it's Minio bucket and ID
152
- bucket , id , err , httpStatus := collectInfo (w , r )
203
+ // Do auth check, grab request info, open the database
204
+ sdb , err , httpStatus := collectInfo (w , r )
153
205
if err != nil {
154
206
jsonErr (w , err .Error (), httpStatus )
155
207
return
156
208
}
157
-
158
- // Retrieve database file from Minio, using locally cached version if it's already there
159
- newDB , err := com .RetrieveDatabaseFile (bucket , id )
160
- if err != nil {
161
- jsonErr (w , err .Error (), http .StatusNotFound )
162
- return
163
- }
164
-
165
- // Open the SQLite database in read only mode
166
- var sdb * sqlite.Conn
167
- sdb , err = sqlite .Open (newDB , sqlite .OpenReadOnly )
168
- if err != nil {
169
- log .Printf ("Couldn't open database in tablesHandler(): %s" , err )
170
- jsonErr (w , err .Error (), http .StatusInternalServerError )
171
- return
172
- }
173
- if err = sdb .EnableExtendedResultCodes (true ); err != nil {
174
- log .Printf ("Couldn't enable extended result codes in tablesHandler(): %v\n " , err .Error ())
175
- jsonErr (w , err .Error (), http .StatusInternalServerError )
176
- return
177
- }
209
+ defer sdb .Close ()
178
210
179
211
// Retrieve the list of tables
180
- var returnData struct {
181
- Tables []string `json:"tables"`
182
- }
183
- returnData .Tables , err = com .Tables (sdb )
212
+ tables , err := com .Tables (sdb )
184
213
if err != nil {
185
214
jsonErr (w , err .Error (), http .StatusInternalServerError )
186
215
return
187
216
}
188
217
189
218
// Return the results
190
- jsonData , err := json .Marshal (returnData . Tables )
219
+ jsonData , err := json .Marshal (tables )
191
220
if err != nil {
192
221
log .Printf ("Error when JSON marshalling returned data in tablesHandler(): %v\n " , err )
193
222
jsonErr (w , err .Error (), http .StatusInternalServerError )
@@ -203,46 +232,23 @@ func tablesHandler(w http.ResponseWriter, r *http.Request) {
203
232
// * "dbowner" is the owner of the database being queried
204
233
// * "dbname" is the name of the database being queried
205
234
func viewsHandler (w http.ResponseWriter , r * http.Request ) {
206
- // Do auth check, database existence check, and grab it's Minio bucket and ID
207
- bucket , id , err , httpStatus := collectInfo (w , r )
235
+ // Do auth check, grab request info, open the database
236
+ sdb , err , httpStatus := collectInfo (w , r )
208
237
if err != nil {
209
238
jsonErr (w , err .Error (), httpStatus )
210
239
return
211
240
}
212
-
213
- // Retrieve database file from Minio, using locally cached version if it's already there
214
- newDB , err := com .RetrieveDatabaseFile (bucket , id )
215
- if err != nil {
216
- jsonErr (w , err .Error (), http .StatusNotFound )
217
- return
218
- }
219
-
220
- // Open the SQLite database in read only mode
221
- var sdb * sqlite.Conn
222
- sdb , err = sqlite .Open (newDB , sqlite .OpenReadOnly )
223
- if err != nil {
224
- log .Printf ("Couldn't open database in viewsHandler(): %s" , err )
225
- jsonErr (w , err .Error (), http .StatusInternalServerError )
226
- return
227
- }
228
- if err = sdb .EnableExtendedResultCodes (true ); err != nil {
229
- log .Printf ("Couldn't enable extended result codes in viewsHandler(): %v\n " , err .Error ())
230
- jsonErr (w , err .Error (), http .StatusInternalServerError )
231
- return
232
- }
241
+ defer sdb .Close ()
233
242
234
243
// Retrieve the list of views
235
- var returnData struct {
236
- Views []string `json:"views"`
237
- }
238
- returnData .Views , err = com .Views (sdb )
244
+ views , err := com .Views (sdb )
239
245
if err != nil {
240
246
jsonErr (w , err .Error (), http .StatusInternalServerError )
241
247
return
242
248
}
243
249
244
250
// Return the results
245
- jsonData , err := json .Marshal (returnData . Views )
251
+ jsonData , err := json .Marshal (views )
246
252
if err != nil {
247
253
log .Printf ("Error when JSON marshalling returned data in viewsHandler(): %v\n " , err )
248
254
jsonErr (w , err .Error (), http .StatusInternalServerError )
0 commit comments