146 lines
3.1 KiB
Go
146 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type HAR struct {
|
|
Log struct {
|
|
Entries []struct {
|
|
Request struct {
|
|
Method string `json:"method"`
|
|
URL string `json:"url"`
|
|
} `json:"request"`
|
|
WebSocketMessages []struct {
|
|
Type string `json:"type"`
|
|
Data string `json:"data"`
|
|
Time float64 `json:"time"`
|
|
} `json:"_webSocketMessages"`
|
|
} `json:"entries"`
|
|
} `json:"log"`
|
|
}
|
|
|
|
type WSMessage struct {
|
|
ID string `json:"id"`
|
|
Type string `json:"type"`
|
|
Payload map[string]interface{} `json:"payload"`
|
|
}
|
|
|
|
func main() {
|
|
if len(os.Args) < 2 {
|
|
log.Fatal("Usage: parse-har <har-file>")
|
|
}
|
|
|
|
data, err := ioutil.ReadFile(os.Args[1])
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
var har HAR
|
|
if err := json.Unmarshal(data, &har); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// First pass: collect all responses
|
|
responses := make(map[string]bool) // ID -> has data
|
|
for _, entry := range har.Log.Entries {
|
|
for _, wsMsg := range entry.WebSocketMessages {
|
|
if wsMsg.Type != "receive" {
|
|
continue
|
|
}
|
|
|
|
var msg WSMessage
|
|
if err := json.Unmarshal([]byte(wsMsg.Data), &msg); err != nil {
|
|
continue
|
|
}
|
|
|
|
if msg.Type == "next" {
|
|
// Check if payload has data
|
|
if data, ok := msg.Payload["data"].(map[string]interface{}); ok && len(data) > 0 {
|
|
responses[msg.ID] = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Println("=== WebSocket Operations (in order) ===\n")
|
|
|
|
msgCount := 0
|
|
for _, entry := range har.Log.Entries {
|
|
for _, wsMsg := range entry.WebSocketMessages {
|
|
if wsMsg.Type != "send" {
|
|
continue
|
|
}
|
|
|
|
var msg WSMessage
|
|
if err := json.Unmarshal([]byte(wsMsg.Data), &msg); err != nil {
|
|
continue
|
|
}
|
|
|
|
if msg.Type == "connection_init" {
|
|
fmt.Printf("[%d] connection_init\n", msgCount)
|
|
msgCount++
|
|
continue
|
|
}
|
|
|
|
if msg.Type == "subscribe" {
|
|
opName := ""
|
|
query := ""
|
|
variables := map[string]interface{}{}
|
|
extensions := map[string]interface{}{}
|
|
|
|
if payload, ok := msg.Payload["operationName"].(string); ok {
|
|
opName = payload
|
|
}
|
|
if q, ok := msg.Payload["query"].(string); ok {
|
|
query = q
|
|
}
|
|
if v, ok := msg.Payload["variables"].(map[string]interface{}); ok {
|
|
variables = v
|
|
}
|
|
if e, ok := msg.Payload["extensions"].(map[string]interface{}); ok {
|
|
extensions = e
|
|
}
|
|
|
|
hasResponse := ""
|
|
if responses[msg.ID] {
|
|
hasResponse = " ✅ GOT DATA"
|
|
} else {
|
|
hasResponse = " ❌ NO DATA"
|
|
}
|
|
fmt.Printf("[%d] %s (ID: %s)%s\n", msgCount, opName, msg.ID, hasResponse)
|
|
|
|
// Show query type
|
|
if strings.Contains(query, "mutation") {
|
|
fmt.Printf(" Type: MUTATION\n")
|
|
} else if strings.Contains(query, "subscription") {
|
|
fmt.Printf(" Type: SUBSCRIPTION\n")
|
|
} else if strings.Contains(query, "query") {
|
|
fmt.Printf(" Type: QUERY\n")
|
|
}
|
|
|
|
// Show variables
|
|
if len(variables) > 0 {
|
|
fmt.Printf(" Variables: %v\n", variables)
|
|
}
|
|
|
|
// Show extensions
|
|
if len(extensions) > 0 {
|
|
fmt.Printf(" Extensions: %v\n", extensions)
|
|
}
|
|
|
|
fmt.Println()
|
|
msgCount++
|
|
}
|
|
}
|
|
}
|
|
|
|
fmt.Printf("\nTotal operations: %d\n", msgCount)
|
|
}
|
|
|