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") } }
func (p *Proxy) proxyUrl(target string, w http.ResponseWriter, r *http.Request) { remoteIP := httpd.RemoteHost(r.RemoteAddr) p.remoteProxyUrl(remoteIP, target, w, r) }
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) } } }