Created
December 18, 2018 01:43
-
-
Save mackee/caafebc13193638b1e11b36ff0bf479d to your computer and use it in GitHub Desktop.
Poor Socket.IO Proxy for debug
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 ( | |
"encoding/json" | |
"fmt" | |
"log" | |
) | |
type Parser interface { | |
Parse(string) error | |
} | |
//go:generate stringer -type=EngineIOPacketType | |
type EngineIOPacketType rune | |
const ( | |
EngineIOPacketOpen EngineIOPacketType = '0' + iota | |
EngineIOPacketClose | |
EngineIOPacketPing | |
EngineIOPacketPong | |
EngineIOPacketMessage | |
EngineIOPacketUpgrade | |
EngineIOPacketNoop | |
) | |
type EngineIO struct { | |
InnerParser Parser | |
} | |
type EngineIOOpenMessage struct { | |
PingInterval uint64 `json:"pingInterval"` | |
PingTimeout uint64 `json:"pingTimeout"` | |
Upgrades []string `json:"upgrades"` | |
SessionID string `json:"sid"` | |
} | |
func (eio *EngineIO) Parse(message string) error { | |
t := EngineIOPacketType(message[0]) | |
log.Printf("[INFO] Engine.IO type is %s", t) | |
if len(message) == 1 { | |
return nil | |
} | |
if t == EngineIOPacketOpen { | |
var v EngineIOOpenMessage | |
err := json.Unmarshal([]byte(message[1:]), &v) | |
if err != nil { | |
return fmt.Errorf("open message error: %s", err) | |
} | |
log.Printf("[INFO] Engine.IO open message is %+v", v) | |
return nil | |
} | |
if eio.InnerParser != nil { | |
err := eio.InnerParser.Parse(message[1:]) | |
if err != nil { | |
return fmt.Errorf("inner parser error: %s", err) | |
} | |
} | |
return nil | |
} |
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 ( | |
"io" | |
"log" | |
"net/http" | |
"strings" | |
"github.com/gorilla/websocket" | |
) | |
var upgrader = websocket.Upgrader{ | |
ReadBufferSize: 1024, | |
WriteBufferSize: 1024, | |
CheckOrigin: func(r *http.Request) bool { return true }, | |
} | |
var parser = &EngineIO{&SocketIO{}} | |
func main() { | |
http.HandleFunc("/socket.io/", func(w http.ResponseWriter, r *http.Request) { | |
log.Println("[INFO] ===================================================") | |
for key, value := range r.Header { | |
values := strings.Join(value, ",") | |
log.Printf("[INFO] header=%s, value=%s", key, values) | |
} | |
conn, err := upgrader.Upgrade(w, r, nil) | |
if err != nil { | |
log.Printf("[ERROR] websocket upgrade error: %s", err) | |
w.WriteHeader(http.StatusInternalServerError) | |
return | |
} | |
ctx := r.Context() | |
url := r.URL | |
url.Host = "localhost:3000" | |
url.Scheme = "ws" | |
h := http.Header{} | |
for _, header := range []string{"Cookie", "Origin"} { | |
h.Add(header, r.Header.Get(header)) | |
} | |
client, _, err := websocket.DefaultDialer.DialContext(ctx, url.String(), h) | |
if err != nil { | |
log.Printf("[ERROR] dial origin error: %s", err) | |
w.WriteHeader(http.StatusInternalServerError) | |
return | |
} | |
go func() { | |
for { | |
t, bs, err := client.ReadMessage() | |
if err == io.EOF { | |
break | |
} | |
parser.Parse(string(bs)) | |
switch t { | |
case websocket.TextMessage: | |
log.Printf("send message: %s", string(bs)) | |
case websocket.BinaryMessage: | |
log.Printf("send binary message") | |
case websocket.PingMessage: | |
log.Printf("send ping: %s", string(bs)) | |
case websocket.PongMessage: | |
log.Printf("send pong: %s", string(bs)) | |
} | |
if err := conn.WriteMessage(t, bs); err != nil { | |
log.Printf("[ERROR] fail send message: %s", err) | |
} | |
} | |
}() | |
for { | |
t, bs, err := conn.ReadMessage() | |
if err == io.EOF { | |
break | |
} | |
parser.Parse(string(bs)) | |
switch t { | |
case websocket.TextMessage: | |
log.Printf("recv message: %s", string(bs)) | |
case websocket.BinaryMessage: | |
log.Printf("recv binary message") | |
case websocket.PingMessage: | |
log.Printf("recv ping: %s", string(bs)) | |
case websocket.PongMessage: | |
log.Printf("recv pong: %s", string(bs)) | |
} | |
if err := client.WriteMessage(t, bs); err != nil { | |
log.Printf("[ERROR] fail recv message: %s", err) | |
} | |
} | |
}) | |
log.Println("[INFO] start server") | |
err := http.ListenAndServe(":8888", nil) | |
if err != nil { | |
log.Printf("[ERROR] fail launch server: %s", err) | |
} | |
} |
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 ( | |
"encoding/json" | |
"fmt" | |
"log" | |
) | |
//go:generate stringer -type=SocketIOPacketType | |
type SocketIOPacketType rune | |
const ( | |
SocketIOPacketConnect SocketIOPacketType = '0' + iota | |
SocketIOPacketDisconnect | |
SocketIOPacketEvent | |
SocketIOPacketAck | |
SocketIOPacketError | |
SocketIOPacketBinaryEvent | |
SocketIOPacketBinaryAck | |
) | |
type SocketIO struct { | |
} | |
type SocketIOEvent struct { | |
Name string | |
Message json.RawMessage | |
} | |
func (e *SocketIOEvent) UnmarshalJSON(b []byte) error { | |
var rawEvent []json.RawMessage | |
err := json.Unmarshal(b, &rawEvent) | |
if err != nil { | |
return err | |
} | |
if len(rawEvent) != 2 { | |
return fmt.Errorf("message is few length or too length") | |
} | |
e.Name = string(rawEvent[0]) | |
e.Message = rawEvent[1] | |
return nil | |
} | |
func (eio *SocketIO) Parse(message string) error { | |
t := SocketIOPacketType(message[0]) | |
log.Printf("[INFO] Socket.IO type is %s", t) | |
if len(message) == 1 { | |
return nil | |
} | |
if t == SocketIOPacketEvent { | |
var event SocketIOEvent | |
err := json.Unmarshal([]byte(message[1:]), &event) | |
if err != nil { | |
return fmt.Errorf("Socket.IO fail parse error: %s", err) | |
} | |
log.Printf("[INFO] Socket.IO event is name=%s, message=%s", event.Name, string(event.Message)) | |
} | |
return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment