github.com/lonnblad/godog@v0.7.14-0.20200306004719-1b0cb3259847/_examples/db/api.go (about)

     1  package main
     2  
     3  import (
     4  	"database/sql"
     5  	"encoding/json"
     6  	"fmt"
     7  	"net/http"
     8  
     9  	_ "github.com/go-sql-driver/mysql"
    10  )
    11  
    12  type server struct {
    13  	db *sql.DB
    14  }
    15  
    16  type user struct {
    17  	ID       int64  `json:"-"`
    18  	Username string `json:"username"`
    19  	Email    string `json:"-"`
    20  }
    21  
    22  func (s *server) users(w http.ResponseWriter, r *http.Request) {
    23  	if r.Method != "GET" {
    24  		fail(w, "Method not allowed", http.StatusMethodNotAllowed)
    25  		return
    26  	}
    27  
    28  	var users []*user
    29  	rows, err := s.db.Query("SELECT id, email, username FROM users")
    30  	defer rows.Close()
    31  	switch err {
    32  	case nil:
    33  		for rows.Next() {
    34  			user := &user{}
    35  			if err := rows.Scan(&user.ID, &user.Email, &user.Username); err != nil {
    36  				fail(w, fmt.Sprintf("failed to scan an user: %s", err), http.StatusInternalServerError)
    37  				return
    38  			}
    39  			users = append(users, user)
    40  		}
    41  		if len(users) == 0 {
    42  			users = make([]*user, 0) // an empty array in this case
    43  		}
    44  	default:
    45  		fail(w, fmt.Sprintf("failed to fetch users: %s", err), http.StatusInternalServerError)
    46  		return
    47  	}
    48  
    49  	data := struct {
    50  		Users []*user `json:"users"`
    51  	}{Users: users}
    52  
    53  	ok(w, data)
    54  }
    55  
    56  func main() {
    57  	db, err := sql.Open("mysql", "root@/godog")
    58  	if err != nil {
    59  		panic(err)
    60  	}
    61  	s := &server{db: db}
    62  	http.HandleFunc("/users", s.users)
    63  	http.ListenAndServe(":8080", nil)
    64  }
    65  
    66  // fail writes a json response with error msg and status header
    67  func fail(w http.ResponseWriter, msg string, status int) {
    68  	w.Header().Set("Content-Type", "application/json")
    69  
    70  	data := struct {
    71  		Error string `json:"error"`
    72  	}{Error: msg}
    73  
    74  	resp, _ := json.Marshal(data)
    75  	w.WriteHeader(status)
    76  
    77  	fmt.Fprintf(w, string(resp))
    78  }
    79  
    80  // ok writes data to response with 200 status
    81  func ok(w http.ResponseWriter, data interface{}) {
    82  	w.Header().Set("Content-Type", "application/json")
    83  
    84  	if s, ok := data.(string); ok {
    85  		fmt.Fprintf(w, s)
    86  		return
    87  	}
    88  
    89  	resp, err := json.Marshal(data)
    90  	if err != nil {
    91  		w.WriteHeader(http.StatusInternalServerError)
    92  		fail(w, "oops something evil has happened", 500)
    93  		return
    94  	}
    95  
    96  	fmt.Fprintf(w, string(resp))
    97  }