0%

Experience of Full Stack Development

最近幫朋友幫忙寫一個可以Demo的Protottype,有三個角色
Server,Client,Observer
許多Client會送資料給Server,Server處理這些資料之後匯集給Observer
說來不難的東西,因為用了我不熟的技術,golang + javascript,浪費太多時間
果然隔行如隔山啊,寫寫在路上遇到的問題

SSL / TLS Transport

由於想要練習,所以直接用SSL來當作傳輸協定,跟TCP大同小異,不過困難的是Certificate的產生
Server端

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
cert, err := tls.LoadX509KeyPair("certs/server.pem", "certs/server.key")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
config := tls.Config{Certificates: []tls.Certificate{cert}}
config.Rand = rand.Reader
service := "0.0.0.0:8000"
listener, err := tls.Listen("tcp", service, &config)
if err != nil {
log.Fatalf("server: listen: %s", err)
}
for {
conn, err := listener.Accept()
if err != nil {
log.Printf("server: accept: %s", err)
break
}
defer conn.Close()
log.Printf("server: accepted from %s", conn.RemoteAddr())
tlscon, ok := conn.(*tls.Conn)
if ok {
log.Print("ok=true")
state := tlscon.ConnectionState()
for _, v := range state.PeerCertificates {
log.Print(x509.MarshalPKIXPublicKey(v.PublicKey))
}
go handleClient(conn)
} else {
log.Print("reject connection")
}
}

Client端

1
2
3
4
5
6
7
8
9
10
cert, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
if err != nil {
log.Fatalf("server: loadkeys: %s", err)
}
config := tls.Config{Certificates: []tls.Certificate{cert}, InsecureSkipVerify: true}
conn, err := tls.Dial("tcp", "127.0.0.1:8000", &config)
if err != nil {
log.Fatalf("client: dial: %s", err)
}
clientFunc(conn)

至於Certificate是用Openssl產生的,於是產生第二個問題

Websocket

這個坑實在死的不明不白
Server端原先這樣寫

1
2
3
4
5
6
7
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
log.Print("New websocket arrive")
serveWs(hub, w, r)
})
if err := http.ListenAndServeTLS("localhost:8888", "certs/server.pem", "certs/server.key", nil); err != nil {
log.Fatal("ListenAndServe:", err)
}

而Observer端則是

1
ws = new WebSocket("wss://127.0.0.1:8888/ws")

看起來沒什麼問題,不過不然,目前的websocket不能接受 Self hosted certificate,然後就怎麼連都連不上了
為了省事,直接用wshttp傳輸了

Aggregate Json

我想要做的功能是假設
Client A傳送

1
[{Name: 'aaa', Age: 18}, {Name: 'bbb', Age: 81}]

Client B傳送`

1
[{Name: 'ccc', Age: 28}, {Name: 'bbb', Age: 82}]

Oberver會看到

1
[{Name: 'aaa', Age: 18}, {Name: 'bbb', Age: 81}, {Name: 'ccc', Age: 28}, {Name: 'bbb', Age: 82}]

我不太熟悉golang對json的操作,於是寫了醜陋無比的程式碼

1
2
3
4
5
6
7
8
9
10
11
12
type keyvalue map[string]string
var keyvalueslice []keyvalue
for _, v := range Map {
var m1 []keyvalue
if err := json.Unmarshal([]byte(v), &m1); err != nil {
log.Print(err)
}
for _, obj := range m1 {
keyvalueslice = append(keyvalueslice, obj)
}
}
b, _ := json.Marshal(keyvalueslice)

實在感到羞恥啊…

React / Webpack

雖然知道React跟Webpack,不過實際拿來用是另外一回事
React還好,因為我沒用到太深的東西,不過webpack.config.js很複雜
要找Websocket Bug的時候,SourceMap還生不出來,只好土法煉鋼

Conclusion

隔行如隔山,不跳脫舒適圈去搞些平時不會搞的東西,什麼時候死都不知道
不過這次經驗真是讓我充滿挫折 Orz