Пример #1
0
func (p *Proxy) OnRequest(
	w http.ResponseWriter,
	r *http.Request) {
	targetHost := httpd.RemoteHost(r.Host)
	remoteIP := httpd.RemoteHost(r.RemoteAddr)
	urlPath := r.URL.Path
	//fmt.Printf("host: %s/%s, remote: %s/%s, url: %s\n", targetHost, r.Host, remoteIP, r.RemoteAddr, urlPath)
	if strings.HasPrefix(urlPath, "http://") {
		p.proxyUrl(urlPath, w, r)
	} else if targetHost == "i.me" {
		p.initDevice(w, remoteIP)
	} else if !p.isSelfAddr(targetHost) && !p.isSelfAddr(remoteIP) {
		target := "http://" + r.Host + urlPath
		p.proxyUrl(target, w, r)
	} else if _, m := httpd.MatchPath(urlPath, "/post"); m {
		p.postTest(w, r)
	} else if page, m := httpd.MatchPath(urlPath, "/test/"); m {
		if page == "" {
			page = "localhost"
		}

		target := "http://" + page[1:]
		p.testUrl(target, w, r)
	} else if page, m := httpd.MatchPath(urlPath, "/to/"); m {
		target := "http://" + page[1:]
		p.proxyUrl(target, w, r)
	} else if _, m := httpd.MatchPath(urlPath, "/usage"); m {
		p.WriteUsage(w)
	} else if page, m := httpd.MatchPath(urlPath, "/profile"); m {
		p.ownProfile(remoteIP, page, w, r)
	} else if page, m := httpd.MatchPath(urlPath, "/dns"); m {
		if !p.disableDNS {
			p.dns(page, w, r)
		} else {
			fmt.Fprintln(w, "DNS is disabled")
		}
	} else if _, m := httpd.MatchPath(urlPath, "/res"); m {
		p.res(w, r, urlPath)
	} else if urlPath == "/" {
		p.index(w, p.ver)
	} else if urlPath == "/devices" {
		p.devices(w)
	} else if urlPath == "/about" {
		scheme := r.URL.Scheme
		if scheme == "" {
			scheme = "http"
		}

		fmt.Fprintf(w, "url%%v: %v\n", r.URL)
		fmt.Fprintln(w, "url.String(): "+r.URL.String())
		fmt.Fprintln(w)

		ex := ""
		if len(r.URL.RawQuery) > 0 {
			ex += "?" + r.URL.RawQuery
		}

		fmt.Fprintln(w, "url: "+r.Method+" "+scheme+"://"+r.Host+urlPath+ex)
		fmt.Fprintln(w, "remote: "+r.RemoteAddr)
		fmt.Fprintln(w, "requestURI: "+r.RequestURI)
		fmt.Fprintln(w, "host: "+r.Host)

		fmt.Fprintln(w)
		for k, v := range r.Header {
			fmt.Fprintln(w, "header: "+k+": "+strings.Join(v, "|"))
		}

		fmt.Fprintln(w)
		for _, s := range r.TransferEncoding {
			fmt.Fprintln(w, "transferEncoding: "+s)
		}

		fmt.Fprintln(w, "")
		fmt.Fprintln(w, "visit http://"+p.mainHost+"/about to get info")
		fmt.Fprintln(w, "visit http://"+p.mainHost+"/test/"+p.mainHost+"/about to test the proxy of http://"+p.mainHost+"/about")
		fmt.Fprintln(w, "visit http://"+p.mainHost+"/to/"+p.mainHost+"/about to purely proxy of http://"+p.mainHost+"/about")
		fmt.Fprintln(w, "")
		fmt.Fprintln(w, "visit http://"+p.mainHost+"/test/"+p.mainHost+"/test/"+p.mainHost+"/about to test the proxy")
	} else if urlPath == "/urlencoded" {
		p.urlEncoded(w)
	} else {
		fmt.Fprintln(w, "visit http://"+r.Host+"/about to get info")
	}
}
Пример #2
0
func (p *Proxy) proxyUrl(target string, w http.ResponseWriter, r *http.Request) {
	remoteIP := httpd.RemoteHost(r.RemoteAddr)
	p.remoteProxyUrl(remoteIP, target, w, r)
}
Пример #3
0
func (p *Proxy) proxyUrl(target string, w http.ResponseWriter, r *http.Request) {
	//fmt.Println("proxy: " + target)
	remoteIP := httpd.RemoteHost(r.RemoteAddr)
	needCache := false

	fullUrl := target
	if len(r.URL.RawQuery) > 0 {
		fullUrl += "?" + r.URL.RawQuery
	}

	requestUrl := fullUrl
	requestR := r
	contentSource := ""

	prof := p.profileOp.Open(remoteIP)

	rangeInfo := cache.CheckRange(r)
	f := p.lives.Open(remoteIP)
	var u *life.UrlState
	if f != nil {
		u = f.OpenUrl(fullUrl)
	}

	if p.urlOp != nil {
		delay := p.urlOp.Delay(remoteIP, fullUrl)
		//fmt.Println("url delay: " + delay.String())
		switch delay.Act {
		case profile.DelayActDelayEach:
			if delay.Time > 0 {
				// TODO: create request before sleep, more effective
				time.Sleep(delay.RandDuration(p.r))
			}
			break
		case profile.DelayActDropUntil:
			if u != nil && u.DropUntil(delay.RandDuration(p.r)) {
				// TODO: more safe method, maybe net.http.Hijacker
				panic("")
			}
			break
		case profile.DelayActTimeout:
			if delay.Time > 0 {
				// TODO: more safe method, maybe net.http.Hijacker
				time.Sleep(delay.RandDuration(p.r))
				panic("")
			}
			break
		}

		act := p.urlOp.Action(remoteIP, fullUrl)
		//fmt.Println("url act: " + act.String())
		switch act.Act {
		case profile.UrlActCache:
			needCache = true
		case profile.UrlActStatus:
			if c, err := strconv.Atoi(act.ContentValue); err == nil {
				w.WriteHeader(c)
			} else {
				w.WriteHeader(502)
			}
			return
		case profile.UrlActMap:
			requestUrl = act.ContentValue
			requestR = nil
			contentSource = "map " + act.ContentValue
		case profile.UrlActRedirect:
			http.Redirect(w, r, act.ContentValue, 302)
			return
		case profile.UrlActRewritten:
			fallthrough
		case profile.UrlActRestore:
			if p.rewriteUrl(fullUrl, w, r, rangeInfo, prof, f, act) {
				return
			}
		}
	}

	if needCache && r.Method == "GET" && f != nil {
		c := f.CheckCache(fullUrl, rangeInfo)
		if c != nil && c.Error == nil {
			c.Response(w)
			return
		}
	}

	httpStart := time.Now()
	resp, postBody, err := net.NewHttp(requestUrl, requestR, p.parseDomainAsDial(target, remoteIP))
	if err != nil {
		c := cache.NewUrlCache(fullUrl, r, nil, nil, contentSource, nil, rangeInfo, httpStart, time.Now(), err)
		if f != nil {
			go p.saveContentToCache(fullUrl, f, c, false)
		}

		http.Error(w, "Bad Gateway", 502)
	} else {
		defer resp.Close()
		content, err := resp.ProxyReturn(w)
		httpEnd := time.Now()
		c := cache.NewUrlCache(fullUrl, r, postBody, resp, contentSource, content, rangeInfo, httpStart, httpEnd, err)
		if f != nil {
			go p.saveContentToCache(fullUrl, f, c, needCache)
		}
	}
}