mirror of
https://github.com/Li4n0/revsuit.git
synced 2026-09-27 00:51:55 +08:00
feat(recycler): add error cecycler (#10)
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
<!-- rule form-->
|
<!-- rule form-->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
:title="formAction+ ' DNS rule'"
|
:title="formAction+ ' DNS rule'"
|
||||||
:width="460"
|
:width="490"
|
||||||
:visible="formVisible"
|
:visible="formVisible"
|
||||||
:body-style="{ paddingBottom: '80px' }"
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
@close="closeDrawer"
|
@close="closeDrawer"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<!-- rule form-->
|
<!-- rule form-->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
:title="formAction+ ' FTP rule'"
|
:title="formAction+ ' FTP rule'"
|
||||||
:width="460"
|
:width="490"
|
||||||
:visible="formVisible"
|
:visible="formVisible"
|
||||||
:body-style="{ paddingBottom: '80px' }"
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
@close="closeDrawer"
|
@close="closeDrawer"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<!-- rule form-->
|
<!-- rule form-->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
:title="formAction+ ' HTTP rule'"
|
:title="formAction+ ' HTTP rule'"
|
||||||
:width="460"
|
:width="490"
|
||||||
:visible="formVisible"
|
:visible="formVisible"
|
||||||
:body-style="{ paddingBottom: '80px' }"
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
@close="closeDrawer"
|
@close="closeDrawer"
|
||||||
@@ -81,11 +81,28 @@
|
|||||||
<a-icon type="question-circle-o"/>
|
<a-icon type="question-circle-o"/>
|
||||||
</a-tooltip>
|
</a-tooltip>
|
||||||
</span>
|
</span>
|
||||||
|
<a-icon type="fullscreen" class="full-screen-icon" @click="fullScreenTextarea = true"/>
|
||||||
<a-textarea v-model="form.response_body"
|
<a-textarea v-model="form.response_body"
|
||||||
placeholder="Hello RevSuit!"
|
placeholder="Hello RevSuit!"
|
||||||
:readOnly="formReadOnly"
|
:readOnly="formReadOnly"
|
||||||
rows="10"
|
:auto-size="{ minRows: 10, maxRows: 30 }"
|
||||||
/>
|
/>
|
||||||
|
<a-modal
|
||||||
|
:dialog-style="{ top: '40px', bottom: '20px'}"
|
||||||
|
width="80rem"
|
||||||
|
:visible="fullScreenTextarea"
|
||||||
|
title='Response Body'
|
||||||
|
okText=''
|
||||||
|
@ok="fullScreenTextarea=false"
|
||||||
|
@cancel="fullScreenTextarea=false"
|
||||||
|
>
|
||||||
|
<a-textarea v-model="form.response_body"
|
||||||
|
placeholder="Hello RevSuit!"
|
||||||
|
:readOnly="formReadOnly"
|
||||||
|
style="height:100%"
|
||||||
|
:auto-size="{ minRows: fullScreenTextareaMinRows(), maxRows: fullScreenTextareaMinRows()*1.5 }"
|
||||||
|
/>
|
||||||
|
</a-modal>
|
||||||
</a-form-model-item>
|
</a-form-model-item>
|
||||||
</a-col>
|
</a-col>
|
||||||
</a-row>
|
</a-row>
|
||||||
@@ -186,11 +203,6 @@
|
|||||||
</a-table>
|
</a-table>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<style scoped>
|
|
||||||
#add-rule {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import {getHttpRule, upsertHttpRule, deleteHttpRule} from '@/api/rule'
|
import {getHttpRule, upsertHttpRule, deleteHttpRule} from '@/api/rule'
|
||||||
@@ -258,7 +270,6 @@ const columns = [
|
|||||||
const rules = {
|
const rules = {
|
||||||
response_status_code: [{
|
response_status_code: [{
|
||||||
validator: (rule, code, callback) => {
|
validator: (rule, code, callback) => {
|
||||||
console.log(code)
|
|
||||||
if (code === undefined || (!isNaN(code) && 100 < code && code < 600)) {
|
if (code === undefined || (!isNaN(code) && 100 < code && code < 600)) {
|
||||||
return callback()
|
return callback()
|
||||||
} else if (/\${(query|body|header)\..+?}/.test(code)) {
|
} else if (/\${(query|body|header)\..+?}/.test(code)) {
|
||||||
@@ -331,6 +342,7 @@ export default {
|
|||||||
"Access-Control-Max-Age",
|
"Access-Control-Max-Age",
|
||||||
"Access-Control-Allow-Methods",
|
"Access-Control-Allow-Methods",
|
||||||
"Access-Control-Allow-Headers"],
|
"Access-Control-Allow-Headers"],
|
||||||
|
fullScreenTextarea: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -492,6 +504,9 @@ export default {
|
|||||||
handleCancel() {
|
handleCancel() {
|
||||||
this.form = {}
|
this.form = {}
|
||||||
this.closeDrawer()
|
this.closeDrawer()
|
||||||
|
},
|
||||||
|
fullScreenTextareaMinRows() {
|
||||||
|
return (document.body.clientHeight / window.getComputedStyle(document.body)["fontSize"].slice(0, -2)) * 0.5
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -507,3 +522,24 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
#add-rule {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-screen-icon {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 5;
|
||||||
|
color: #9e9e9e;
|
||||||
|
right: 1px;
|
||||||
|
font-size: 1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: font-size 0.1s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.full-screen-icon:hover {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
transition: font-size 0.1s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
<!-- rule form-->
|
<!-- rule form-->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
:title="formAction+ ' MySQL rule'"
|
:title="formAction+ ' MySQL rule'"
|
||||||
:width="460"
|
:width="490"
|
||||||
:visible="formVisible"
|
:visible="formVisible"
|
||||||
:body-style="{ paddingBottom: '80px' }"
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
@close="closeDrawer"
|
@close="closeDrawer"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<!-- rule form-->
|
<!-- rule form-->
|
||||||
<a-drawer
|
<a-drawer
|
||||||
:title="formAction+ ' RMI rule'"
|
:title="formAction+ ' RMI rule'"
|
||||||
:width="460"
|
:width="490"
|
||||||
:visible="formVisible"
|
:visible="formVisible"
|
||||||
:body-style="{ paddingBottom: '80px' }"
|
:body-style="{ paddingBottom: '80px' }"
|
||||||
@close="closeDrawer"
|
@close="closeDrawer"
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func (a *Announcer) AddBot(b Bot) *Announcer {
|
|||||||
func Notice(r record.Record) {
|
func Notice(r record.Record) {
|
||||||
for _, bot := range announcer.Bots {
|
for _, bot := range announcer.Bots {
|
||||||
if err := bot.notice(r); err != nil {
|
if err := bot.notice(r); err != nil {
|
||||||
log.Error(err.Error())
|
log.Warn(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ func init() {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
err := download()
|
err := download()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Download qqwry.dat failed, caused by:%v, recommend to download it by yourself otherwise the `IpArea` will be null", err)
|
log.Warn("Download qqwry.dat failed, caused by:%v, recommend to download it by yourself otherwise the `IpArea` will be null", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if time.Until(info.ModTime()) > 5*24*time.Hour {
|
} else if time.Until(info.ModTime()) > 5*24*time.Hour {
|
||||||
@@ -36,7 +36,7 @@ func GetQQWry() *qqwry.QQwry {
|
|||||||
init := qqwry.DatData.InitDatFile()
|
init := qqwry.DatData.InitDatFile()
|
||||||
if v, ok := init.(error); ok {
|
if v, ok := init.(error); ok {
|
||||||
if v != nil {
|
if v != nil {
|
||||||
log.Error("qqwry init failed")
|
log.Warn("qqwry init failed")
|
||||||
wry = nil
|
wry = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package recycler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"runtime"
|
||||||
|
|
||||||
|
log "unknwon.dev/clog/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
dunno = []byte("???")
|
||||||
|
centerDot = []byte("·")
|
||||||
|
dot = []byte(".")
|
||||||
|
slash = []byte("/")
|
||||||
|
)
|
||||||
|
|
||||||
|
func Recycle(err interface{}) {
|
||||||
|
stack := string(stack(3))
|
||||||
|
log.Error("%v\r\n%v", err, stack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// stack returns a nicely formatted stack frame, skipping skip frames.
|
||||||
|
func stack(skip int) []byte {
|
||||||
|
buf := new(bytes.Buffer) // the returned data
|
||||||
|
// As we loop, we open files and read them. These variables record the currently
|
||||||
|
// loaded file.
|
||||||
|
var lines [][]byte
|
||||||
|
var lastFile string
|
||||||
|
for i := skip; ; i++ { // Skip the expected number of frames
|
||||||
|
pc, file, line, ok := runtime.Caller(i)
|
||||||
|
if !ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Print this much at least. If we can't find the source, it won't show.
|
||||||
|
_, _ = fmt.Fprintf(buf, "%s:%d (0x%x)\n", file, line, pc)
|
||||||
|
if file != lastFile {
|
||||||
|
data, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines = bytes.Split(data, []byte{'\n'})
|
||||||
|
lastFile = file
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(buf, "\t%s: %s\n", function(pc), source(lines, line))
|
||||||
|
}
|
||||||
|
return buf.Bytes()
|
||||||
|
}
|
||||||
|
|
||||||
|
// source returns a space-trimmed slice of the n'th line.
|
||||||
|
func source(lines [][]byte, n int) []byte {
|
||||||
|
n-- // in stack trace, lines are 1-indexed but our array is 0-indexed
|
||||||
|
if n < 0 || n >= len(lines) {
|
||||||
|
return dunno
|
||||||
|
}
|
||||||
|
return bytes.TrimSpace(lines[n])
|
||||||
|
}
|
||||||
|
|
||||||
|
// function returns, if possible, the name of the function containing the PC.
|
||||||
|
func function(pc uintptr) []byte {
|
||||||
|
fn := runtime.FuncForPC(pc)
|
||||||
|
if fn == nil {
|
||||||
|
return dunno
|
||||||
|
}
|
||||||
|
name := []byte(fn.Name())
|
||||||
|
// The name includes the path name to the package, which is unnecessary
|
||||||
|
// since the file name is already included. Plus, it has center dots.
|
||||||
|
// That is, we see
|
||||||
|
// runtime/debug.*T·ptrmethod
|
||||||
|
// and want
|
||||||
|
// *T.ptrmethod
|
||||||
|
// Also the package path might contains dot (e.g. code.google.com/...),
|
||||||
|
// so first eliminate the path prefix
|
||||||
|
if lastSlash := bytes.LastIndex(name, slash); lastSlash >= 0 {
|
||||||
|
name = name[lastSlash+1:]
|
||||||
|
}
|
||||||
|
if period := bytes.Index(name, dot); period >= 0 {
|
||||||
|
name = name[period+1:]
|
||||||
|
}
|
||||||
|
name = bytes.Replace(name, centerDot, dot, -1)
|
||||||
|
return name
|
||||||
|
}
|
||||||
@@ -35,7 +35,7 @@ func (br BaseRule) Match(s string) (flag, flagGroup string, vars map[string]stri
|
|||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
if catcher, err := regexp.Compile(br.FlagFormat); err != nil {
|
if catcher, err := regexp.Compile(br.FlagFormat); err != nil {
|
||||||
log.Error("%s[rule:%s]", err, br.Name)
|
log.Warn("%s[rule:%s]", err, br.Name)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
br.flagCatcher = catcher
|
br.flagCatcher = catcher
|
||||||
|
|||||||
+8
-1
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/newdns"
|
"github.com/li4n0/revsuit/internal/newdns"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/qqwry"
|
||||||
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
"github.com/li4n0/revsuit/internal/rule"
|
"github.com/li4n0/revsuit/internal/rule"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
@@ -52,6 +53,12 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
//create new dns zone with root domain
|
//create new dns zone with root domain
|
||||||
newZone := func(name string) *newdns.Zone {
|
newZone := func(name string) *newdns.Zone {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
recycler.Recycle(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
domain := strings.TrimSuffix(name, ".")
|
domain := strings.TrimSuffix(name, ".")
|
||||||
frags := strings.Split(domain, ".")
|
frags := strings.Split(domain, ".")
|
||||||
zoneName := ""
|
zoneName := ""
|
||||||
@@ -79,7 +86,7 @@ func (s *Server) Run() {
|
|||||||
|
|
||||||
r, err := newRecord(_rule, flag, domain, ip, qqwry.Area(ip))
|
r, err := newRecord(_rule, flag, domain, ip, qqwry.Area(ip))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
|
log.Warn("DNS record(rule_id:%s) created failed :%s", _rule.Name, err)
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
log.Info("DNS record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
log.Info("DNS record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
||||||
|
|||||||
+12
-6
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/qqwry"
|
||||||
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
"github.com/li4n0/revsuit/internal/rule"
|
"github.com/li4n0/revsuit/internal/rule"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
@@ -54,14 +55,19 @@ func (s *Server) updateRules() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleConnection(conn net.Conn) {
|
func (s *Server) handleConnection(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer func() {
|
||||||
|
_ = conn.Close()
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
recycler.Recycle(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
||||||
log.Error("FTP set connection deadline error:%v", err)
|
log.Warn("FTP set connection deadline error:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := conn.Write([]byte("220 (vsFTPd 3.0.2)\r\n")); err != nil {
|
if _, err := conn.Write([]byte("220 (vsFTPd 3.0.2)\r\n")); err != nil {
|
||||||
log.Error("FTP write connection error:%v", err)
|
log.Warn("FTP write connection error:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := strings.Split(conn.RemoteAddr().String(), ":")[0]
|
ip := strings.Split(conn.RemoteAddr().String(), ":")[0]
|
||||||
@@ -158,7 +164,7 @@ loop:
|
|||||||
// create new record
|
// create new record
|
||||||
r, err := NewRecord(_rule, flag, user, password, path, ip, area, status)
|
r, err := NewRecord(_rule, flag, user, password, path, ip, area, status)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("FTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
log.Warn("FTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("FTP record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
log.Info("FTP record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
||||||
@@ -210,7 +216,7 @@ func (s *Server) Run() {
|
|||||||
for {
|
for {
|
||||||
tcpConn, err := listener.Accept()
|
tcpConn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("FTP accept connection error: %v", err)
|
log.Warn("FTP accept connection error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
_ = tcpConn.Close()
|
_ = tcpConn.Close()
|
||||||
@@ -220,7 +226,7 @@ func (s *Server) Run() {
|
|||||||
for {
|
for {
|
||||||
tcpConn, err := listener.Accept()
|
tcpConn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("FTP accept connection error: %v", err)
|
log.Warn("FTP accept connection error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go s.handleConnection(tcpConn)
|
go s.handleConnection(tcpConn)
|
||||||
|
|||||||
+3
-3
@@ -97,7 +97,7 @@ func (s *Server) ConnectionClosed(c *vmysql.Conn) {
|
|||||||
|
|
||||||
cr, ok := s.connRulePool.Load(c.ConnectionID)
|
cr, ok := s.connRulePool.Load(c.ConnectionID)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Error("MySQL Connection rule(%d) not match flag", c.ConnectionID)
|
log.Warn("MySQL Connection rule(%d) not match flag", c.ConnectionID)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ func (s *Server) ConnectionClosed(c *vmysql.Conn) {
|
|||||||
|
|
||||||
r, err := newRecord(_rule, flag, user, clientName, clientOS, ip, qqwry.Area(ip), supportLoadLocalData, files)
|
r, err := newRecord(_rule, flag, user, clientName, clientOS, ip, qqwry.Area(ip), supportLoadLocalData, files)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("MySQL record(rule_id:%s) created failed :%s", _rule.Name, err)
|
log.Warn("MySQL record(rule_id:%s) created failed :%s", _rule.Name, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("MySQL record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
log.Info("MySQL record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
||||||
@@ -275,7 +275,7 @@ func (s *Server) Run() {
|
|||||||
log.Info("Starting MySQL Server at %s", s.Addr)
|
log.Info("Starting MySQL Server at %s", s.Addr)
|
||||||
s.listener, err = vmysql.NewListener("tcp", s.Addr, authServer, s, s.VersionString, 0, 0)
|
s.listener, err = vmysql.NewListener("tcp", s.Addr, authServer, s, s.VersionString, 0, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("New MySQL Server failed: %s", err)
|
log.Warn("New MySQL Server failed: %s", err)
|
||||||
os.Exit(-1)
|
os.Exit(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ var authServers = make(map[string]AuthServer)
|
|||||||
// RegisterAuthServerImpl registers an implementations of AuthServer.
|
// RegisterAuthServerImpl registers an implementations of AuthServer.
|
||||||
func RegisterAuthServerImpl(name string, authServer AuthServer) {
|
func RegisterAuthServerImpl(name string, authServer AuthServer) {
|
||||||
if _, ok := authServers[name]; ok {
|
if _, ok := authServers[name]; ok {
|
||||||
log.Error("AuthServer named %v already exists", name)
|
log.Warn("AuthServer named %v already exists", name)
|
||||||
}
|
}
|
||||||
authServers[name] = authServer
|
authServers[name] = authServer
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -344,7 +344,7 @@ func (c *Conn) readUploadFileEphemeralPacket() []byte {
|
|||||||
|
|
||||||
_, err := io.ReadFull(r, data)
|
_, err := io.ReadFull(r, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error while reading data: %s", err)
|
log.Warn("Error while reading data: %s", err)
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
fileChunkData = append(fileChunkData, data)
|
fileChunkData = append(fileChunkData, data)
|
||||||
@@ -718,7 +718,7 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
// case though, and very unlikely to happen,
|
// case though, and very unlikely to happen,
|
||||||
// and the only downside is we log a bit more then.
|
// and the only downside is we log a bit more then.
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
log.Error("Error reading packet from %s: %v", c, err)
|
log.Warn("Error reading packet from %s: %v", c, err)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -732,7 +732,7 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
c.RecycleReadPacket()
|
c.RecycleReadPacket()
|
||||||
c.SchemaName = db
|
c.SchemaName = db
|
||||||
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
||||||
log.Error("Error writing ComInitDB result to %s: %v", c, err)
|
log.Warn("Error writing ComInitDB result to %s: %v", c, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
case ComQuery:
|
case ComQuery:
|
||||||
@@ -749,10 +749,10 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
if c.Capabilities&CapabilityClientMultiStatements != 0 {
|
if c.Capabilities&CapabilityClientMultiStatements != 0 {
|
||||||
queries, err = sqlparser.SplitStatementToPieces(query)
|
queries, err = sqlparser.SplitStatementToPieces(query)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Conn %v: Error splitting query: %v", c, err)
|
log.Warn("Conn %v: Error splitting query: %v", c, err)
|
||||||
if werr := c.writeErrorPacketFromError(err); werr != nil {
|
if werr := c.writeErrorPacketFromError(err); werr != nil {
|
||||||
// If we can't even write the error, we're done.
|
// If we can't even write the error, we're done.
|
||||||
log.Error("Conn %v: Error writing query error: %v", c, werr)
|
log.Warn("Conn %v: Error writing query error: %v", c, werr)
|
||||||
return werr
|
return werr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -772,7 +772,7 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
timings.Record(queryTimingKey, queryStart)
|
timings.Record(queryTimingKey, queryStart)
|
||||||
|
|
||||||
if err := c.flush(); err != nil {
|
if err := c.flush(); err != nil {
|
||||||
log.Error("Conn %v: Flush() failed: %v", c.ID(), err)
|
log.Warn("Conn %v: Flush() failed: %v", c.ID(), err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,12 +781,12 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
// Return error if listener was shut down and OK otherwise
|
// Return error if listener was shut down and OK otherwise
|
||||||
if c.listener.isShutdown() {
|
if c.listener.isShutdown() {
|
||||||
if err := c.writeErrorPacket(ERServerShutdown, SSServerShutdown, "Server shutdown in progress"); err != nil {
|
if err := c.writeErrorPacket(ERServerShutdown, SSServerShutdown, "Server shutdown in progress"); err != nil {
|
||||||
log.Error("Error writing ComPing error to %s: %v", c, err)
|
log.Warn("Error writing ComPing error to %s: %v", c, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
||||||
log.Error("Error writing ComPing result to %s: %v", c, err)
|
log.Warn("Error writing ComPing result to %s: %v", c, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -800,28 +800,28 @@ func (c *Conn) handleNextCommand(handler Handler) error {
|
|||||||
case 1:
|
case 1:
|
||||||
c.Capabilities &^= CapabilityClientMultiStatements
|
c.Capabilities &^= CapabilityClientMultiStatements
|
||||||
default:
|
default:
|
||||||
log.Error("Got unhandled packet (ComSetOption default) from client %v, returning error: %v", c.ConnectionID, data)
|
log.Warn("Got unhandled packet (ComSetOption default) from client %v, returning error: %v", c.ConnectionID, data)
|
||||||
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil {
|
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil {
|
||||||
log.Error("Error writing error packet to client: %v", err)
|
log.Warn("Error writing error packet to client: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := c.writeEndResult(false, 0, 0, 0); err != nil {
|
if err := c.writeEndResult(false, 0, 0, 0); err != nil {
|
||||||
log.Error("Error writeEndResult error %v ", err)
|
log.Warn("Error writeEndResult error %v ", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.Error("Got unhandled packet (ComSetOption else) from client %v, returning error: %v", c.ConnectionID, data)
|
log.Warn("Got unhandled packet (ComSetOption else) from client %v, returning error: %v", c.ConnectionID, data)
|
||||||
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil {
|
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "error handling packet: %v", data); err != nil {
|
||||||
log.Error("Error writing error packet to client: %v", err)
|
log.Warn("Error writing error packet to client: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
log.Error("Got unhandled packet (default) from %s, returning error: %v", c, data)
|
log.Warn("Got unhandled packet (default) from %s, returning error: %v", c, data)
|
||||||
c.RecycleReadPacket()
|
c.RecycleReadPacket()
|
||||||
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "command handling not implemented yet: %v", data[0]); err != nil {
|
if err := c.writeErrorPacket(ERUnknownComError, SSUnknownComError, "command handling not implemented yet: %v", data[0]); err != nil {
|
||||||
log.Error("Error writing error packet to %s: %s", c, err)
|
log.Warn("Error writing error packet to %s: %s", c, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -872,7 +872,7 @@ func (c *Conn) execQuery(query string, handler Handler, more bool) error {
|
|||||||
// was a read operation.
|
// was a read operation.
|
||||||
if !sendFinished {
|
if !sendFinished {
|
||||||
if err := c.writeEndResult(more, 0, 0, handler.WarningCount(c)); err != nil {
|
if err := c.writeEndResult(more, 0, 0, handler.WarningCount(c)); err != nil {
|
||||||
log.Error("Error writing result to %s: %v", c, err)
|
log.Warn("Error writing result to %s: %v", c, err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-10
@@ -23,6 +23,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
"vitess.io/vitess/go/netutil"
|
"vitess.io/vitess/go/netutil"
|
||||||
"vitess.io/vitess/go/sqltypes"
|
"vitess.io/vitess/go/sqltypes"
|
||||||
@@ -222,6 +223,11 @@ func (l *Listener) Addr() net.Addr {
|
|||||||
|
|
||||||
// Accept runs an accept loop until the listener is closed.
|
// Accept runs an accept loop until the listener is closed.
|
||||||
func (l *Listener) Accept() {
|
func (l *Listener) Accept() {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
recycler.Recycle(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
for {
|
for {
|
||||||
conn, err := l.listener.Accept()
|
conn, err := l.listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -253,7 +259,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
// Catch panics, and close the connection in any case.
|
// Catch panics, and close the connection in any case.
|
||||||
defer func() {
|
defer func() {
|
||||||
if x := recover(); x != nil {
|
if x := recover(); x != nil {
|
||||||
log.Error("mysql_server caught panic:\n%v\n%s", x, tb.Stack(4))
|
log.Warn("mysql_server caught panic:\n%v\n%s", x, tb.Stack(4))
|
||||||
}
|
}
|
||||||
// We call flush here in case there's a premature return after
|
// We call flush here in case there's a premature return after
|
||||||
// startWriterBuffering is called
|
// startWriterBuffering is called
|
||||||
@@ -269,7 +275,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
salt, err := c.writeHandshakeV10(l.ServerVersion, l.authServer, l.TLSConfig != nil)
|
salt, err := c.writeHandshakeV10(l.ServerVersion, l.authServer, l.TLSConfig != nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
log.Error("Cannot send HandshakeV10 packet to %s: %v", c, err)
|
log.Warn("Cannot send HandshakeV10 packet to %s: %v", c, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -280,13 +286,13 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
// Don't log EOF errors. They cause too much spam, same as main read loop.
|
// Don't log EOF errors. They cause too much spam, same as main read loop.
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
log.Error("Cannot read client handshake response from %s: %v", c, err)
|
log.Warn("Cannot read client handshake response from %s: %v", c, err)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
user, authMethod, authResponse, err := l.parseClientHandshakePacket(c, true, response)
|
user, authMethod, authResponse, err := l.parseClientHandshakePacket(c, true, response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Cannot parse client handshake response from %s: %v", c, err)
|
log.Warn("Cannot parse client handshake response from %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -299,14 +305,14 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
// SSL was enabled. We need to re-read the auth packet.
|
// SSL was enabled. We need to re-read the auth packet.
|
||||||
response, err = c.readEphemeralPacket()
|
response, err = c.readEphemeralPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Cannot read post-SSL client handshake response from %s: %v", c, err)
|
log.Warn("Cannot read post-SSL client handshake response from %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns copies of the data, so we can recycle the buffer.
|
// Returns copies of the data, so we can recycle the buffer.
|
||||||
user, authMethod, authResponse, err = l.parseClientHandshakePacket(c, false, response)
|
user, authMethod, authResponse, err = l.parseClientHandshakePacket(c, false, response)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Cannot parse post-SSL client handshake response from %s: %v", c, err)
|
log.Warn("Cannot parse post-SSL client handshake response from %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.RecycleReadPacket()
|
c.RecycleReadPacket()
|
||||||
@@ -360,13 +366,13 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
data := make([]byte, 21) //nolint:ineffassign,staticcheck // SA4006 This line is required because the binary protocol requires padding with 0
|
data := make([]byte, 21) //nolint:ineffassign,staticcheck // SA4006 This line is required because the binary protocol requires padding with 0
|
||||||
data = append(salt, byte(0x00))
|
data = append(salt, byte(0x00))
|
||||||
if err := c.writeAuthSwitchRequest(MysqlNativePassword, data); err != nil {
|
if err := c.writeAuthSwitchRequest(MysqlNativePassword, data); err != nil {
|
||||||
log.Error("Error writing auth switch packet for %s: %v", c, err)
|
log.Warn("Error writing auth switch packet for %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := c.readEphemeralPacket()
|
response, err := c.readEphemeralPacket()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Error reading auth switch response for %s: %v", c, err)
|
log.Warn("Error reading auth switch response for %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.RecycleReadPacket()
|
c.RecycleReadPacket()
|
||||||
@@ -396,7 +402,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
data = authServerDialogSwitchData()
|
data = authServerDialogSwitchData()
|
||||||
}
|
}
|
||||||
if err := c.writeAuthSwitchRequest(authServerMethod, data); err != nil {
|
if err := c.writeAuthSwitchRequest(authServerMethod, data); err != nil {
|
||||||
log.Error("Error writing auth switch packet for %s: %v", c, err)
|
log.Warn("Error writing auth switch packet for %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,7 +424,7 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti
|
|||||||
|
|
||||||
// Negotiation worked, send OK packet.
|
// Negotiation worked, send OK packet.
|
||||||
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
if err := c.writeOKPacket(0, 0, c.StatusFlags, 0); err != nil {
|
||||||
log.Error("Cannot write OK packet to %s: %v", c, err)
|
log.Warn("Cannot write OK packet to %s: %v", c, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -88,7 +88,7 @@ func (s *Server) updateRules() error {
|
|||||||
|
|
||||||
func (s *Server) Run() {
|
func (s *Server) Run() {
|
||||||
if err := s.updateRules(); err != nil {
|
if err := s.updateRules(); err != nil {
|
||||||
log.Error(err.Error())
|
log.Warn(err.Error())
|
||||||
}
|
}
|
||||||
log.Info("Starting HTTP Server at %s, token:%s", s.Addr, s.Token)
|
log.Info("Starting HTTP Server at %s, token:%s", s.Addr, s.Token)
|
||||||
err := s.Router.Run(s.Addr)
|
err := s.Router.Run(s.Addr)
|
||||||
@@ -152,7 +152,7 @@ func (s *Server) Receive(c *gin.Context) {
|
|||||||
// create new record
|
// create new record
|
||||||
r, err := NewRecord(_rule, flag, c.Request.Method, u, ip, area, string(raw))
|
r, err := NewRecord(_rule, flag, c.Request.Method, u, ip, area, string(raw))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("HTTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
log.Warn("HTTP record[rule_id:%d] created failed :%s", _rule.ID, err)
|
||||||
code, err := strconv.Atoi(compileTpl(c, _rule.ResponseStatusCode, vars))
|
code, err := strconv.Atoi(compileTpl(c, _rule.ResponseStatusCode, vars))
|
||||||
if err != nil || code < 100 || code > 600 {
|
if err != nil || code < 100 || code > 600 {
|
||||||
code = 400
|
code = 400
|
||||||
|
|||||||
+13
-7
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/li4n0/revsuit/internal/database"
|
"github.com/li4n0/revsuit/internal/database"
|
||||||
"github.com/li4n0/revsuit/internal/qqwry"
|
"github.com/li4n0/revsuit/internal/qqwry"
|
||||||
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,10 +47,15 @@ func (s *Server) updateRules() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) handleConnection(conn net.Conn) {
|
func (s *Server) handleConnection(conn net.Conn) {
|
||||||
defer conn.Close()
|
defer func() {
|
||||||
|
_ = conn.Close()
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
recycler.Recycle(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
if err := conn.SetDeadline(time.Now().Add(time.Second * 30)); err != nil {
|
||||||
log.Error("RMI set connection deadline error:%v", err)
|
log.Warn("RMI set connection deadline error:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
ip, port, _ := net.SplitHostPort(conn.RemoteAddr().String())
|
||||||
@@ -57,7 +63,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
buf := make([]byte, 1024)
|
buf := make([]byte, 1024)
|
||||||
_, err := conn.Read(buf)
|
_, err := conn.Read(buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RMI read connection error:%v", err)
|
log.Warn("RMI read connection error:%v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bytes.Contains(buf, []byte{0x4a, 0x52, 0x4d, 0x49}) {
|
if !bytes.Contains(buf, []byte{0x4a, 0x52, 0x4d, 0x49}) {
|
||||||
@@ -77,7 +83,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
|
|
||||||
_, err = conn.Write(send)
|
_, err = conn.Write(send)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RMI write connection error: %v", err)
|
log.Warn("RMI write connection error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := make([]byte, 512)
|
data := make([]byte, 512)
|
||||||
@@ -85,7 +91,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
for length := 0; length < 50; {
|
for length := 0; length < 50; {
|
||||||
n, err := conn.Read(data)
|
n, err := conn.Read(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RMI read connection error: %v", err)
|
log.Warn("RMI read connection error: %v", err)
|
||||||
}
|
}
|
||||||
length += n
|
length += n
|
||||||
}
|
}
|
||||||
@@ -104,7 +110,7 @@ func (s *Server) handleConnection(conn net.Conn) {
|
|||||||
// create new record
|
// create new record
|
||||||
r, err := NewRecord(_rule, flag, path, ip, area)
|
r, err := NewRecord(_rule, flag, path, ip, area)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RMI record[rule_id:%d] created failed :%s", _rule.ID, err)
|
log.Warn("RMI record[rule_id:%d] created failed :%s", _rule.ID, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Info("RMI record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
log.Info("RMI record[id:%d rule:%s remote_ip:%s] has been created", r.ID, _rule.Name, ip)
|
||||||
@@ -149,7 +155,7 @@ func (s *Server) Run() {
|
|||||||
for {
|
for {
|
||||||
tcpConn, err := listener.Accept()
|
tcpConn, err := listener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RMI accept connection error: %v", err)
|
log.Warn("RMI accept connection error: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go s.handleConnection(tcpConn)
|
go s.handleConnection(tcpConn)
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/li4n0/revsuit/internal/record"
|
"github.com/li4n0/revsuit/internal/record"
|
||||||
|
"github.com/li4n0/revsuit/internal/recycler"
|
||||||
log "unknwon.dev/clog/v2"
|
log "unknwon.dev/clog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,3 +40,48 @@ func events(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
log.Info(c.Request.RemoteAddr, "disconnect")
|
log.Info(c.Request.RemoteAddr, "disconnect")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func recovery(c *gin.Context) {
|
||||||
|
timeFormat := func(t time.Time) string {
|
||||||
|
var timeString = t.Format("2006/01/02 - 15:04:05")
|
||||||
|
return timeString
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
// Check for a broken connection, as it is not really a
|
||||||
|
// condition that warrants a panic stack trace.
|
||||||
|
var brokenPipe bool
|
||||||
|
if ne, ok := err.(*net.OpError); ok {
|
||||||
|
if se, ok := ne.Err.(*os.SyscallError); ok {
|
||||||
|
if strings.Contains(strings.ToLower(se.Error()), "broken pipe") || strings.Contains(strings.ToLower(se.Error()), "connection reset by peer") {
|
||||||
|
brokenPipe = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
httpRequest, _ := httputil.DumpRequest(c.Request, false)
|
||||||
|
headers := strings.Split(string(httpRequest), "\r\n")
|
||||||
|
for idx, header := range headers {
|
||||||
|
current := strings.Split(header, ":")
|
||||||
|
if current[0] == "Authorization" {
|
||||||
|
headers[idx] = current[0] + ": *"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if brokenPipe {
|
||||||
|
recycler.Recycle(fmt.Sprintf("%s\n%s", err, string(httpRequest)))
|
||||||
|
} else if gin.IsDebugging() {
|
||||||
|
recycler.Recycle(fmt.Sprintf("[Recovery] %s panic recovered:\n%s\n%s\n", timeFormat(time.Now()), strings.Join(headers, "\r\n"), err))
|
||||||
|
} else {
|
||||||
|
recycler.Recycle(fmt.Sprintf("[Recovery] %s panic recovered:\n%s\n", timeFormat(time.Now()), err))
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the connection is dead, we can't write a status to it.
|
||||||
|
if brokenPipe {
|
||||||
|
_ = c.Error(err.(error)) // nolint: errcheck
|
||||||
|
c.Abort()
|
||||||
|
} else {
|
||||||
|
c.AbortWithStatus(http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (revsuit *Revsuit) registerRouter() {
|
func (revsuit *Revsuit) registerRouter() {
|
||||||
revsuit.http.Router = gin.Default()
|
|
||||||
if revsuit.logLevel != log.LevelTrace {
|
|
||||||
revsuit.http.Router = gin.New()
|
revsuit.http.Router = gin.New()
|
||||||
revsuit.http.Router.Use(gin.Recovery())
|
revsuit.http.Router.Use(recovery)
|
||||||
|
if revsuit.logLevel == log.LevelTrace {
|
||||||
|
revsuit.http.Router.Use(gin.Logger())
|
||||||
}
|
}
|
||||||
|
|
||||||
revsuit.registerPlatformRouter()
|
revsuit.registerPlatformRouter()
|
||||||
|
|||||||
Reference in New Issue
Block a user