-
Notifications
You must be signed in to change notification settings - Fork 3
/
http_rpc.go
129 lines (110 loc) · 2.74 KB
/
http_rpc.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
package http_rpc
import (
"../http_rpc/errors"
"encoding/json"
"github.com/micro/go-micro/client"
"github.com/micro/go-micro/metadata"
"github.com/micro/go-os/config"
"github.com/micro/go-web"
"github.com/prometheus/common/log"
"github.com/rs/cors"
"golang.org/x/net/context"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
//go-os config
var ConfigDefault config.Config
var Debug = false
//类似于路由
const ApiServiceName = "TODO: Write a name what you want .."
//配置Host
func APIHost() string {
return ConfigDefault.Get("api_host").String("0.0.0.0:8080")
}
func ApiAllowedOrigins() []string {
return ConfigDefault.Get("api_allowed_origins").StringSlice([]string{"*"})
}
//错误定义
var (
ErrInvalidPing = errors.BadRequest(10001, "bad ...")
)
func main() {
//启动一个web服务监听
address := APIHost()
service := web.NewService(
web.Name(ApiServiceName),
web.Address(address),
)
service.Init()
//跨域处理
c := cors.New(cors.Options{
AllowedOrigins: ApiAllowedOrigins(),
AllowedHeaders: []string{"*"},
AllowedMethods: []string{"POST", "OPTIONS"},
Debug: Debug,
MaxAge: 3600,
})
//test
service.Handle("/ping", c.Handler(http.HandlerFunc(Ping)))
}
// http request to rpc context
func RequestToContext(r *http.Request) context.Context {
//定义 non-nil empty Context
ctx := context.Background()
//通过元数据来访问RPC
md := make(metadata.Metadata)
for k, v := range r.Header {
md[k] = strings.Join(v, ",")
}
return metadata.NewContext(ctx, md)
}
func API(w http.ResponseWriter, r *http.Request) {
//TODO: Get Args 请求参数
//TODO: r.URL.Path 解析
req := client.NewJsonRequest("service", "method", "args")
ctx := RequestToContext(r)
var rpcrsp json.RawMessage
err := client.Call(ctx, req, &rpcrsp)
log.Debug("req: %v, rsp: %v, err: %v", req, string(rpcrsp), err)
err = errors.ParseFromRPCError(err)
Response(w, rpcrsp, err)
}
func Ping(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
log.Debug("ping read error: %v", err)
Response(w, nil, ErrInvalidPing)
return
}
var t float64
err = json.Unmarshal(body, &t)
if err != nil {
log.Info("unmarshal error: %v", err)
Response(w, nil, ErrInvalidPing)
}
now := float64(time.Now().UnixNano()) / 1e9
b, err := json.Marshal([]float64{t, now})
Response(w, b, err)
}
func Response(w http.ResponseWriter, body json.RawMessage, err error) {
if err != nil {
ce := errors.Parse(err.Error())
if !Debug {
ce.Internal = ""
}
switch ce.Status {
case 0:
w.WriteHeader(500)
default:
w.WriteHeader(int(ce.Status))
}
w.Write([]byte(ce.Error()))
return
}
b, _ := body.MarshalJSON()
w.Header().Set("Content-Length", strconv.Itoa(len(b)))
w.Write(b)
}