github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgNet/kmgHttp/proxy.go (about)

     1  package kmgHttp
     2  
     3  import (
     4  	"net/http"
     5  	"net/url"
     6  	"strings"
     7  )
     8  
     9  // url明文反向代理.
    10  // uri表示,以此uri作为前缀可以进入这个地方,此处代理不会修改用户的uri
    11  // 例如: 注册 AddUriProxyToDefaultServer("/data/upload/","http://b.com/")
    12  // 用户访问 http://xxx.com/data/upload/745dfc0e7d24b9232a0226116e115967.jpg 此处会去访问 http://b.com/data/upload/745dfc0e7d24b9232a0226116e115967.jpg
    13  func AddUriProxyToDefaultServer(uri, targetUrl string) {
    14  	http.DefaultServeMux.HandleFunc(uri, func(w http.ResponseWriter, req *http.Request) {
    15  		proxyReq := MustHttpRequestClone(req)
    16  		target, err := url.Parse(targetUrl)
    17  		if err != nil {
    18  			panic(err)
    19  		}
    20  		proxyReq.Host = target.Host
    21  		proxyReq.URL.Host = target.Host
    22  		proxyReq.URL.Scheme = target.Scheme
    23  		err = HttpProxyToWriter(w, proxyReq)
    24  		if err != nil {
    25  			panic(err)
    26  		}
    27  	})
    28  }
    29  
    30  // url明文反向代理.
    31  // uri 是否以/开头和结束无所谓, targetUrl 是否以/结束无所谓.
    32  // uri表示,以此path作为前缀可以进入这个地方,此处代理可能会修改请求的path
    33  // 例如: 注册 MustAddUriProxyRefToUriToDefaultServer("/data/upload/","http://b.com/")
    34  // 用户访问 http://xxx.com/data/upload/745dfc0e7d24b9232a0226116e115967.jpg 此处会去访问 http://b.com/745dfc0e7d24b9232a0226116e115967.jpg
    35  func MustAddUriProxyRefToUriToDefaultServer(uri, targetUrl string) {
    36  	uri = "/" + strings.Trim(uri, "/")
    37  	targetUrlObj, err := url.Parse(targetUrl)
    38  	if err != nil {
    39  		panic(err)
    40  	}
    41  	handler := func(w http.ResponseWriter, req *http.Request) {
    42  		proxyReq := MustHttpRequestClone(req)
    43  		proxyReq.Host = targetUrlObj.Host
    44  		proxyReq.URL.Host = targetUrlObj.Host
    45  		proxyReq.URL.Scheme = targetUrlObj.Scheme
    46  		// uri指向单个文件特殊情况 ("/favicon.ico","http://b.com/favicon.ico"
    47  		refPath := strings.TrimPrefix(strings.TrimPrefix(req.URL.Path, uri), "/")
    48  		if refPath == "" {
    49  			proxyReq.URL.Path = strings.TrimSuffix(targetUrlObj.Path, "/")
    50  		} else {
    51  			proxyReq.URL.Path = strings.TrimSuffix(targetUrlObj.Path, "/") + "/" + refPath // 发起请求的时候使用的是 proxyReq.URL.Path 不使用 proxyReq.RequestURI
    52  		}
    53  		proxyReq.URL, err = url.Parse(proxyReq.URL.String())
    54  		if err != nil {
    55  			panic(err)
    56  		}
    57  		proxyReq.RequestURI = proxyReq.URL.RequestURI()
    58  		err = HttpProxyToWriter(w, proxyReq)
    59  		if err != nil {
    60  			panic(err)
    61  		}
    62  	}
    63  	// 目录
    64  	http.DefaultServeMux.HandleFunc(uri+"/", handler)
    65  	// 单文件,由于无法区分是单文件还是目录,只能注册2遍.
    66  	http.DefaultServeMux.HandleFunc(uri, handler)
    67  }