Skip to content

Instantly share code, notes, and snippets.

@FlyingFish07
Created September 29, 2018 15:59
Show Gist options
  • Save FlyingFish07/4eb0fc4efb31cfe23255f2ad78129922 to your computer and use it in GitHub Desktop.
Save FlyingFish07/4eb0fc4efb31cfe23255f2ad78129922 to your computer and use it in GitHub Desktop.
hrcproxy,简单的可修改http返回内容的反向代理
package main
import (
"bufio"
"bytes"
"flag"
"fmt"
"io/ioutil"
"log"
"net/http"
"net/http/httputil"
"net/url"
"os"
"strconv"
"strings"
)
type proxyConfig struct {
TargetHost string
TargetUrl string
SourceStr string
DestinationStr string
}
var listenIpPort string
var backendServer string
var configMap = make(map[string][]proxyConfig)
type transport struct {
http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
resp, err = t.RoundTripper.RoundTrip(req)
if err != nil {
return nil, err
}
thisUrl := req.URL.Path
thisHost := req.Host
// log.Println("Input request :[HOST]" + thisHost + "[URL]" + thisUrl)
if v, ok := configMap[(thisHost + "|@|" + thisUrl)]; ok {
log.Println("Start Processing...")
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return nil, err
}
err = resp.Body.Close()
if err != nil {
return nil, err
}
for i := 0; i < len(v); i++ {
var config proxyConfig = v[i]
b = bytes.Replace(b, []byte(config.SourceStr), []byte(config.DestinationStr), -1)
}
body := ioutil.NopCloser(bytes.NewReader(b))
resp.Body = body
resp.ContentLength = int64(len(b))
resp.Header.Set("Content-Length", strconv.Itoa(len(b)))
log.Println("Process end...")
}
return resp, nil
}
func main() {
// Override the default usage
flag.Usage = GoproxyUsage
handleArgs()
target, _ := url.Parse("http://" + backendServer)
proxy := httputil.NewSingleHostReverseProxy(target)
// proxy.ModifyResponse = rewriteBody
proxy.Transport = &transport{http.DefaultTransport}
http.Handle("/", proxy)
log.Fatal(http.ListenAndServe(listenIpPort, nil))
}
func handleArgs() {
configFileNamePoint := flag.String("f", "hrcproxy.conf", "config file")
listenIpPortPoint := flag.String("l", "localhost:9090", "server listen port")
backendServerPoint := flag.String("s", "", "backend server ip and port")
flag.Parse()
configFileName := *configFileNamePoint
listenIpPort, backendServer = *listenIpPortPoint, *backendServerPoint
if configFileName == "" || listenIpPort == "" || backendServer == "" {
fmt.Println("\nPlease Input enough infos!\n")
flag.Usage()
os.Exit(1)
}
readConfigFile(configFileName)
}
func readConfigFile(configFileName string) {
file, err := os.Open(configFileName)
if err != nil {
log.Fatal(err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
for scanner.Scan() {
var line = strings.TrimSpace(scanner.Text())
//跳过空行和注释行
if line != "" || line[0] != '#' {
var parts = strings.Split(line, "|@|")
//仅处理4个参数的,否则报错
if len(parts) != 4 {
log.Fatal("config error : " + line)
}
var config proxyConfig
config.TargetHost = parts[0]
config.TargetUrl = parts[1]
config.SourceStr = parts[2]
config.DestinationStr = parts[3]
var key = config.TargetHost + "|@|" + config.TargetUrl
configMap[key] = append(configMap[key], config)
}
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}
func GoproxyUsage() {
fmt.Fprintf(os.Stderr, "Usage: ./hrcproxy -l=0.0.0.0:9090 -s=xx.xx.xx.xx:80 -f=my.conf\n\n")
flag.PrintDefaults()
}
#目标的域名|@|目标url|@|要替换的源字符串|@|目标字符串
test.dev.com|@|/online/main|@|192.168.1.26:8008|@|out.test.site
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment