forked from chanxuehong/wechat
/
multi_server_frontend.go
131 lines (111 loc) · 4.26 KB
/
multi_server_frontend.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// @description wechat 是腾讯微信公众平台 api 的 golang 语言封装
// @link https://github.com/chanxuehong/wechat for the canonical source repository
// @license https://github.com/chanxuehong/wechat/blob/master/LICENSE
// @authors chanxuehong(chanxuehong@gmail.com)
package mp
import (
"fmt"
"net/http"
"net/url"
"sync"
)
// 回调 URL 上索引 WechatServer 的 key 的名称.
// 比如下面的回调地址里面就可以根据 wechat1 来索引对应的 WechatServer.
// http://www.xxx.com/?wechat_server=wechat1&signature=XXX×tamp=123456789&nonce=12345678
const URLQueryWechatServerKeyName = "wechat_server"
// 多个 WechatServer 的前端, 负责处理 http 请求, net/http.Handler 的实现
//
// NOTE:
// MultiWechatServerFrontend 可以处理多个公众号的消息(事件),但是要求在回调 URL 上加上一个
// 查询参数,参考常量 URLQueryWechatServerKeyName,这个参数的值就是 MultiWechatServerFrontend
// 索引 WechatServer 的 key。
//
// 例如回调 URL 为 http://www.xxx.com/weixin?wechat_server=1234567890,那么就可以在后端调用
//
// MultiWechatServerFrontend.SetWechatServer("1234567890", WechatServer)
//
// 来增加一个 WechatServer 来处理 wechat_server=1234567890 的消息(事件)。
//
// MultiWechatServerFrontend 并发安全,可以在运行中动态增加和删除 WechatServer。
type MultiWechatServerFrontend struct {
rwmutex sync.RWMutex
wechatServerMap map[string]WechatServer
invalidRequestHandler InvalidRequestHandler
}
// 设置 InvalidRequestHandler, 如果 handler == nil 则使用默认的 DefaultInvalidRequestHandler
func (frontend *MultiWechatServerFrontend) SetInvalidRequestHandler(handler InvalidRequestHandler) {
frontend.rwmutex.Lock()
defer frontend.rwmutex.Unlock()
if handler == nil {
frontend.invalidRequestHandler = DefaultInvalidRequestHandler
} else {
frontend.invalidRequestHandler = handler
}
}
// 设置 serverKey-WechatServer pair.
// 如果 serverKey == "" 或者 server == nil 则不做任何操作
func (frontend *MultiWechatServerFrontend) SetWechatServer(serverKey string, server WechatServer) {
if serverKey == "" {
return
}
if server == nil {
return
}
frontend.rwmutex.Lock()
defer frontend.rwmutex.Unlock()
if frontend.wechatServerMap == nil {
frontend.wechatServerMap = make(map[string]WechatServer)
}
frontend.wechatServerMap[serverKey] = server
}
// 删除 serverKey 对应的 WechatServer
func (frontend *MultiWechatServerFrontend) DeleteWechatServer(serverKey string) {
frontend.rwmutex.Lock()
defer frontend.rwmutex.Unlock()
delete(frontend.wechatServerMap, serverKey)
}
// 删除所有的 WechatServer
func (frontend *MultiWechatServerFrontend) DeleteAllWechatServer() {
frontend.rwmutex.Lock()
defer frontend.rwmutex.Unlock()
frontend.wechatServerMap = make(map[string]WechatServer)
}
// 实现 http.Handler
func (frontend *MultiWechatServerFrontend) ServeHTTP(w http.ResponseWriter, r *http.Request) {
urlValues, err := url.ParseQuery(r.URL.RawQuery)
if err != nil {
frontend.rwmutex.RLock()
invalidRequestHandler := frontend.invalidRequestHandler
frontend.rwmutex.RUnlock()
if invalidRequestHandler == nil {
invalidRequestHandler = DefaultInvalidRequestHandler
}
invalidRequestHandler.ServeInvalidRequest(w, r, err)
return
}
serverKey := urlValues.Get(URLQueryWechatServerKeyName)
if serverKey == "" {
frontend.rwmutex.RLock()
invalidRequestHandler := frontend.invalidRequestHandler
frontend.rwmutex.RUnlock()
if invalidRequestHandler == nil {
invalidRequestHandler = DefaultInvalidRequestHandler
}
err = fmt.Errorf("the url query value with name %s is empty", URLQueryWechatServerKeyName)
invalidRequestHandler.ServeInvalidRequest(w, r, err)
return
}
frontend.rwmutex.RLock()
invalidRequestHandler := frontend.invalidRequestHandler
wechatServer := frontend.wechatServerMap[serverKey]
frontend.rwmutex.RUnlock()
if invalidRequestHandler == nil {
invalidRequestHandler = DefaultInvalidRequestHandler
}
if wechatServer == nil {
err = fmt.Errorf("Not found WechatServer for %s == %s", URLQueryWechatServerKeyName, serverKey)
invalidRequestHandler.ServeInvalidRequest(w, r, err)
return
}
ServeHTTP(w, r, urlValues, wechatServer, invalidRequestHandler)
}