diff --git a/Dockerfile b/Dockerfile index 9345df30c..b1d74b4f9 100644 --- a/Dockerfile +++ b/Dockerfile @@ -42,8 +42,8 @@ RUN go build -ldflags="-s -w \ -X 'mizuserver/pkg/version.SemVer=${SEM_VER}'" -o mizuagent . # Download Basenine executable, verify the sha1sum and move it to a directory in $PATH -ADD https://github.com/up9inc/basenine/releases/download/v0.2.6/basenine_linux_amd64 ./basenine_linux_amd64 -ADD https://github.com/up9inc/basenine/releases/download/v0.2.6/basenine_linux_amd64.sha256 ./basenine_linux_amd64.sha256 +ADD https://github.com/up9inc/basenine/releases/download/v0.2.8/basenine_linux_amd64 ./basenine_linux_amd64 +ADD https://github.com/up9inc/basenine/releases/download/v0.2.8/basenine_linux_amd64.sha256 ./basenine_linux_amd64.sha256 RUN shasum -a 256 -c basenine_linux_amd64.sha256 RUN chmod +x ./basenine_linux_amd64 diff --git a/agent/go.mod b/agent/go.mod index 68b61dccd..a39ab79ce 100644 --- a/agent/go.mod +++ b/agent/go.mod @@ -16,7 +16,7 @@ require ( github.com/op/go-logging v0.0.0-20160315200505-970db520ece7 github.com/orcaman/concurrent-map v0.0.0-20210106121528-16402b402231 github.com/patrickmn/go-cache v2.1.0+incompatible - github.com/up9inc/basenine/client/go v0.0.0-20211109233221-12b405471084 + github.com/up9inc/basenine/client/go v0.0.0-20211114204315-4d028da5fda5 github.com/up9inc/mizu/shared v0.0.0 github.com/up9inc/mizu/tap v0.0.0 github.com/up9inc/mizu/tap/api v0.0.0 diff --git a/agent/go.sum b/agent/go.sum index 2f4f0cade..4ed8136b3 100644 --- a/agent/go.sum +++ b/agent/go.sum @@ -450,8 +450,8 @@ github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/up9inc/basenine/client/go v0.0.0-20211109233221-12b405471084 h1:gLoP7AyS/c6pYuBQOgALWpzzc5/aSrq98Lr49JRfmfs= -github.com/up9inc/basenine/client/go v0.0.0-20211109233221-12b405471084/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= +github.com/up9inc/basenine/client/go v0.0.0-20211114204315-4d028da5fda5 h1:JbLairDLEJpAC8bwmFuOAB+LYpY/oQbzGRSWRpkF7PQ= +github.com/up9inc/basenine/client/go v0.0.0-20211114204315-4d028da5fda5/go.mod h1:SvJGPoa/6erhUQV7kvHBwM/0x5LyO6XaG2lUaCaKiUI= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f h1:p4VB7kIXpOQvVn1ZaTIVp+3vuYAXFe3OJEvjbUYJLaA= github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= diff --git a/debug.Dockerfile b/debug.Dockerfile index d04e6b995..7728c13e2 100644 --- a/debug.Dockerfile +++ b/debug.Dockerfile @@ -37,8 +37,8 @@ COPY agent . RUN go build -gcflags="all=-N -l" -o mizuagent . # Download Basenine executable, verify the sha1sum and move it to a directory in $PATH -ADD https://github.com/up9inc/basenine/releases/download/v0.2.6/basenine_linux_amd64 ./basenine_linux_amd64 -ADD https://github.com/up9inc/basenine/releases/download/v0.2.6/basenine_linux_amd64.sha256 ./basenine_linux_amd64.sha256 +ADD https://github.com/up9inc/basenine/releases/download/v0.2.8/basenine_linux_amd64 ./basenine_linux_amd64 +ADD https://github.com/up9inc/basenine/releases/download/v0.2.8/basenine_linux_amd64.sha256 ./basenine_linux_amd64.sha256 RUN shasum -a 256 -c basenine_linux_amd64.sha256 RUN chmod +x ./basenine_linux_amd64 diff --git a/tap/extensions/http/main.go b/tap/extensions/http/main.go index b58fc7a02..d24a8d478 100644 --- a/tap/extensions/http/main.go +++ b/tap/extensions/http/main.go @@ -418,7 +418,7 @@ func (d dissecting) Represent(protoIn api.Protocol, request map[string]interface func (d dissecting) Macros() map[string]string { return map[string]string{ - `http`: fmt.Sprintf(`proto.abbr == "%s"`, protocol.Abbreviation), + `http`: fmt.Sprintf(`proto.abbr == "%s" and proto.version == "%s"`, protocol.Abbreviation, protocol.Version), `grpc`: fmt.Sprintf(`proto.abbr == "%s" and proto.version == "%s"`, protocol.Abbreviation, http2Protocol.Version), `http2`: fmt.Sprintf(`proto.abbr == "%s" and proto.version == "%s"`, protocol.Abbreviation, http2Protocol.Version), } diff --git a/ui/package-lock.json b/ui/package-lock.json index 745364d11..c0d6ddd5a 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -13644,9 +13644,9 @@ } }, "react-scrollable-feed-virtualized": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/react-scrollable-feed-virtualized/-/react-scrollable-feed-virtualized-1.4.3.tgz", - "integrity": "sha512-M9WgJKr57jCyWKNCksc3oi+xhtO0YbL9d7Ll8Sdc5ZWOIstNvdNbNX0k4Nq6kXUVaHCJ9qE8omdSI/CxT3MLAQ==" + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/react-scrollable-feed-virtualized/-/react-scrollable-feed-virtualized-1.4.8.tgz", + "integrity": "sha512-zsSO/9QB+4V6HEk39lxeMEUA6JFSZjfV4stw7RF17+vZdlVhyATsTBCzsj8hZywY4F29cBfH+3/GKrMhwmhAsw==" }, "react-syntax-highlighter": { "version": "15.4.3", diff --git a/ui/package.json b/ui/package.json index 088241fe0..68dc98301 100644 --- a/ui/package.json +++ b/ui/package.json @@ -23,7 +23,7 @@ "react-copy-to-clipboard": "^5.0.3", "react-dom": "^17.0.2", "react-scripts": "4.0.3", - "react-scrollable-feed-virtualized": "^1.4.3", + "react-scrollable-feed-virtualized": "^1.4.8", "react-syntax-highlighter": "^15.4.3", "react-toastify": "^8.0.3", "typescript": "^4.2.4", diff --git a/ui/src/components/EntriesList.tsx b/ui/src/components/EntriesList.tsx index 1ec329469..081c1966f 100644 --- a/ui/src/components/EntriesList.tsx +++ b/ui/src/components/EntriesList.tsx @@ -1,4 +1,3 @@ -import {EntryItem} from "./EntryListItem/EntryListItem"; import React, {useRef} from "react"; import styles from './style/EntriesList.module.sass'; import ScrollableFeedVirtualized from "react-scrollable-feed-virtualized"; @@ -6,40 +5,32 @@ import down from "./assets/downImg.svg"; interface EntriesListProps { entries: any[]; - setEntries: (entries: any[]) => void; - focusedEntryId: string; - setFocusedEntryId: (id: string) => void; listEntryREF: any; - onScrollEvent: (isAtBottom:boolean) => void; - scrollableList: boolean; - ws: any - openWebSocket: any; - query: string; - updateQuery: any; + onSnapBrokenEvent: () => void; + isSnappedToBottom: boolean; + setIsSnappedToBottom: any; queriedCurrent: number; queriedTotal: number; startTime: number; } -export const EntriesList: React.FC = ({entries, setEntries, focusedEntryId, setFocusedEntryId, listEntryREF, onScrollEvent, scrollableList, ws, openWebSocket, query, updateQuery, queriedCurrent, queriedTotal, startTime}) => { +export const EntriesList: React.FC = ({entries, listEntryREF, onSnapBrokenEvent, isSnappedToBottom, setIsSnappedToBottom, queriedCurrent, queriedTotal, startTime}) => { const scrollableRef = useRef(null); return <>
- onScrollEvent(isAtBottom)}> + {false /* TODO: why there is a need for something here (not necessarily false)? */} - {entries.map(entry => )} + {entries}
diff --git a/ui/src/components/EntryListItem/EntryListItem.tsx b/ui/src/components/EntryListItem/EntryListItem.tsx index ae771801d..e9346d6c5 100644 --- a/ui/src/components/EntryListItem/EntryListItem.tsx +++ b/ui/src/components/EntryListItem/EntryListItem.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React, {useState} from "react"; import styles from './EntryListItem.module.sass'; import StatusCode, {getClassification, StatusCodeClassification} from "../UI/StatusCode"; import Protocol, {ProtocolInterface} from "../UI/Protocol" @@ -38,12 +38,14 @@ interface Rules { interface EntryProps { entry: Entry; setFocusedEntryId: (id: string) => void; - isSelected?: boolean; style: object; updateQuery: any; } -export const EntryItem: React.FC = ({entry, setFocusedEntryId, isSelected, style, updateQuery}) => { +export const EntryItem: React.FC = ({entry, setFocusedEntryId, style, updateQuery}) => { + + const [isSelected, setIsSelected] = useState(false); + const classification = getClassification(entry.statusCode) const numberOfRules = entry.rules.numberOfRules let ingoingIcon; @@ -119,7 +121,10 @@ export const EntryItem: React.FC = ({entry, setFocusedEntryId, isSel id={entry.id.toString()} className={`${styles.row} ${isSelected && !rule && !contractEnabled ? styles.rowSelected : additionalRulesProperties}`} - onClick={() => setFocusedEntryId(entry.id.toString())} + onClick={() => { + setIsSelected(!isSelected); + setFocusedEntryId(entry.id.toString()); + }} style={{ border: isSelected ? `1px ${entry.protocol.backgroundColor} solid` : "1px transparent solid", position: "absolute", diff --git a/ui/src/components/TrafficPage.tsx b/ui/src/components/TrafficPage.tsx index fa0a5ef18..51a33d372 100644 --- a/ui/src/components/TrafficPage.tsx +++ b/ui/src/components/TrafficPage.tsx @@ -1,6 +1,7 @@ import React, {useEffect, useRef, useState} from "react"; import {Filters} from "./Filters"; import {EntriesList} from "./EntriesList"; +import {EntryItem} from "./EntryListItem/EntryListItem"; import {makeStyles} from "@material-ui/core"; import "./style/TrafficPage.sass"; import styles from './style/EntriesList.module.sass'; @@ -50,50 +51,58 @@ export const TrafficPage: React.FC = ({setAnalyzeStatus, onTLS const classes = useLayoutStyles(); const [entries, setEntries] = useState([] as any); + const [entriesBuffer, setEntriesBuffer] = useState([] as any); const [focusedEntryId, setFocusedEntryId] = useState(null); const [selectedEntryData, setSelectedEntryData] = useState(null); const [connection, setConnection] = useState(ConnectionStatus.Closed); const [tappingStatus, setTappingStatus] = useState(null); - const [disableScrollList, setDisableScrollList] = useState(false); + const [isSnappedToBottom, setIsSnappedToBottom] = useState(true); - const [query, setQueryDefault] = useState(""); + const [query, setQuery] = useState(""); const [queryBackgroundColor, setQueryBackgroundColor] = useState("#f5f5f5"); + const [addition, updateQuery] = useState(""); const [queriedCurrent, setQueriedCurrent] = useState(0); const [queriedTotal, setQueriedTotal] = useState(0); const [startTime, setStartTime] = useState(0); - const setQuery = async (query) => { - if (!query) { - setQueryBackgroundColor("#f5f5f5") - } else { - const data = await api.validateQuery(query); - if (data.valid) { - setQueryBackgroundColor("#d2fad2") + useEffect(() => { + (async function() { + if (!query) { + setQueryBackgroundColor("#f5f5f5") } else { - setQueryBackgroundColor("#fad6dc") + const data = await api.validateQuery(query); + if (!data) { + return; + } + if (data.valid) { + setQueryBackgroundColor("#d2fad2"); + } else { + setQueryBackgroundColor("#fad6dc"); + } } - } - setQueryDefault(query) - } + })(); + }, [query]); - const updateQuery = (addition) => { + useEffect(() => { if (query) { - setQuery(`${query} and ${addition}`) + setQuery(`${query} and ${addition}`); } else { - setQuery(addition) + setQuery(addition); } - } + // eslint-disable-next-line + }, [addition]); const ws = useRef(null); const listEntry = useRef(null); const openWebSocket = (query) => { - setEntries([]) + setEntries([]); + setEntriesBuffer([]); ws.current = new WebSocket(MizuWebsocketURL); ws.current.onopen = () => { ws.current.send(query) @@ -108,15 +117,18 @@ export const TrafficPage: React.FC = ({setAnalyzeStatus, onTLS const message = JSON.parse(e.data); switch (message.messageType) { case "entry": - const entry = message.data - if (!focusedEntryId) setFocusedEntryId(entry.id.toString()) - let newEntries = [...entries]; - setEntries([...newEntries, entry]) - if(listEntry.current) { - if(isScrollable(listEntry.current.firstChild)) { - setDisableScrollList(true) - } - } + const entry = message.data; + if (!focusedEntryId) setFocusedEntryId(entry.id.toString()); + setEntriesBuffer([ + ...entriesBuffer, + + ]); break case "status": setTappingStatus(message.tappingStatus); @@ -140,8 +152,9 @@ export const TrafficPage: React.FC = ({setAnalyzeStatus, onTLS }); break; case "queryMetadata": - setQueriedCurrent(message.data.current) - setQueriedTotal(message.data.total) + setQueriedCurrent(message.data.current); + setQueriedTotal(message.data.total); + setEntries(entriesBuffer); break; case "startTime": setStartTime(message.data); @@ -209,21 +222,17 @@ export const TrafficPage: React.FC = ({setAnalyzeStatus, onTLS } } - const onScrollEvent = (isAtBottom) => { - isAtBottom ? setDisableScrollList(false) : setDisableScrollList(true) + const onSnapBrokenEvent = () => { + setIsSnappedToBottom(false) } - const isScrollable = (element) => { - return element.scrollHeight > element.clientHeight; - }; - return (
pause play + src={playIcon} onClick={toggleConnection}/>
{getConnectionTitle()}
@@ -243,16 +252,10 @@ export const TrafficPage: React.FC = ({setAnalyzeStatus, onTLS
{ @@ -45,9 +49,25 @@ export default class Api { } validateQuery = async (query) => { + if (this.source) { + this.source.cancel(); + } + this.source = CancelToken.source(); + const form = new FormData(); form.append('query', query) - const response = await this.client.post(`/query/validate`, form); + const response = await this.client.post(`/query/validate`, form, { + cancelToken: this.source.token + }).catch(function (thrown) { + if (!axios.isCancel(thrown)) { + console.error('Validate error', thrown.message); + } + }); + + if (!response) { + return null; + } + return response.data; } }