mirror of
https://github.com/TeaOSLab/EdgeAdmin.git
synced 2025-11-27 22:00:24 +08:00
实现点击访问日志显示详情窗口
This commit is contained in:
@@ -15,6 +15,7 @@ func init() {
|
|||||||
GetPost("", new(IndexAction)).
|
GetPost("", new(IndexAction)).
|
||||||
GetPost("/today", new(TodayAction)).
|
GetPost("/today", new(TodayAction)).
|
||||||
GetPost("/history", new(HistoryAction)).
|
GetPost("/history", new(HistoryAction)).
|
||||||
|
Get("/viewPopup", new(ViewPopupAction)).
|
||||||
EndAll()
|
EndAll()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
86
internal/web/actions/default/servers/server/log/viewPopup.go
Normal file
86
internal/web/actions/default/servers/server/log/viewPopup.go
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/TeaOSLab/EdgeAdmin/internal/web/actions/actionutils"
|
||||||
|
"github.com/TeaOSLab/EdgeCommon/pkg/rpc/pb"
|
||||||
|
"github.com/iwind/TeaGo/maps"
|
||||||
|
"net/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ViewPopupAction struct {
|
||||||
|
actionutils.ParentAction
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ViewPopupAction) Init() {
|
||||||
|
this.Nav("", "", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (this *ViewPopupAction) RunGet(params struct {
|
||||||
|
RequestId string
|
||||||
|
}) {
|
||||||
|
accessLogResp, err := this.RPC().HTTPAccessLogRPC().FindHTTPAccessLog(this.AdminContext(), &pb.FindHTTPAccessLogRequest{RequestId: params.RequestId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
accessLog := accessLogResp.AccessLog
|
||||||
|
if accessLog == nil {
|
||||||
|
this.WriteString("not found: " + params.RequestId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 状态
|
||||||
|
if len(accessLog.StatusMessage) == 0 {
|
||||||
|
accessLog.StatusMessage = http.StatusText(int(accessLog.Status))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Data["accessLog"] = accessLog
|
||||||
|
|
||||||
|
// WAF相关
|
||||||
|
var wafMap maps.Map = nil
|
||||||
|
if accessLog.FirewallPolicyId > 0 {
|
||||||
|
policyResp, err := this.RPC().HTTPFirewallPolicyRPC().FindEnabledFirewallPolicy(this.AdminContext(), &pb.FindEnabledFirewallPolicyRequest{FirewallPolicyId: accessLog.FirewallPolicyId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if policyResp.FirewallPolicy != nil {
|
||||||
|
wafMap = maps.Map{
|
||||||
|
"policy": maps.Map{
|
||||||
|
"id": policyResp.FirewallPolicy.Id,
|
||||||
|
"name": policyResp.FirewallPolicy.Name,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
if accessLog.FirewallRuleGroupId > 0 {
|
||||||
|
groupResp, err := this.RPC().HTTPFirewallRuleGroupRPC().FindEnabledHTTPFirewallRuleGroup(this.AdminContext(), &pb.FindEnabledHTTPFirewallRuleGroupRequest{FirewallRuleGroupId: accessLog.FirewallRuleGroupId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if groupResp.FirewallRuleGroup != nil {
|
||||||
|
wafMap["group"] = maps.Map{
|
||||||
|
"id": groupResp.FirewallRuleGroup.Id,
|
||||||
|
"name": groupResp.FirewallRuleGroup.Name,
|
||||||
|
}
|
||||||
|
|
||||||
|
if accessLog.FirewallRuleSetId > 0 {
|
||||||
|
setResp, err := this.RPC().HTTPFirewallRuleSetRPC().FindEnabledHTTPFirewallRuleSet(this.AdminContext(), &pb.FindEnabledHTTPFirewallRuleSetRequest{FirewallRuleSetId: accessLog.FirewallRuleSetId})
|
||||||
|
if err != nil {
|
||||||
|
this.ErrorPage(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if setResp.FirewallRuleSet != nil {
|
||||||
|
wafMap["set"] = maps.Map{
|
||||||
|
"id": setResp.FirewallRuleSet.Id,
|
||||||
|
"name": setResp.FirewallRuleSet.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.Data["wafInfo"] = wafMap
|
||||||
|
|
||||||
|
this.Show()
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@ func (this *HTTPFirewallRuleGroupDAO) FindRuleGroupConfig(ctx context.Context, g
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
groupResp, err := client.HTTPFirewallRuleGroupRPC().FindHTTPFirewallRuleGroupConfig(ctx, &pb.FindHTTPFirewallRuleGroupConfigRequest{FirewallRuleGroupId: groupId})
|
groupResp, err := client.HTTPFirewallRuleGroupRPC().FindEnabledHTTPFirewallRuleGroupConfig(ctx, &pb.FindEnabledHTTPFirewallRuleGroupConfigRequest{FirewallRuleGroupId: groupId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ func (this *HTTPFirewallRuleSetDAO) FindRuleSetConfig(ctx context.Context, setId
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
resp, err := client.HTTPFirewallRuleSetRPC().FindHTTPFirewallRuleSetConfig(ctx, &pb.FindHTTPFirewallRuleSetConfigRequest{FirewallRuleSetId: setId})
|
resp, err := client.HTTPFirewallRuleSetRPC().FindEnabledHTTPFirewallRuleSetConfig(ctx, &pb.FindEnabledHTTPFirewallRuleSetConfigRequest{FirewallRuleSetId: setId})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,9 +14,33 @@ Vue.component("http-access-log-box", {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return pieces[0] + "." + pieces[1].substr(0, 3);
|
return pieces[0] + "." + pieces[1].substr(0, 3);
|
||||||
|
},
|
||||||
|
showLog: function () {
|
||||||
|
let that = this
|
||||||
|
let requestId = this.accessLog.requestId
|
||||||
|
this.$parent.$children.forEach(function (v) {
|
||||||
|
if (v.deselect != null) {
|
||||||
|
v.deselect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.select()
|
||||||
|
teaweb.popup("/servers/server/log/viewPopup?requestId=" + requestId, {
|
||||||
|
width: "50em",
|
||||||
|
height: "24em",
|
||||||
|
onClose: function () {
|
||||||
|
that.deselect()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
select: function () {
|
||||||
|
this.$refs.box.parentNode.style.cssText = "background: rgba(0, 0, 0, 0.1)"
|
||||||
|
},
|
||||||
|
deselect: function () {
|
||||||
|
this.$refs.box.parentNode.style.cssText = ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
template: `<div :style="{'color': (accessLog.status >= 400) ? '#dc143c' : ''}">
|
template: `<div :style="{'color': (accessLog.status >= 400) ? '#dc143c' : ''}" ref="box">
|
||||||
{{accessLog.remoteAddr}} [{{accessLog.timeLocal}}] <em>"{{accessLog.requestMethod}} {{accessLog.scheme}}://{{accessLog.host}}{{accessLog.requestURI}} <a :href="accessLog.scheme + '://' + accessLog.host + accessLog.requestURI" target="_blank" title="新窗口打开" class="disabled"><i class="external icon tiny"></i> </a> {{accessLog.proto}}" </em> {{accessLog.status}} <span v-if="accessLog.attrs != null && accessLog.attrs['cache_cached'] == '1'">[cached]</span> <span v-if="accessLog.attrs != null && accessLog.attrs['waf.action'] != null && accessLog.attrs['waf.action'].length > 0">[waf {{accessLog.attrs['waf.action']}}]</span> - 耗时:{{formatCost(accessLog.requestTime)}} ms
|
{{accessLog.remoteAddr}} [{{accessLog.timeLocal}}] <em>"{{accessLog.requestMethod}} {{accessLog.scheme}}://{{accessLog.host}}{{accessLog.requestURI}} <a :href="accessLog.scheme + '://' + accessLog.host + accessLog.requestURI" target="_blank" title="新窗口打开" class="disabled"><i class="external icon tiny"></i> </a> {{accessLog.proto}}" </em> {{accessLog.status}} <span v-if="accessLog.attrs != null && accessLog.attrs['cache_cached'] == '1'">[cached]</span> <span v-if="accessLog.attrs != null && accessLog.attrs['waf.action'] != null && accessLog.attrs['waf.action'].length > 0">[waf {{accessLog.attrs['waf.action']}}]</span> - 耗时:{{formatCost(accessLog.requestTime)}} ms
|
||||||
|
<a href="" @click.prevent="showLog" title="查看详情"><i class="icon expand"></i></a>
|
||||||
</div>`
|
</div>`
|
||||||
})
|
})
|
||||||
@@ -118,7 +118,12 @@ window.teaweb = {
|
|||||||
padding: "0.5em",
|
padding: "0.5em",
|
||||||
showConfirmButton: false,
|
showConfirmButton: false,
|
||||||
showCloseButton: true,
|
showCloseButton: true,
|
||||||
focusConfirm: false
|
focusConfirm: false,
|
||||||
|
onClose: function (popup) {
|
||||||
|
if (typeof (options["onClose"]) == "function") {
|
||||||
|
options["onClose"].apply(Tea.Vue, arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
popupFinish: function () {
|
popupFinish: function () {
|
||||||
|
|||||||
4
web/views/@default/servers/server/log/viewPopup.css
Normal file
4
web/views/@default/servers/server/log/viewPopup.css
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
table td {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
|
/*# sourceMappingURL=viewPopup.css.map */
|
||||||
1
web/views/@default/servers/server/log/viewPopup.css.map
Normal file
1
web/views/@default/servers/server/log/viewPopup.css.map
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"version":3,"sources":["viewPopup.less"],"names":[],"mappings":"AAAA,KAAM;EACL,qBAAA","file":"viewPopup.css"}
|
||||||
116
web/views/@default/servers/server/log/viewPopup.html
Normal file
116
web/views/@default/servers/server/log/viewPopup.html
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
{$layout "layout_popup"}
|
||||||
|
|
||||||
|
<div class="ui menu tabular tiny">
|
||||||
|
<a class="item" :class="{active: tab == 'summary'}" @click.prevent="switchTab('summary')">综合信息</a>
|
||||||
|
<a class="item" :class="{active: tab == 'response'}" @click.prevent="switchTab('response')">响应数据(Response)</a>
|
||||||
|
<a class="item" :class="{active: tab == 'request'}" @click.prevent="switchTab('request')">请求数据(Request)</a>
|
||||||
|
<a class="item" :class="{active: tab == 'cookie'}" @click.prevent="switchTab('cookie')">Cookie</a>
|
||||||
|
<a class="item" :class="{active: tab == 'client'}" @click.prevent="switchTab('client')">终端信息</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="tab == 'summary'">
|
||||||
|
<table class="ui table selectable small">
|
||||||
|
<tr>
|
||||||
|
<td style="width: 50%">请求概要(Request):{{accessLog.request}}</td>
|
||||||
|
<td>请求URI(RequestURI):{{accessLog.requestURI}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>请求方法(RequestMethod):{{accessLog.requestMethod}}</td>
|
||||||
|
<td>主机地址(Host):{{accessLog.host}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>请求来源(Referer):
|
||||||
|
<span v-if="accessLog.referer != null && accessLog.referer.length > 0">{{accessLog.referer}}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</td>
|
||||||
|
<td>终端地址(RemoteAddr:RemotePort):{{accessLog.remoteAddr}}:{{accessLog.remotePort}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>终端信息(UserAgent):
|
||||||
|
<span v-if="accessLog.userAgent != null && accessLog.userAgent.length > 0">{{accessLog.userAgent}}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</td>
|
||||||
|
<td>协议(Proto):{{accessLog.proto}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>状态(StatusMessage):<span :class="{red:accessLog.status>=400, green:accessLog.status<400}">{{accessLog.status}} {{accessLog.statusMessage}}</span></td>
|
||||||
|
<td>文件类型(ContentType):
|
||||||
|
<span v-if="accessLog.contentType != null && accessLog.contentType.length > 0">{{accessLog.contentType}}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>发送字节(BytesSent):{{accessLog.bytesSent}}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ISO8601时间:{{accessLog.timeISO8601}}</td>
|
||||||
|
<td>本地时间(TimeLocal):{{accessLog.timeLocal}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="wafInfo != null">
|
||||||
|
<td class="color-border">WAF策略:{{wafInfo.policy.name}}</td>
|
||||||
|
<td>WAF规则分组:
|
||||||
|
<span v-if="wafInfo.group != null">{{wafInfo.group.name}}</span>
|
||||||
|
<span v-else>-</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="wafInfo != null && wafInfo.set != null">
|
||||||
|
<td class="color-border">WAF规则集:{{wafInfo.set.name}}</td>
|
||||||
|
<td></td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="accessLog.errors != null && accessLog.errors.length > 0">
|
||||||
|
<td colspan="2">
|
||||||
|
<div v-for="error in accessLog.errors">
|
||||||
|
<span class="red">{{error}}</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="tab == 'response'">
|
||||||
|
<table class="ui table selectable small">
|
||||||
|
<tr>
|
||||||
|
<td class="title">Status</td>
|
||||||
|
<td>{{accessLog.status}} {{accessLog.statusMessage}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr v-if="accessLog.sentHeader != null" v-for="(v, k) in accessLog.sentHeader">
|
||||||
|
<td>{{k}}</td>
|
||||||
|
<td>{{v.values[0]}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="tab == 'request'">
|
||||||
|
<table class="ui table selectable small">
|
||||||
|
<tr v-if="accessLog.header != null" v-for="(v, k) in accessLog.header">
|
||||||
|
<td class="title">{{k}}</td>
|
||||||
|
<td>{{v.values[0]}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="tab == 'cookie'">
|
||||||
|
<div v-if="accessLog.cookie == null">暂时没有Cookie数据。</div>
|
||||||
|
<div v-else>
|
||||||
|
<table class="ui table selectable small">
|
||||||
|
<tr v-for="(v, k) in accessLog.cookie">
|
||||||
|
<td class="title">{{k}}</td>
|
||||||
|
<td>{{v}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="tab == 'client'">
|
||||||
|
<table class="ui table selectable small">
|
||||||
|
<tr>
|
||||||
|
<td class="title">综合信息(UserAgent)</td>
|
||||||
|
<td>{{accessLog.userAgent}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>IP</td>
|
||||||
|
<td>{{accessLog.remoteAddr}}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
7
web/views/@default/servers/server/log/viewPopup.js
Normal file
7
web/views/@default/servers/server/log/viewPopup.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Tea.context(function () {
|
||||||
|
this.tab = "summary"
|
||||||
|
|
||||||
|
this.switchTab = function (tab) {
|
||||||
|
this.tab = tab
|
||||||
|
}
|
||||||
|
})
|
||||||
3
web/views/@default/servers/server/log/viewPopup.less
Normal file
3
web/views/@default/servers/server/log/viewPopup.less
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
table td {
|
||||||
|
word-break: break-all;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user