Page Menu
Home
Sealhub
Search
Configure Global Search
Log In
Files
F10352665
trafficLog.tsx
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
5 KB
Referenced Files
None
Subscribers
None
trafficLog.tsx
View Options
import
{
Entry
,
Har
,
PostData
,
Request
,
Response
}
from
"har-format"
;
import
{
render
,
Component
}
from
"preact"
;
type
MyState
=
{
finished_entries
:
Entry
[];
unfinished_entries
:
Map
<
string
,
Entry
>
;
};
class
TrafficLog
extends
Component
{
connection
:
WebSocket
|
undefined
;
state
:
MyState
=
{
finished_entries
:
[],
unfinished_entries
:
new
Map
()
};
constructor
()
{
super
();
}
componentDidMount
()
{
// This should also be dynamic
this
.
connection
=
new
WebSocket
(
"ws://localhost:10001"
);
this
.
connection
.
onmessage
=
(
msg
)
=>
{
this
.
process_msg
(
msg
.
data
);
this
.
setState
({
finished_entries
:
this
.
state
.
finished_entries
,
unfinished_entries
:
this
.
state
.
unfinished_entries
,
});
};
this
.
connection
.
onclose
=
this
.
connection
.
onerror
=
()
=>
{
window
.
location
.
reload
();
};
}
render
()
{
const
download_har
=
()
=>
{
var
tempLink
=
document
.
createElement
(
"a"
);
var
taBlob
=
new
Blob
([
JSON
.
stringify
(
this
.
export_har
())],
{
type
:
"text/plain"
,
});
tempLink
.
setAttribute
(
"href"
,
URL
.
createObjectURL
(
taBlob
));
tempLink
.
setAttribute
(
"download"
,
`rentgendroid-capture.har`
);
tempLink
.
click
();
URL
.
revokeObjectURL
(
tempLink
.
href
);
};
const
inspect_har
=
async
()
=>
{
const
req_body
=
{
har
:
this
.
export_har
(),
private_data
:
[
[
"adid"
,
document
.
getElementById
(
"adid_priv_info_table"
)
!
.
textContent
,
],
[
"latitude"
,
document
.
getElementById
(
"lat_priv_info_table"
)
!
.
textContent
,
],
[
"longitude"
,
document
.
getElementById
(
"lon_priv_info_table"
)
!
.
textContent
,
],
],
};
const
resp
=
await
fetch
(
"/inspect_har"
,
{
method
:
"POST"
,
body
:
JSON
.
stringify
(
req_body
),
});
const
resp_text
=
await
resp
.
text
();
const
newWindow
=
window
.
open
();
newWindow
?
.
document
.
write
(
resp_text
);
newWindow
?
.
document
.
close
();
};
const
contentWithLineBreaks
=
this
.
state
.
finished_entries
.
map
((
req
)
=>
{
return
(
<
span
>
{
req
.
request
.
url
}
<
br
/>
<
/span>
);
});
return
(
<
div
>
<
button
onClick
=
{
download_har
}
>
Download
HAR
<
/button>
<
button
onClick
=
{
inspect_har
}
>
Inspect
HAR
<
/button>
<
div
>
<
h2
>
stats
:
<
/h2>
<
p
>
Request
+
responce
pairs
:
{
" "
}
{
this
.
state
.
finished_entries
.
length
}
<
/p>
<
p
>
Waiting
for
the
responce
:
{
" "
}
{
this
.
state
.
unfinished_entries
.
size
}
<
/p>
<
/div>
<
div
>
{
contentWithLineBreaks
}
<
/div>
<
/div>
);
}
process_msg
(
s
:
string
)
{
let
obj
=
JSON
.
parse
(
s
);
console
.
log
(
obj
);
if
(
obj
.
type
!==
"data"
)
return
;
if
(
obj
.
payload
&&
obj
.
payload
.
data
&&
obj
.
payload
.
data
.
requestReceived
)
this
.
process_req
(
obj
.
payload
.
data
.
requestReceived
);
if
(
obj
.
payload
&&
obj
.
payload
.
data
&&
obj
.
payload
.
data
.
responseCompleted
)
this
.
process_res
(
obj
.
payload
.
data
.
responseCompleted
);
}
process_res
(
res
:
any
)
{
let
entry
=
this
.
state
.
unfinished_entries
.
get
(
res
.
id
)
!
;
let
content_type
=
"application/text"
;
let
headers
=
JSON
.
parse
(
res
.
rawHeaders
).
map
(
(
header
:
[
string
,
string
])
=>
{
if
(
header
[
0
].
toLowerCase
()
===
"content-type"
)
content_type
=
header
[
1
];
return
{
name
:
header
[
0
],
value
:
header
[
1
],
comment
:
""
};
}
);
//'{"startTime":1751745139334,
// "startTimestamp":347666.762487,
// "bodyReceivedTimestamp":347667.529477,
// "headersSentTimestamp":347906.038202,
// "responseSentTimestamp":347906.616067}'
let
timing_events
=
JSON
.
parse
(
res
.
timingEvents
);
let
start_ts
=
timing_events
.
startTimestamp
;
let
got_headers_ts
=
timing_events
.
headersSentTimestamp
;
let
end_ts
=
timing_events
.
responseSentTimestamp
;
let
wait_time
=
got_headers_ts
-
start_ts
;
let
recieve_time
=
end_ts
-
got_headers_ts
;
let
response
:
Response
=
{
status
:
res
.
statusCode
,
statusText
:
res
.
statusMessage
,
httpVersion
:
entry
.
request
.
httpVersion
,
cookies
:
[],
headers
,
content
:
{
size
:
0
,
mimeType
:
content_type
,
text
:
res
.
body
,
encoding
:
"base64"
,
},
redirectURL
:
""
,
headersSize
:
-
1
,
bodySize
:
-
1
,
};
entry
.
response
=
response
;
entry
.
timings
.
wait
=
wait_time
;
entry
.
timings
.
receive
=
recieve_time
;
this
.
state
.
unfinished_entries
.
delete
(
res
.
id
);
this
.
state
.
finished_entries
.
push
(
entry
);
}
process_req
(
req
:
any
)
{
let
content_type
=
"application/text"
;
let
headers
=
JSON
.
parse
(
req
.
rawHeaders
).
map
(
(
header
:
[
string
,
string
])
=>
{
if
(
header
[
0
].
toLowerCase
()
===
"Content-Type"
)
content_type
=
header
[
1
];
return
{
name
:
header
[
0
],
value
:
header
[
1
],
comment
:
""
};
}
);
let
timing_events
=
JSON
.
parse
(
req
.
timingEvents
);
let
start_time
:
number
=
timing_events
.
startTime
!
;
let
start_datetime
=
new
Date
(
start_time
).
toISOString
();
let
request
:
Request
=
{
method
:
req
.
method
,
url
:
req
.
url
,
httpVersion
:
req
.
httpVersion
,
cookies
:
[],
headers
,
queryString
:
[],
postData
:
req
.
body
?
({
text
:
req
.
body
,
mimeType
:
content_type
}
as
PostData
)
:
undefined
,
headersSize
:
-
1
,
bodySize
:
-
1
,
comment
:
""
,
};
//'{"startTime":1751745139334,"startTimestamp":347666.762487,"bodyReceivedTimestamp":347667.529477,"headersSentTimestamp":347906.038202,"responseSentTimestamp":347906.616067}'
let
entry
:
Entry
=
{
startedDateTime
:
start_datetime
,
time
:
0
,
request
:
request
,
response
:
{
status
:
0
,
statusText
:
""
,
httpVersion
:
""
,
cookies
:
[],
headers
:
[],
content
:
{
size
:
0
,
mimeType
:
""
,
},
redirectURL
:
""
,
headersSize
:
0
,
bodySize
:
0
,
},
cache
:
{},
timings
:
{
wait
:
0
,
receive
:
0
,
},
};
this
.
state
.
unfinished_entries
.
set
(
req
.
id
,
entry
);
}
export_har
()
:
Har
{
let
ret
:
Har
=
{
log
:
{
version
:
"1.2"
,
creator
:
{
name
:
"Rentgendroid"
,
version
:
"0.0.1"
,
},
entries
:
[
...
this
.
state
.
finished_entries
,
...
this
.
state
.
unfinished_entries
.
values
(),
],
},
};
return
ret
;
}
}
render
(
<
TrafficLog
/>
,
document
.
getElementById
(
"traffic-log"
)
!
);
File Metadata
Details
Attached
Mime Type
text/x-java
Expires
Sun, Nov 2, 17:52 (1 d, 8 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1030476
Default Alt Text
trafficLog.tsx (5 KB)
Attached To
Mode
R134 rentgen-android
Attached
Detach File
Event Timeline
Log In to Comment