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  }