READ (SELECT/GET)
The READ part of REST API is rather simple. Fetch one row, filtered rows or all rows. The challenge is to make it dynamic.
1. HTLM call REST path
Somewhere on a page you must trigger the call to get the data. One way is to add a path to a button
<button onclick="api3get('tsk/all')">Call Javascript</button>
2. Do an AJAX Request with retuning data
The AJAX Request accepts dynamic call (+path) and writes back to the HTML page target (id="data")
function api3get(path) { var url = "https://api3.go4webdev.org/"+path; var xhr = new XMLHttpRequest(); xhr.open("GET", url); xhr.setRequestHeader("Accept", "application/json"); xhr.onload = function() { if (xhr.readyState === 4) { document.getElementById("data").innerHTML = this.responseText } }; xhr.send(); }
3+4. Lookup and get SQL Query from the REST call
Instead of storing each Query in the API, the query is stored in a database (almost similar to the Postgresql view function) fetched for each request. This means easier to maintain and more generic API (fewer endpoints)
The query is fetced with an id "tsk_all" from the REST call https://api3.go4webdev.org/tsk/all
func Getquery(path string) string { // get query from lookup db var query string err := db.QueryRow("SELECT sql_query FROM sqls WHERE sql_id=$1", path).Scan(&query) if err != nil { path = "" } fmt.Println(query) return query }
The lookup Query look like this with a parameter that is filled with JSON from the form in the next step
SELECT * FROM tsk;
7+8+9. Execute the SQL Query and return data
The READ endpoint in the Go API contains both executing the query as well as return data back to the client.
package main import ( "encoding/json" "fmt" "net/http" "net/url" ) func Get(w http.ResponseWriter, r *http.Request) { scope, action, val := getpath(r) var data interface{} val, _ = url.QueryUnescape(val) switch action { case "id": query := Getquery(scope + "_" + action) data = getid(query, val) fmt.Println(query) case "all": query := Getquery(scope + "_" + action) data = getall(query) } json.NewEncoder(w).Encode(data) //write back to client } // return a single row func getid(query string, val string) interface{} { if len(query) > 0 { row := make(map[string]interface{}) db.QueryRowx(query, val).MapScan(row) return (row) } return nil } // query to return a list func getall(query string) interface{} { fmt.Println(query) if len(query) > 0 { var list []map[string]interface{} rows, err := db.Queryx(query) if err != nil { log("no records") } defer rows.Close() for rows.Next() { row := make(map[string]interface{}) err = rows.MapScan(row) if err != nil { log(err.Error()) } list = append(list, row) } rows.Close() if len(list) == 0 { return ("norec") } return list } return nil }
The data appears in the tag id="data"
<div id="data">The result</div>
All steps above put together: