提交 2fb09665 编写于 作者: W wuhanqing

重新封装response, 处理OPTIONS预检请求

上级 19d9358a
......@@ -28,25 +28,6 @@ func NewRequest(data []byte, conn net.Conn) *Request {
return &Request{data: data, conn: conn}
}
func (r Request) ResponseJson(v interface{}) error {
var body []byte
var err error
switch v.(type) {
case []byte:
body = v.([]byte)
case string:
body = []byte(v.(string))
default:
body, err = json.Marshal(v)
if err != nil {
return err
}
}
data := NewResponseOK(body).HttpJson()
_, err = r.conn.Write(data)
return err
}
func (r Request) ResponseWebSocket() error {
reqHeader := r.GetHttpRequest().Header
accept, err := r.getWebSocketNonceAccept([]byte(reqHeader["Sec-Websocket-Key"][0])) // Sec-WebSocket-Key to Sec-Websocket-Key
......@@ -69,6 +50,10 @@ func (r Request) GetData() []byte {
return r.data
}
func (r Request) GetConn() net.Conn {
return r.conn
}
func (r Request) GetHttpBodyToJson(v interface{}) error {
return json.Unmarshal(r.GetHttpBody(), v)
}
......
......@@ -2,23 +2,22 @@ package model
import (
"bytes"
"encoding/json"
"fmt"
"net"
"net/http"
"strings"
)
type Response struct {
statusCode int
body []byte
}
func NewResponse(statusCode int, body []byte) *Response {
return &Response{statusCode: statusCode, body: body}
statusCode int
err error
conn net.Conn
body, response []byte
}
func NewResponseOK(body []byte) *Response {
return NewResponse(http.StatusOK, body)
func NewResponse(conn net.Conn) *Response {
return &Response{conn: conn}
}
func (r Response) getHeader() []string {
......@@ -41,7 +40,7 @@ func (r Response) getHeader() []string {
// https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
}
func (r Response) HttpJson() []byte {
func (r Response) httpJson() []byte {
header := r.getHeader()
header = append(header, "Content-Type: application/json; charset=utf-8")
headerText := strings.Join(header, "\n")
......@@ -49,11 +48,46 @@ func (r Response) HttpJson() []byte {
// return []byte(headerText + "\n\r\n" + string(r.body))
}
func (r Response) HttpHtml() []byte {
func (r Response) Json(v interface{}) Response {
var err error
switch v.(type) {
case []byte:
r.body = v.([]byte)
case string:
r.body = []byte(v.(string))
default:
r.body, err = json.Marshal(v)
if err != nil {
r.err = err
}
}
if r.err == nil {
r.statusCode = http.StatusOK
r.response = r.httpJson()
}
return r
}
func (r Response) OPTIONS() Response {
return r.Html([]byte{}, 200)
}
func (r Response) Html(body []byte, statusCode int) Response {
r.statusCode = http.StatusOK
r.body = body
header := r.getHeader()
header = append(header, "Content-Type: text/html; charset=utf-8")
headerText := strings.Join(header, "\n")
return []byte(headerText + "\n\r\n" + string(r.body))
r.response = []byte(headerText + "\n\r\n" + string(r.body))
return r
}
func (r Response) Write() error {
if r.err != nil {
return r.err
}
_, err := r.conn.Write(r.response)
return err
}
type JsonObject map[string]interface{}
......@@ -63,10 +97,6 @@ type ResponseApiData struct {
Data JsonObject `json:"data"`
}
func (r ResponseApiData) Write(req Request) error {
return req.ResponseJson(r)
}
func ResponseApi(data JsonObject, msg string, code int) ResponseApiData {
return ResponseApiData{Data: data, Msg: msg, Code: code}
}
......
......@@ -31,7 +31,11 @@ func MainHandler(u contract.IUser) error {
if isHttp && msgCount == 1 {
// HTTP API 接口业务处理。不支持HTTP 的 Keep-Alive
req := model.NewRequest(data, u.GetConn())
req.ParseHttp()
err = req.ParseHttp()
if err != nil {
logger.Error(fmt.Sprintf("---ParseHttpError(%v)---", err))
return err
}
if req.IsWebSocket() {
// websocket 握手
dp.SetProtocol(model.PROTOCOL_WEBSOCKET)
......
package handler
import (
"fmt"
"github.com/iotames/easyim/model"
)
var HttpApiRoute map[string]func(req *model.Request) error = map[string]func(req *model.Request) error{
"/api/user/register": userRegister,
"/api/user/login": userLogin,
"/api/user/logout": userLogout,
"/api/user/check_token": checkUserToken,
"/api/user/refresh_token": userRefreshToken,
"/api/user/friends": getUserFriends,
"/api/user/friend/add": addUserFriend,
"/api/user/friend/accept": acceptUserFriend,
"/api/user/friend/remove": removeUserFriend,
"/api/user/search": searchUser,
var HttpApiRoute map[string]func(req *model.Request, resp *model.Response) model.Response = map[string]func(req *model.Request, resp *model.Response) model.Response{
"POST /api/user/register": userRegister,
"POST /api/user/login": userLogin,
"POST /api/user/logout": userLogout,
"GET /api/user/check_token": checkUserToken,
"POST /api/user/refresh_token": userRefreshToken,
"GET /api/user/friends": getUserFriends,
"POST /api/user/friend/add": addUserFriend,
"POST /api/user/friend/accept": acceptUserFriend,
"POST /api/user/friend/remove": removeUserFriend,
"GET /api/user/search": searchUser,
}
func HttpHandler(req *model.Request) error {
hreq := req.GetHttpRequest()
handler, ok := HttpApiRoute[hreq.URL.Path]
resp := model.NewResponse(req.GetConn())
if hreq.Method == "OPTIONS" {
return resp.OPTIONS().Write()
}
handler, ok := HttpApiRoute[fmt.Sprintf("%s %s", hreq.Method, hreq.URL.Path)]
if ok {
return handler(req)
resp := handler(req, resp)
return resp.Write()
}
return HttpNotFound(req, resp).Write()
}
func HttpNotFound(req *model.Request, resp *model.Response) model.Response {
hreq := req.GetHttpRequest()
data := model.JsonObject{
"protocol": hreq.Proto,
"method": hreq.Method,
......@@ -32,7 +44,7 @@ func HttpHandler(req *model.Request) error {
"query": hreq.URL.RawQuery,
"body": req.GetHttpBody(),
}
return model.ResponseApi(data, "找不到路由", 400).Write(*req)
return resp.Json(model.ResponseApi(data, "找不到路由", 400))
}
type UserLoginForm struct {
......
......@@ -4,3 +4,9 @@ package handler
// TODO 邀请好友进群聊
// TODO 退出群聊
// TODO 近期聊天
/**
* @api {options} /options OPTIONS预检请求
* @apiName OPTIONS预检请求
* @apiGroup Other
*/
......@@ -6,7 +6,7 @@ import (
/**
* @api {get} /api/user/friends 好友列表
* @apiGroup 好友相关
* @apiGroup Friend
* @apiDescription 获取用户的好友列表(通讯录显示的联系人)
* @apiQuery {String} access_token 通讯凭证: access_token 的值
* @apiSuccess {integer} code 状态码(请求成功为200)
......@@ -25,14 +25,14 @@ import (
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{}}
*/
func getUserFriends(req *model.Request) error {
return nil
func getUserFriends(req *model.Request, resp *model.Response) model.Response {
return *resp
}
/**
* @api {post} /api/user/friend/add 发起好友邀请
* @apiName 发起好友邀请
* @apiGroup 好友相关
* @apiGroup Friend
* @apiDescription 搜索用户后,对该用户发送好友邀请。需要用户同意邀请,才能成为正式好友。
* @apiBody {String} access_token 发起好友邀请的用户的身份令牌
* @apiBody {String} to_user_id 被邀请用户的ID
......@@ -43,13 +43,13 @@ func getUserFriends(req *model.Request) error {
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{"id":"1629420924912535555"}}
*/
func addUserFriend(req *model.Request) error {
return nil
func addUserFriend(req *model.Request, resp *model.Response) model.Response {
return *resp
}
/**
* @api {post} /api/user/friend/accept 接受好友邀请
* @apiGroup 好友相关
* @apiGroup Friend
* @apiDescription 同意其他用户发过来的好友申请。正式成为好友。
* @apiBody {String} access_token 接受好友邀请的用户的身份令牌
* @apiBody {String} id 好友邀请的请求ID
......@@ -59,24 +59,24 @@ func addUserFriend(req *model.Request) error {
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{}}
*/
func acceptUserFriend(req *model.Request) error {
return nil
func acceptUserFriend(req *model.Request, resp *model.Response) model.Response {
return *resp
}
/**
* @api {post} /api/user/friend/remove 删除好友
* @apiGroup 好友相关
* @apiGroup Friend
* @apiDescription TODO
*/
func removeUserFriend(req *model.Request) error {
return nil
func removeUserFriend(req *model.Request, resp *model.Response) model.Response {
return *resp
}
/**
* @api {get} /api/user/search 用户搜索
* @apiGroup 好友相关
* @apiGroup Friend
* @apiDescription 根据用户账号搜索用户 TODO
*/
func searchUser(req *model.Request) error {
return nil
func searchUser(req *model.Request, resp *model.Response) model.Response {
return *resp
}
......@@ -26,22 +26,22 @@ import (
* {"code":400,"msg":"密码不正确","data":{}}
* @apiUse LoginOrRegisterSuccessBlock
*/
func userLogin(req *model.Request) error {
func userLogin(req *model.Request, resp *model.Response) model.Response {
postData := UserLoginForm{}
err := req.GetHttpBodyToJson(&postData)
if err != nil {
return req.ResponseJson(model.ResponseQueryArgsError(err.Error()))
return resp.Json(model.ResponseQueryArgsError(err.Error()))
}
user := new(database.User)
user.Account = postData.Account
database.GetModel(user)
if user.ID == 0 {
return model.ResponseFail("找不到登录账号", 400).Write(*req)
return resp.Json(model.ResponseFail("找不到登录账号", 400))
}
if !user.CheckPassword(postData.Password) {
return model.ResponseFail("密码不正确", 400).Write(*req)
return resp.Json(model.ResponseFail("密码不正确", 400))
}
return loginOrRegisterSuccess(*user, *req)
return loginOrRegisterSuccess(*user, resp)
}
/**
......@@ -55,18 +55,18 @@ func userLogin(req *model.Request) error {
* {"code":400,"msg":"注册失败!登录账号已存在","data":{}}
* @apiUse LoginOrRegisterSuccessBlock
*/
func userRegister(req *model.Request) error {
func userRegister(req *model.Request, resp *model.Response) model.Response {
postData := UserRegisterForm{}
err := req.GetHttpBodyToJson(&postData)
if err != nil {
return req.ResponseJson(model.ResponseQueryArgsError(err.Error()))
return resp.Json(model.ResponseQueryArgsError(err.Error()))
}
u := database.User{Account: postData.Account, Nickname: postData.Nickname}
u, err = u.Register(postData.Password)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
return loginOrRegisterSuccess(u, *req)
return loginOrRegisterSuccess(u, resp)
}
/**
......@@ -80,7 +80,7 @@ func userRegister(req *model.Request) error {
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50IjoiYWNjb3VudFd1aGFucWluZyIsImF2YXRhciI6IiIsImV4cCI6MTY3NzQ3NDkxNCwiaWQiOjE2Mjk0MjA5MjQ5MTI1Mzc2MDB9.IucceY2x7FSB81-nxEj_yMYggYaBnCzEX1GA8LdzPCE","avatar":"https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png","expires_in":7200,"id":"1629420924912537600","nickname":"飞天的猪","refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2NvdW50IjoiYWNjb3VudFd1aGFucWluZyIsImF2YXRhciI6IiIsImV4cCI6MTY4MDA1OTcxNCwiaWQiOjE2Mjk0MjA5MjQ5MTI1Mzc2MDB9.Mu4N8-uegCdq26ocIx7HINmoUgLyrwpqo4cYDslHwzs"}}
*/
func loginOrRegisterSuccess(u database.User, req model.Request) error {
func loginOrRegisterSuccess(u database.User, resp *model.Response) model.Response {
jwtInfo := u.GetJwtInfo()
data := model.JsonObject{
"id": fmt.Sprintf("%d", u.ID),
......@@ -90,7 +90,7 @@ func loginOrRegisterSuccess(u database.User, req model.Request) error {
"expires_in": jwtInfo.Expiresin,
"refresh_token": jwtInfo.RefreshToken,
}
return model.ResponseApi(data, "success", 200).Write(req)
return resp.Json(model.ResponseApi(data, "success", 200))
}
/**
......@@ -103,51 +103,51 @@ func loginOrRegisterSuccess(u database.User, req model.Request) error {
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"退出登录成功","data":{}}
*/
func userLogout(req *model.Request) error {
func userLogout(req *model.Request, resp *model.Response) model.Response {
postData := PostAccessToken{}
err := req.GetHttpBodyToJson(&postData)
if err != nil {
return req.ResponseJson(model.ResponseQueryArgsError(err.Error()))
return resp.Json(model.ResponseQueryArgsError(err.Error()))
}
u := database.User{}
err = u.Logout(postData.AccessToken)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
return model.ResponseOk("登出成功").Write(*req)
return resp.Json(model.ResponseOk("登出成功"))
}
/**
* @api {get} /api/user/check_token 校验token
* @apiGroup 用户与权限
* @apiQuery {String} token 通讯凭证: access_token 或 refresh_token 的值
* @apiSuccess {integer} code 状态码(请求成功为200)
* @apiSuccess {string} msg 请求成功提示信息
* @apiSuccess {Object} data 响应数据
* @apiError {integer} code 请求异常状态码
* @apiError {string} msg 请求异常提示信息
* @apiSuccess {Number} data.expires_in 有效期剩余时间。单位:秒
* @apiSuccess {String} data.grant_type token授权模式。值为 access_token 或 refresh_token
* @apiErrorExample {json} 请求异常示例
* {"code":400,"msg":"access_token不正确","data":{}}
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{"expires_in":7130,"grant_type":"access_token"}}
* @api {get} /api/user/check_token 校验token
* @apiGroup 用户与权限
* @apiQuery {String} token 通讯凭证: access_token 或 refresh_token 的值
* @apiSuccess {integer} code 状态码(请求成功为200)
* @apiSuccess {string} msg 请求成功提示信息
* @apiSuccess {Object} data 响应数据
* @apiError {integer} code 请求异常状态码
* @apiError {string} msg 请求异常提示信息
* @apiSuccess {Number} data.expires_in 有效期剩余时间。单位:秒
* @apiSuccess {String} data.grant_type token授权模式。值为 access_token 或 refresh_token
* @apiErrorExample {json} 请求异常示例
* {"code":400,"msg":"access_token不正确","data":{}}
* @apiSuccessExample {json} 请求成功示例
* {"code":200,"msg":"success","data":{"expires_in":7130,"grant_type":"access_token"}}
*/
func checkUserToken(req *model.Request) error {
func checkUserToken(req *model.Request, resp *model.Response) model.Response {
query := req.GetHttpRequest().URL.Query()
token := query.Get("token")
u := database.User{}
claims, err := u.DecodeJwt(token)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
grantType, ok := claims[database.GRANT_TYPE]
if !ok {
return model.ResponseFail("token 不正确", 400).Write(*req)
return resp.Json(model.ResponseFail("token 不正确", 400))
}
_, err = u.GetUserByJwt(token, claims)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
expiredAt, _ := claims["exp"].(json.Number).Int64()
expiresIn := expiredAt - time.Now().Unix()
......@@ -155,7 +155,7 @@ func checkUserToken(req *model.Request) error {
"grant_type": grantType,
"expires_in": expiresIn,
}
return model.ResponseApi(data, "success", 200).Write(*req)
return resp.Json(model.ResponseApi(data, "success", 200))
}
/**
......@@ -185,21 +185,21 @@ func checkUserToken(req *model.Request) error {
* }
*}
*/
func userRefreshToken(req *model.Request) error {
func userRefreshToken(req *model.Request, resp *model.Response) model.Response {
postData := PostRefreshToken{}
err := req.GetHttpBodyToJson(&postData)
if err != nil {
return req.ResponseJson(model.ResponseQueryArgsError(err.Error()))
return resp.Json(model.ResponseQueryArgsError(err.Error()))
}
// 验证refresh_token Begin
u := new(database.User)
claims, err := u.CheckTokenGrantType(postData.RefreshToken, database.REFRESH_TOKEN)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
uu, err := u.GetUserByJwt(postData.RefreshToken, claims)
if err != nil {
return model.ResponseFail(err.Error(), 400).Write(*req)
return resp.Json(model.ResponseFail(err.Error(), 400))
}
// 验证refresh_token End
if postData.ResetSecret {
......@@ -213,11 +213,11 @@ func userRefreshToken(req *model.Request) error {
}
if postData.GrantType == database.ACCESS_TOKEN {
data["token"] = uu.GetAccessToken()
return model.ResponseApi(data, "success", 200).Write(*req)
return resp.Json(model.ResponseApi(data, "success", 200))
}
if postData.GrantType == database.REFRESH_TOKEN {
data["token"] = uu.GetRefreshToken()
return model.ResponseApi(data, "success", 200).Write(*req)
return resp.Json(model.ResponseApi(data, "success", 200))
}
return model.ResponseFail("grant_type不正确", 400).Write(*req)
return resp.Json(model.ResponseFail("grant_type不正确", 400))
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册