a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
59 lines
2.0 KiB
Go
59 lines
2.0 KiB
Go
package languages
|
|
|
|
import (
|
|
"regexp"
|
|
"strings"
|
|
|
|
"github.com/zzet/gortex/internal/graph"
|
|
"github.com/zzet/gortex/internal/parser"
|
|
)
|
|
|
|
// goWSUpgradeRe matches the server-side WebSocket upgrade calls of the
|
|
// common Go libraries: gorilla/websocket `upgrader.Upgrade(...)`,
|
|
// gobwas/ws `ws.UpgradeHTTP(...)`, and coder/nhooyr `websocket.Accept(...)`.
|
|
var goWSUpgradeRe = regexp.MustCompile(`\.Upgrade\s*\(|\.UpgradeHTTP\s*\(|websocket\.Accept\s*\(`)
|
|
|
|
// emitGoWebSocketEdges marks each function that performs a WebSocket
|
|
// upgrade as a real-time endpoint: it emits an EdgeListensOn from the
|
|
// handler to a per-handler websocket KindEvent node, so `analyze
|
|
// kind=pubsub` / architecture queries surface the WebSocket surface that
|
|
// the call graph cannot see. Gated on the file importing a websocket
|
|
// package to avoid matching unrelated `.Upgrade(` methods.
|
|
func emitGoWebSocketEdges(src []byte, filePath string, result *parser.ExtractionResult) {
|
|
s := string(src)
|
|
if !strings.Contains(s, "websocket") && !strings.Contains(s, "gobwas/ws") {
|
|
return
|
|
}
|
|
locs := goWSUpgradeRe.FindAllStringIndex(s, -1)
|
|
if len(locs) == 0 {
|
|
return
|
|
}
|
|
funcRanges := buildFuncRanges(result)
|
|
seenNode := map[string]bool{}
|
|
for _, m := range locs {
|
|
line := lineAt(src, m[0])
|
|
callerID := findEnclosingFunc(funcRanges, line)
|
|
if callerID == "" {
|
|
continue
|
|
}
|
|
topic := callerID
|
|
if i := strings.LastIndexAny(topic, ":./"); i >= 0 {
|
|
topic = topic[i+1:]
|
|
}
|
|
nodeID := "event::pubsub::" + transportWebSocket + "::" + topic
|
|
if !seenNode[nodeID] {
|
|
seenNode[nodeID] = true
|
|
result.Nodes = append(result.Nodes, &graph.Node{
|
|
ID: nodeID, Kind: graph.KindEvent, Name: topic,
|
|
FilePath: filePath, Language: "go",
|
|
Meta: map[string]any{"event_kind": "pubsub", "transport": transportWebSocket, "name": topic},
|
|
})
|
|
}
|
|
result.Edges = append(result.Edges, &graph.Edge{
|
|
From: callerID, To: nodeID, Kind: graph.EdgeListensOn,
|
|
FilePath: filePath, Line: line, Origin: graph.OriginASTInferred,
|
|
Meta: map[string]any{"method": "upgrade", "transport": transportWebSocket},
|
|
})
|
|
}
|
|
}
|