4api.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*
  2. Available routes:
  3. /api/users OPTIONS Expose available actions
  4. /api/users GET Return user list, possibly filtered
  5. /api/users POST Create user
  6. /api/users/123 GET Return user 123 -> not listed in book
  7. /api/users/123 PUT Update user 123
  8. /api/users/123 DELETE Delete user 123
  9. */
  10. package main
  11. import (
  12. "database/sql"
  13. "encoding/json"
  14. "fmt"
  15. "log"
  16. "net/http"
  17. _ "github.com/go-sql-driver/mysql"
  18. "github.com/gorilla/mux"
  19. )
  20. var database *sql.DB
  21. type Users struct {
  22. Users []User `json:"users"`
  23. }
  24. type User struct {
  25. ID int `json:"id"`
  26. Name string `json:"username"`
  27. Email string `json:"mail"`
  28. First string `json:"first"`
  29. Last string `json:"last"`
  30. }
  31. /*
  32. UserCreate creates a new user and stores it.
  33. The SQL query is vulnerable to injection, so the route matching needs be safe.
  34. */
  35. func UserCreate(w http.ResponseWriter, r *http.Request) {
  36. NewUser := User{
  37. Name: r.FormValue("name"),
  38. Email: r.FormValue("mail"),
  39. First: r.FormValue("first"),
  40. Last: r.FormValue("last"),
  41. }
  42. output, err := json.MarshalIndent(NewUser, "", " ")
  43. fmt.Println(string(output))
  44. if err != nil {
  45. fmt.Println("Something went wrong!")
  46. }
  47. sql := "INSERT INTO user SET user_nickname='" + NewUser.Name +
  48. "', user_first='" + NewUser.First +
  49. "', user_last='" + NewUser.Last +
  50. "', user_email='" + NewUser.Email + "'"
  51. q, err := database.Exec(sql)
  52. if err != nil {
  53. fmt.Println(err)
  54. }
  55. fmt.Println(q)
  56. }
  57. func UsersRetrieve(w http.ResponseWriter, r *http.Request) {
  58. w.Header().Set("Pragma", "no-cache")
  59. rows, err := database.Query(`
  60. SELECT u.user_id, u.user_name, u.user_email, u.user_first, u.user_last
  61. FROM users u
  62. LIMIT 10
  63. `)
  64. if err != nil {
  65. fmt.Fprintln(w, "Something went wrong!")
  66. log.Fatal(err)
  67. }
  68. Response := Users{}
  69. for rows.Next() {
  70. user := User{}
  71. rows.Scan(&user.ID, &user.Name, &user.Email, &user.First, &user.Last)
  72. Response.Users = append(Response.Users, user)
  73. }
  74. output, _ := json.MarshalIndent(Response, "", " ")
  75. fmt.Fprintln(w, string(output))
  76. }
  77. type API struct {
  78. Message string `json:"message"`
  79. }
  80. func UserMethods(w http.ResponseWriter, r *http.Request) {
  81. }
  82. func UserReplace(w http.ResponseWriter, r *http.Request) {
  83. }
  84. func UserDelete(w http.ResponseWriter, r *http.Request) {
  85. }
  86. func UserRetrieve(w http.ResponseWriter, r *http.Request) {
  87. w.Header().Set("Pragma", "no-cache")
  88. vars := mux.Vars(r)
  89. id := vars["id"]
  90. user := User{}
  91. var result API
  92. sqlQuery := `
  93. SELECT u.user_id, u.user_nickname, u.user_first, u.user_last, u.user_email
  94. FROM user u
  95. WHERE u.user_id = ?
  96. `
  97. stmt, err := database.Prepare(sqlQuery)
  98. if err != nil {
  99. log.Fatal(err.Error())
  100. }
  101. row := stmt.QueryRow(id)
  102. scanErr := row.Scan(&user.ID, &user.Name, &user.First, &user.Last, &user.Email)
  103. switch {
  104. case scanErr == sql.ErrNoRows:
  105. // FIXME XSS
  106. result = API{Message: fmt.Sprintf("No such user: %s", id)}
  107. json, err := json.MarshalIndent(result, "", " ")
  108. if err != nil {
  109. log.Fatal(err.Error())
  110. }
  111. w.Write(json)
  112. case err != nil:
  113. // FIXME XSS
  114. result = API{Message: fmt.Sprintf("Error reading user: %s", id)}
  115. json, errIndent := json.MarshalIndent(result, "", " ")
  116. if errIndent != nil {
  117. log.Fatal(errIndent.Error())
  118. }
  119. w.Write(json)
  120. log.Fatal(err.Error())
  121. case err == nil:
  122. json, errIndent := json.MarshalIndent(user, "", " ")
  123. if errIndent != nil {
  124. log.Fatal(errIndent.Error())
  125. }
  126. w.Write(json)
  127. }
  128. }
  129. func main() {
  130. var err error
  131. db, err := sql.Open("mysql", "goroot:gopass@/goweb_social_network")
  132. if err != nil {
  133. log.Fatal(err.Error())
  134. }
  135. database = db
  136. routes := mux.NewRouter()
  137. routes.HandleFunc("/api/users", UserCreate).Methods("POST")
  138. routes.HandleFunc(`/api/users`, UsersRetrieve).Methods("GET")
  139. // Not yet implemented.
  140. routes.HandleFunc(`/api/users`, UserMethods).Methods("OPTIONS")
  141. routes.HandleFunc(`/api/users/{id:[\d]+}`, UserRetrieve).Methods("GET")
  142. routes.HandleFunc(`/api/users/{id:[\d]+}`, UserReplace).Methods("PUT")
  143. routes.HandleFunc(`/api/users/{id:[\d]+}`, UserDelete).Methods("DELETE")
  144. // --------------------
  145. http.Handle("/", routes)
  146. http.ListenAndServe(":8080", nil)
  147. }