github.com/pbberlin/tools@v0.0.0-20160910141205-7aa5421c2169/net/http/domclean2/08_proxify.go (about) 1 package domclean2 2 3 import ( 4 "fmt" 5 "net/url" 6 "strings" 7 8 "github.com/pbberlin/tools/appengine/util_appengine" 9 "github.com/pbberlin/tools/net/http/dom" 10 "github.com/pbberlin/tools/net/http/fetch" 11 "github.com/pbberlin/tools/net/http/routes" 12 "golang.org/x/net/html" 13 ) 14 15 type FuncType2 func(*html.Node) 16 17 const emptySrc = "//:0" 18 19 // r is the request to the proxy 20 // u is the url, that the proxy has called 21 func closuredProxifier(argProxyHostPort string, urlSrc *url.URL) FuncType2 { 22 23 // needed to get the current request into the 24 // "static" recursive functions 25 var closProxyHostPort = argProxyHostPort // port included! 26 27 var closRemoteHost = fetch.HostFromUrl(urlSrc) 28 // log.Printf("ProxyHost %v, RemoteHost %v (%s)", closProxyHostPort, closRemoteHost, urlSrc) 29 30 // -------------------------- 31 // ---------------------- 32 33 var fRecurse FuncType2 34 fRecurse = func(n *html.Node) { 35 36 switch { 37 case n.Type == html.ElementNode && n.Data == "form": 38 hidFld := dom.Nd("input") 39 hidFld.Attr = []html.Attribute{ 40 html.Attribute{Key: "name", Val: "redirect-to"}, 41 html.Attribute{Key: "value", Val: attrX(n.Attr, "action")}, 42 } 43 n.AppendChild(hidFld) 44 45 submt := dom.Nd("input") 46 submt.Attr = []html.Attribute{ 47 html.Attribute{Key: "type", Val: "submit"}, 48 html.Attribute{Key: "value", Val: "subm"}, 49 html.Attribute{Key: "accesskey", Val: "f"}, 50 } 51 n.AppendChild(submt) 52 53 n.Attr = attrSet(n.Attr, "method", "post") 54 n.Attr = attrSet(n.Attr, "was", "rewritten") 55 56 n.Attr = attrsAbsoluteAndProxified(n.Attr, closProxyHostPort, closRemoteHost) 57 58 case n.Type == html.ElementNode && (n.Data == "a" || n.Data == "img"): 59 60 if n.Data == "a" || n.Data == "img" { 61 attrStore := attrsAbsoluteAndProxified(n.Attr, closProxyHostPort, closRemoteHost) 62 n.Attr = attrStore 63 } 64 65 default: 66 } 67 68 for c := n.FirstChild; c != nil; c = c.NextSibling { 69 fRecurse(c) 70 } 71 } 72 73 return fRecurse 74 75 } 76 77 func absolutize(scheme, host, val string) (ret string) { 78 if strings.HasPrefix(val, "/") && !strings.HasPrefix(val, "//ssl.") { 79 ret = fmt.Sprintf("%v://%v%v", scheme, host, val) 80 // log.Printf("absolutized %v %v - %v", val, host, ret) 81 } else { 82 ret = val 83 } 84 return 85 } 86 87 func attrsAbsoluteAndProxified(attributes []html.Attribute, proxyHostPort, remoteHost string) []html.Attribute { 88 89 rew := make([]html.Attribute, 0, len(attributes)) 90 91 for i := 0; i < len(attributes); i++ { 92 93 attr := attributes[i] 94 95 // Make all absolute 96 if attr.Key == "href" || attr.Key == "src" || attr.Key == "action" { // make absolute 97 98 if attrX(attributes, "cfrom") == "img" { 99 attr.Val = absolutize("http", remoteHost, attr.Val) 100 } else { 101 attr.Val = absolutize("https", remoteHost, attr.Val) 102 } 103 104 } 105 106 if attr.Key == "href" { 107 108 if attrX(attributes, "cfrom") == "img" { 109 // dont proxify image links, except they are relative 110 // we already absolutized them above 111 112 } else { 113 // proxify - v1 114 // no rewrite to https-posted-form; urls remain visible 115 if true { 116 // only proxy 117 attr.Val = fmt.Sprintf("%v?%v=%v", routes.ProxifyURI, routes.URLParamKey, attr.Val) 118 } else { 119 // dedup 120 attr.Val = fmt.Sprintf("%v?%v=%v", routes.DedupURI, routes.URLParamKey, attr.Val) 121 } 122 123 if util_appengine.IsLocalEnviron() { 124 attr.Val = fmt.Sprintf("http://%v%v", proxyHostPort, attr.Val) 125 } else { 126 attr.Val = fmt.Sprintf("https://%v%v", proxyHostPort, attr.Val) 127 } 128 } 129 130 } 131 132 if attr.Key == "action" { 133 134 // proxify - v2 135 136 // Since we appended a form field, we do not need: 137 // action = spf("/blob2/form-redirector?redirect-to=%v", action) 138 if util_appengine.IsLocalEnviron() { 139 attr.Val = fmt.Sprintf("http://%v%v", proxyHostPort, routes.FormRedirector) 140 } else { 141 attr.Val = fmt.Sprintf("https://%v%v", proxyHostPort, routes.FormRedirector) 142 } 143 144 } 145 146 rew = append(rew, attr) 147 } 148 149 // 150 // 151 // We instrumented all forms with a field "redirect-to" 152 // Now we have to make the value of this field absolute 153 isRedirectInput := false 154 for _, attr := range rew { 155 if attr.Key == "name" && attr.Val == "redirect-to" { 156 isRedirectInput = true 157 } 158 } 159 if isRedirectInput { 160 for _, attr := range rew { 161 if attr.Key == "value" { 162 attr.Val = absolutize("https", remoteHost, attr.Val) 163 } 164 } 165 } 166 167 return rew 168 } 169 170 func proxify(n *html.Node, ProxyHostPort string, urlRemoteSrc *url.URL) { 171 fRecurser := closuredProxifier(ProxyHostPort, urlRemoteSrc) 172 fRecurser(n) 173 }