/
qproxy.go
171 lines (149 loc) · 4.15 KB
/
qproxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
/*************************************************************************
> File Name: proxy.go
> Author: b0lu
> Mail: b0lu_xyz@163.com
> Created Time: 2016年01月13日 星期三 13时51分30秒
************************************************************************/
package main
import (
"flag"
"fmt"
"io"
"log"
"net/http"
"net/http/httputil"
"os"
"regexp"
"strings"
"github.com/Unknwon/goconfig"
"github.com/elazarl/goproxy"
)
var (
p = fmt.Println
pf = fmt.Printf
fpf = fmt.Fprintf
debug = new(bool)
)
func isFileExiste(filename string) bool {
_, err := os.Stat(filename)
return !(err != nil && os.IsNotExist(err))
}
func check(err error) {
if err != nil {
panic(err)
}
}
func Q_Stdout(req *http.Request) {
p("\n---------------------start---------------------------")
request_str, err := httputil.DumpRequest(req, false)
check(err)
p("URL==>", req.URL)
p("HOST==>", req.Host)
p("REQUESTURI==>", req.RequestURI)
p("PATH==>", req.URL.Path)
p("RAWQUERY==>", req.URL.RawQuery)
p("\n---------------------------ALL REQUESTS INFO------------------------------")
p(string(request_str))
p("---------------------------ALL REQUESTS INFO------------------------------\n")
p("---------------------end---------------------------\n")
}
func Q_log(req *http.Request, w io.Writer) {
request_str, err := httputil.DumpRequest(req, false)
check(err)
w.Write(request_str)
}
type HttpHandle struct {
req chan *http.Request
errch chan error
}
func NewHttpHandle() (*HttpHandle, error) {
httpHandler := &HttpHandle{make(chan *http.Request), make(chan error)}
var (
f *os.File
logfile string
err error
)
logfile = "qproxylog"
if isFileExiste(logfile) {
f, err = os.OpenFile(logfile, os.O_RDWR|os.O_APPEND, 0777)
check(err)
} else {
f, err = os.Create(logfile)
check(err)
}
go func() {
for m := range httpHandler.req {
if *debug {
Q_Stdout(m)
}
Q_log(m, f)
}
httpHandler.errch <- f.Close()
}()
return httpHandler, nil
}
func (httpHandler *HttpHandle) PutRequest(req *http.Request) {
httpHandler.req <- req
}
func (httpHandler *HttpHandle) Close() error {
close(httpHandler.req)
return <-httpHandler.errch
}
func main() {
verbose := flag.Bool("v", false, "proxy log info to stdout")
addr := flag.String("l", ":9010", "proxy listen addr")
debug = flag.Bool("d", false, "open the debug mode")
//fmt.Printf("v1 type :%s\n", reflect.TypeOf(debug))
flag.Usage = func() {
p("================By b0lu===============")
p("usage: " + string(os.Args[0]) + " -v -l :9010 -d")
p("-d open then debug mode")
p("-v open proxy log info to stdout")
p("-l set the proxy listen addr and port. default: -l :9010")
p("\nPS: proxy will log requests info into qproxylog file")
}
flag.Parse()
defer func() {
if err := recover(); err != nil {
p(err)
}
}()
p("================By b0lu===============")
p("Load config.ini to init allowHostsRule and staticResourcesRules")
cfg, err := goconfig.LoadConfigFile("config.ini")
if err != nil {
log.Println("读取配置文件失败[config.ini]")
return
}
allowHostsRule, err := cfg.GetValue(goconfig.DEFAULT_SECTION, "allowHostsRule")
check(err)
p("allowHostsRule==>", allowHostsRule)
allowRules := make([]*regexp.Regexp, 0)
for _, hostRule := range strings.Split(allowHostsRule, ",") {
allowRules = append(allowRules, regexp.MustCompile(hostRule))
}
p(allowRules)
staticResources, err := cfg.GetValue(goconfig.DEFAULT_SECTION, "staticResources")
check(err)
p("staticResources==>", staticResources)
staticResourcesRules := regexp.MustCompile(staticResources)
p(staticResourcesRules)
httpHandler, err := NewHttpHandle()
check(err)
proxy := goproxy.NewProxyHttpServer()
proxy.Verbose = *verbose
/*
if err := os.MkdirAll("proxydump", 0755); err != nil {
log.Fatal("Cant create dir", err)
}
*/
proxy.OnRequest(goproxy.ReqHostMatches(allowRules...)).
DoFunc(func(req *http.Request, ctx *goproxy.ProxyCtx) (*http.Request, *http.Response) {
if !staticResourcesRules.MatchString(req.URL.Path) {
httpHandler.PutRequest(req)
}
return req, nil
})
p("----------------------Proxy Start------------------------")
http.ListenAndServe(*addr, proxy)
}