├── .gitignore ├── README.md └── proxy.go /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gin Reverse Proxy Middleware 2 | 3 | proxy different domain request to different host through specified proxy rules
4 | no need nginx just go 5 | 6 | ## usage 7 | 8 | ``` 9 | 10 | import proxy "github.com/chenhg5/gin-reverseproxy" 11 | 12 | router.Use(proxy.ReverseProxy(map[string] string { 13 | "www.xyz.com" : "localhost:4001", 14 | "www.abc.com" : "localhost:4003", 15 | })) 16 | 17 | 18 | ``` 19 | 20 | 21 | ## todo 22 | 23 | - [ ] Load balance 24 | - [ ] Error handle 25 | - [ ] specified route -------------------------------------------------------------------------------- /proxy.go: -------------------------------------------------------------------------------- 1 | package gin_reverseproxy 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "github.com/gin-gonic/gin" 7 | "io/ioutil" 8 | "log" 9 | "net/http" 10 | ) 11 | 12 | func ReverseProxy(domains map[string]string) gin.HandlerFunc { 13 | return func(c *gin.Context) { 14 | log.Println("host: " + c.Request.Host) 15 | if c.Request.Host != "localhost:4000" { 16 | log.Println("continue for next") 17 | c.Next() 18 | } 19 | 20 | // we need to buffer the body if we want to read it here and send it 21 | // in the request. 22 | body, err := ioutil.ReadAll(c.Request.Body) 23 | if err != nil { 24 | http.Error(c.Writer, err.Error(), http.StatusInternalServerError) 25 | return 26 | } 27 | 28 | // you can reassign the body if you need to parse it as multipart 29 | c.Request.Body = ioutil.NopCloser(bytes.NewReader(body)) 30 | 31 | // create a new url from the raw RequestURI sent by the client 32 | url := fmt.Sprintf("%s://%s%s", "http", domains[c.Request.Host], c.Request.RequestURI) 33 | 34 | proxyReq, err := http.NewRequest(c.Request.Method, url, bytes.NewReader(body)) 35 | 36 | // We may want to filter some headers, otherwise we could just use a shallow copy 37 | // proxyReq.Header = c.Request.Header 38 | proxyReq.Header = make(http.Header) 39 | for h, val := range c.Request.Header { 40 | proxyReq.Header[h] = val 41 | } 42 | 43 | client := &http.Client{} 44 | resp, err := client.Do(proxyReq) 45 | if err != nil { 46 | http.Error(c.Writer, err.Error(), http.StatusBadGateway) 47 | return 48 | } 49 | defer resp.Body.Close() 50 | bodyContent, _ := ioutil.ReadAll(resp.Body) 51 | c.Writer.Write(bodyContent) 52 | for h, val := range resp.Header { 53 | c.Writer.Header()[h] = val 54 | } 55 | c.Abort() 56 | } 57 | } 58 | --------------------------------------------------------------------------------