Last active
February 6, 2016 18:24
-
-
Save Savchukv/445d3b6c1a4776188947 to your computer and use it in GitHub Desktop.
Server
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"database/sql" | |
"gopkg.in/gorp.v1" | |
"log" | |
"net/url" | |
//"flag" | |
"strconv" | |
"time" | |
"fmt" | |
"net/http" | |
"github.com/gorilla/websocket" | |
"github.com/gin-gonic/gin" | |
//"golang.org/x/net/websocket" | |
"github.com/dgrijalva/jwt-go" | |
_ "github.com/go-sql-driver/mysql" | |
) | |
var database *sql.DB | |
type User struct { | |
Id int64 `db:"id" json:"id"` | |
Email string `db:"email" json:"email"` | |
Username string `db:"username" json:"username"` | |
Password string `db:"password" json:"password"` | |
Sex int64 `db:"sex" json:"sex"` | |
Age int64 `db:"age" json:"age"` | |
} | |
type Login struct { | |
Email string `json: "email" binding: "required"` | |
Password string `json: "password" binding: "required"` | |
} | |
type Check struct { | |
Email string `json: "email" binding: "required"` | |
} | |
var ( | |
validUser = User{Id: 1, Email: "Vas", Username: "Sav"} | |
mySigningKey = "USEHERE" | |
) | |
var dbmap = initDb() | |
func initDb() *gorp.DbMap { | |
db, err := sql.Open("mysql", "root:root123456@/myapi") | |
checkErr(err, "sql.Open failed") | |
dbmap := &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}} | |
dbmap.AddTableWithName(User{}, "User").SetKeys(true, "Id") | |
err = dbmap.CreateTablesIfNotExists() | |
checkErr(err, "Create tables failed") | |
return dbmap | |
} | |
func checkErr(err error, msg string) { | |
if err != nil { | |
log.Fatalln(msg, err) | |
} | |
} | |
//var myconn string | |
//websocket | |
var connections map[*websocket.Conn]bool | |
var destinations map[string]*websocket.Conn | |
func wsHandler(w http.ResponseWriter, r *http.Request) { | |
// Taken from gorilla's website | |
conn, err := websocket.Upgrade(w, r, nil, 1024, 1024) | |
if _, ok := err.(websocket.HandshakeError); ok { | |
http.Error(w, "Not a websocket handshake", 400) | |
return | |
} else if err != nil { | |
log.Println(err) | |
return | |
} | |
log.Println("Succesfully upgraded connection") | |
connections[conn] = true | |
for { | |
// Blocks until a message is read | |
_, msg, err := conn.ReadMessage() | |
if err != nil { | |
delete(connections, conn) | |
conn.Close() | |
return | |
//log.Println(err) | |
} | |
log.Println(string(msg)) | |
sendAll(msg,conn) | |
} | |
} | |
func sendAll(msg []byte, myconn *websocket.Conn) { | |
for conn := range connections { | |
if myconn != conn { | |
if err := conn.WriteMessage(websocket.TextMessage, msg); err != nil { | |
delete(connections, conn) | |
conn.Close() | |
} | |
} | |
} | |
} | |
func wsHandlerChat(w http.ResponseWriter, r *http.Request) { | |
// Taken from gorilla's website | |
query := r.URL.Query() | |
// ws?origin=A&destination=B для юзера A | |
// ws?origin=B&destination=A для юзера B | |
originID := query.Get("origin") | |
destinationID := query.Get("destination") | |
conn, err := websocket.Upgrade(w, r, nil, 1024, 1024) | |
if _, ok := err.(websocket.HandshakeError); ok { | |
http.Error(w, "Not a websocket handshake", 400) | |
return | |
} else if err != nil { | |
log.Println(err) | |
return | |
} | |
destinations[originID] = conn | |
log.Println("Succesfully upgraded connection") | |
connections[conn] = true | |
for { | |
// Blocks until a message is read | |
_, msg, err := conn.ReadMessage() | |
if err != nil { | |
delete(destinations, originID) | |
delete(connections, conn) | |
conn.Close() | |
return | |
//log.Println(err) | |
} | |
log.Println(string(msg)) | |
connDestination, ok := destinations[destinationID] | |
if !ok { | |
log.Println("destination", destinationID, "not found") | |
continue | |
} | |
if err := connDestination.WriteMessage(websocket.TextMessage, msg); err != nil { | |
delete(connections, connDestination) | |
delete(destinations, destinationID) | |
conn.Close() | |
} | |
} | |
} | |
//end websocket | |
func main() { | |
r := gin.Default() | |
r.GET("/ws", func(c *gin.Context) { | |
wsHandler(c.Writer, c.Request) | |
}) | |
r.GET("/ws/chat", func(c *gin.Context) { | |
wsHandlerChat(c.Writer, c.Request) | |
}) | |
connections = make(map[*websocket.Conn]bool) | |
destinations = make(map[string]*websocket.Conn) | |
v1 := r.Group("api/v1") | |
{ | |
v1.GET("/users", GetUsers) | |
v1.GET("/users/:id", GetUser) | |
v1.GET("/chat/:origin/:destination/:destination/:origin", GetChat) | |
//v1.GET("/users/email", GetPassword) | |
v1.POST("/users", PostUser) | |
v1.PUT("/users/:id", UpdateUser) | |
v1.DELETE("/users/:id", DeleteUser) | |
} | |
r.LoadHTMLGlob("templates/*") | |
r.GET("/user", func(c *gin.Context) { | |
c.HTML(http.StatusOK, "user.html", gin.H{ | |
"title": "Main website", | |
}) | |
}) | |
r.GET("/userget", func(c *gin.Context) { | |
c.HTML(http.StatusOK, "userget.html", gin.H{ | |
"title": "Main website", | |
}) | |
}) | |
r.GET("/usergetid", func(c *gin.Context) { | |
c.HTML(http.StatusOK, "usergetid.html", gin.H{ | |
"title": "Main website", | |
}) | |
}) | |
r.GET("/deleteuser", func(c *gin.Context) { | |
c.HTML(http.StatusOK, "deleteuser.html", gin.H{ | |
"title": "Main website", | |
}) | |
}) | |
r.GET("/updateuser", func(c *gin.Context) { | |
c.HTML(http.StatusOK, "updateuser.html", gin.H{ | |
"title": "Main website", | |
}) | |
}) | |
//func to return fogot password | |
r.Use(func(c *gin.Context) { | |
// Run this on all requests | |
// Should be moved to a proper middleware | |
c.Writer.Header().Set("Access-Control-Allow-Origin", "*") | |
c.Writer.Header().Set("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, Authorization") | |
c.Next() | |
}) | |
r.OPTIONS("/*cors", func(c *gin.Context) { | |
// Empty 200 response | |
}) | |
r.POST("/users/token", func(c *gin.Context) { | |
var login Login | |
val := c.Bind(&login) | |
dbb, err:= sql.Open("mysql", "root:root123456@/myapi") | |
if err != nil { | |
} | |
database = dbb | |
var email string | |
var password string | |
sql:= "Select email,password from User where email='" + login.Email + "'" | |
q:= database.QueryRow(sql).Scan(&email,&password) | |
if q != nil { | |
//log.Fatal(q) | |
} | |
fmt.Println(email) | |
fmt.Println(password) | |
if val!=nil { | |
c.JSON(200, gin.H{"code": 401, "msg": "Both name & password are required"}) | |
return | |
} | |
if login.Email == email && login.Password == password { | |
// if login.Firstname == dbmap.Select("Select firstname from User where id=1") { | |
token := jwt.New(jwt.SigningMethodHS256) | |
// Headers | |
token.Header["alg"] = "HS256" | |
token.Header["typ"] = "JWT" | |
// Claims | |
token.Claims["name"] = login.Email | |
token.Claims["mail"] = login.Password | |
token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix() | |
tokenString, err := token.SignedString([]byte(mySigningKey)) | |
if err != nil { | |
c.JSON(200, gin.H{"code": 500, "msg": "Server error!"}) | |
return | |
} | |
c.JSON(200, gin.H{"code": 200, "msg": "OK", "jwt": tokenString}) | |
} else { | |
c.JSON(200, gin.H{"code": 400, "msg": "Error username or password!"}) | |
} | |
}) | |
r.POST("/users/balance", func(c *gin.Context) { | |
token, err := jwt.ParseFromRequest(c.Request, func(token *jwt.Token) (interface{}, error) { | |
b := ([]byte(mySigningKey)) | |
return b, nil | |
}) | |
fmt.Println(err) | |
if err != nil { | |
c.JSON(200, gin.H{"code": 403, "msg": err.Error()}) | |
} else { | |
if token.Valid { | |
token.Claims["balance"] = 49 | |
tokenString, err := token.SignedString([]byte(mySigningKey)) | |
if err != nil { | |
c.JSON(200, gin.H{"code": 500, "msg": "Server error!"}) | |
return | |
} | |
c.JSON(200, gin.H{"code": 200, "msg": "OK", "jwt": tokenString}) | |
} else { | |
c.JSON(200, gin.H{"code": 401, "msg": "Sorry, you are not validate"}) | |
} | |
} | |
}) | |
//check | |
r.POST("/users/email", func(c *gin.Context) { | |
var check Check | |
val := c.Bind(&check) | |
dbb, err:= sql.Open("mysql", "root:root123456@/myapi") | |
if err != nil { | |
} | |
database = dbb | |
var email string | |
var password string | |
sql:= "Select email,password from User where email='" + check.Email + "'" | |
q:= database.QueryRow(sql).Scan(&email,&password) | |
if q != nil { | |
// log.Fatal(q) | |
} | |
fmt.Println(email) | |
fmt.Println(password) | |
if val!=nil { | |
// c.JSON(200, gin.H{"code": 401, "msg": "Both name & password are required"}) | |
//return | |
} | |
if check.Email == email { | |
//if 1==1 { | |
c.JSON(200, gin.H{"code": 200, "msg": "OK", "Your Password": password}) | |
} else { | |
c.JSON(200, gin.H{"code": 400, "msg": "Error Mail!"}) | |
} | |
}) | |
r.Run(":8080") | |
} | |
func GetUsers(c *gin.Context) { | |
var users []User | |
_, err := dbmap.Select(&users, "SELECT * FROM User;") | |
if err == nil { | |
c.JSON(200, users) | |
} else { | |
c.JSON(404, gin.H{"error": "no user(s) into the table"}) | |
} | |
// curl -i http://localhost:8080/api/v1/users | |
} | |
func GetUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=? LIMIT 1;", id) | |
if err == nil { | |
user_id, _ := strconv.ParseInt(id, 0, 64) | |
content := &User{ | |
Id: user_id, | |
Email: user.Email, | |
Username: user.Username, | |
Password: user.Password, | |
Sex: user.Sex, | |
Age: user.Age, | |
} | |
c.JSON(200, content) | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i http://localhost:8080/api/v1/users/1 | |
} | |
func GetChat(c *gin.Context) { | |
originID := c.Params.ByName("origin") | |
destinationID := c.Params.ByName("destination") | |
wsURL := new(url.URL) | |
query := wsURL.Query() | |
query.Add("origin", originID) | |
query.Add("destination", destinationID) | |
wsURL.Path = "/ws/chat" | |
wsURL.RawQuery = query.Encode() | |
c.JSON(200, gin.H{"websocket_url": wsURL.String()}) | |
// curl -i http://localhost:8080/api/v1/chat/1/2 | |
} | |
func PostUser(c *gin.Context) { | |
var user User | |
c.Bind(&user) | |
log.Println(user) | |
if user.Email != "" && user.Username != "" { | |
if insert, _ := dbmap.Exec(`INSERT INTO User (email, username, password, sex, age) VALUES (?, ?, ?, ?, ?)`, user.Email, user.Username, user.Password, user.Sex, user.Age); insert != nil { | |
user_id, err := insert.LastInsertId() | |
if err == nil { | |
content := &User{ | |
Id: user_id, | |
Email: user.Email, | |
Username: user.Username, | |
Password: user.Password, | |
Sex: user.Sex, | |
Age: user.Age, | |
} | |
c.JSON(201, content) | |
} else { | |
checkErr(err, "Insert failed") | |
} | |
} | |
} else { | |
c.JSON(400, gin.H{"error": "fields are empty"}) | |
} | |
// curl -i -X POST -H "Content-Type: application/json" -d "{ \"firstname\": \"Thea\", \"lastname\": \"Queen\" }" http://localhost:8080/api/v1/users | |
} | |
func UpdateUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=?;", id) | |
if err == nil { | |
var json User | |
c.Bind(&json) | |
user_id, _ := strconv.ParseInt(id, 0, 64) | |
user := User{ | |
Id: user_id, | |
Email: json.Email, | |
Username: json.Username, | |
Password: json.Password, | |
Sex: json.Sex, | |
Age: json.Age, | |
} | |
if user.Email != "" && user.Username != "" { | |
_, err = dbmap.Update(&user) | |
if err == nil { | |
c.JSON(200, user) | |
} else { | |
checkErr(err, "Updated failed") | |
} | |
} else { | |
c.JSON(400, gin.H{"error": "fields are empty"}) | |
} | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i -X PUT -H "Content-Type: application/json" -d "{ \"firstname\": \"Thea\", \"lastname\": \"Merlyn\" }" http://localhost:8080/api/v1/users/1 | |
} | |
func DeleteUser(c *gin.Context) { | |
id := c.Params.ByName("id") | |
var user User | |
err := dbmap.SelectOne(&user, "SELECT * FROM User WHERE id=?;", id) | |
if err == nil { | |
_, err = dbmap.Delete(&user) | |
if err == nil { | |
c.JSON(200, gin.H{"id #" + id: "deleted"}) | |
} else { | |
checkErr(err, "Delete failed") | |
} | |
} else { | |
c.JSON(404, gin.H{"error": "user not found"}) | |
} | |
// curl -i -X DELETE http://localhost:8080/api/v1/users/1 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment