Skip to content
This repository was archived by the owner on Mar 4, 2025. It is now read-only.

Commit d7cca79

Browse files
committed
api: Add diff handler to v1 API
This adds a /v1/diff handler which calls the com.Diff function and returns its results in JSON format. While this might be useful later its main purpose at the moment is to expose the com.Diff function in an easy to call way for testing purposes. Because of this the API handler is not added to the help page yet.
1 parent e289ee4 commit d7cca79

File tree

2 files changed

+108
-0
lines changed

2 files changed

+108
-0
lines changed

api/handlers.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"log"
77
"net/http"
8+
"net/url"
89

910
sqlite "github.com/gwenn/gosqlite"
1011
com "github.com/sqlitebrowser/dbhub.io/common"
@@ -249,3 +250,109 @@ func viewsHandler(w http.ResponseWriter, r *http.Request) {
249250
}
250251
fmt.Fprintf(w, string(jsonData))
251252
}
253+
254+
// diffHandler generates a diff between two databases or two versions of a database
255+
// This can be run from the command line using curl, like this:
256+
// $ curl -F apikey="YOUR_API_KEY_HERE" -F dbowner_a="justinclift" -F dbname_a="Join Testing.sqlite" -F commit_a="ea12..." -F commit_b="5a7c..." https://api.dbhub.io/v1/diff
257+
// * "apikey" is one of your API keys. These can be generated from your Settings page once logged in
258+
// * "dbowner_a" is the owner of the first database being diffed
259+
// * "dbname_a" is the name of the first database being diffed
260+
// * "dbowner_b" is the owner of the second database being diffed (optional, if not provided same as first owner)
261+
// * "dbname_b" is the name of the second database being diffed (optional, if not provided same as first name)
262+
// * "commit_a" is the first commit for diffing
263+
// * "commit_b" is the second commit for diffing
264+
func diffHandler(w http.ResponseWriter, r *http.Request) {
265+
loggedInUser, err := checkAuth(w, r)
266+
if err != nil {
267+
jsonErr(w, err.Error(), http.StatusUnauthorized)
268+
return
269+
}
270+
271+
// Retrieve owner, name, and commit ids
272+
oa := r.PostFormValue("dbowner_a")
273+
na := r.PostFormValue("dbname_a")
274+
ca := r.PostFormValue("commit_a")
275+
ob := r.PostFormValue("dbowner_a")
276+
nb := r.PostFormValue("dbname_b")
277+
cb := r.PostFormValue("commit_b")
278+
279+
// If no primary database owner and name are given or if no commit ids are given, return
280+
if oa == "" || na == "" || ca == "" || cb == "" {
281+
jsonErr(w, err.Error(), http.StatusBadRequest)
282+
return
283+
}
284+
285+
// If no secondary database owner and name are provided, use the ones of the first database
286+
if ob == "" || nb == "" {
287+
ob = oa
288+
nb = na
289+
}
290+
291+
// Unescape, then validate the owner and database names and commit ids
292+
dbOwnerA, err := url.QueryUnescape(oa)
293+
if err != nil {
294+
jsonErr(w, err.Error(), http.StatusBadRequest)
295+
return
296+
}
297+
dbOwnerB, err := url.QueryUnescape(ob)
298+
if err != nil {
299+
jsonErr(w, err.Error(), http.StatusBadRequest)
300+
return
301+
}
302+
dbNameA, err := url.QueryUnescape(na)
303+
if err != nil {
304+
jsonErr(w, err.Error(), http.StatusBadRequest)
305+
return
306+
}
307+
dbNameB, err := url.QueryUnescape(nb)
308+
if err != nil {
309+
jsonErr(w, err.Error(), http.StatusBadRequest)
310+
return
311+
}
312+
err = com.ValidateUser(dbOwnerA)
313+
if err != nil {
314+
jsonErr(w, err.Error(), http.StatusBadRequest)
315+
return
316+
}
317+
err = com.ValidateUser(dbOwnerB)
318+
if err != nil {
319+
jsonErr(w, err.Error(), http.StatusBadRequest)
320+
return
321+
}
322+
err = com.ValidateDB(dbNameA)
323+
if err != nil {
324+
jsonErr(w, err.Error(), http.StatusBadRequest)
325+
return
326+
}
327+
err = com.ValidateDB(dbNameB)
328+
if err != nil {
329+
jsonErr(w, err.Error(), http.StatusBadRequest)
330+
return
331+
}
332+
err = com.ValidateCommitID(ca)
333+
if err != nil {
334+
jsonErr(w, err.Error(), http.StatusBadRequest)
335+
return
336+
}
337+
err = com.ValidateCommitID(cb)
338+
if err != nil {
339+
jsonErr(w, err.Error(), http.StatusBadRequest)
340+
return
341+
}
342+
343+
// Perform diff
344+
diffs, err := com.Diff(dbOwnerA, "/", dbNameA, ca, dbOwnerB, "/", dbNameB, cb, loggedInUser)
345+
if err != nil {
346+
jsonErr(w, err.Error(), http.StatusInternalServerError)
347+
return
348+
}
349+
350+
// Return the results
351+
jsonData, err := json.Marshal(diffs)
352+
if err != nil {
353+
log.Printf("Error when JSON marshalling returned data in diffHandler(): %v\n", err)
354+
jsonErr(w, err.Error(), http.StatusInternalServerError)
355+
return
356+
}
357+
fmt.Fprintf(w, string(jsonData))
358+
}

api/main.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ func main() {
8080
http.Handle("/v1/query", gz.GzipHandler(handleWrapper(queryHandler)))
8181
http.Handle("/v1/tables", gz.GzipHandler(handleWrapper(tablesHandler)))
8282
http.Handle("/v1/views", gz.GzipHandler(handleWrapper(viewsHandler)))
83+
http.Handle("/v1/diff", gz.GzipHandler(handleWrapper(diffHandler)))
8384

8485
// Generate the formatted server string
8586
server = fmt.Sprintf("https://%s", com.Conf.Api.ServerName)

0 commit comments

Comments
 (0)