示例#1
0
// Create a new client for making http requests against a Jazz server with the provided credentials
// The client will execute the requests authenticating somewhat transparently when needed
func NewClient(userID string, password string) (*Client, error) {
	jClient := &Client{}

	jClient.userID = userID
	jClient.password = password

	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}
	jar, err := cookiejar.New(&options)
	if err != nil {
		return nil, err
	}
	client := http.Client{Jar: jar}

	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
	}
	client.Transport = tr
	client.CheckRedirect = nil

	jClient.httpClient = &client

	// Provide a no-op logger as the default
	jClient.Log = log.New(ioutil.Discard, "", log.LstdFlags)

	return jClient, nil
}
示例#2
0
func addRedirectFunctionality(client *http.Client, ro *RequestOptions) {
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		if ro.RedirectLimit == 0 {
			ro.RedirectLimit = RedirectLimit
		}

		if len(via) >= ro.RedirectLimit {
			return ErrRedirectLimitExceeded
		}

		if ro.SensitiveHTTPHeaders == nil {
			ro.SensitiveHTTPHeaders = SensitiveHTTPHeaders
		}

		for k, vv := range via[0].Header {
			// Is this a sensitive header?
			if _, found := ro.SensitiveHTTPHeaders[k]; found && !ro.RedirectLocationTrusted {
				continue
			}

			for _, v := range vv {
				req.Header.Add(k, v)
			}
		}

		return nil
	}
}
示例#3
0
/*-------------------------------------------------------------------------------*/
func TestCallbackError(t *testing.T) {
	port := 8202

	//create controller for all mocks
	ctrl := gomock.NewController(t)
	//check mocks at end
	defer ctrl.Finish()

	//key values
	loser := "you are a loser"
	state := "jabba da hut/:)" //make sure we are decoding correctly by adding strange chars

	pageMapper := NewSimplePageMapper(three, "notused", "notused")
	cookieMapper := NewMockCookieMapper(ctrl)
	serveMux, authConn := createDispatcherWithMocks(ctrl, pageMapper, cookieMapper, nil)
	go func() {
		http.ListenAndServe(fmt.Sprintf(":%d", port), serveMux)
	}()

	//don't care about the cookie name
	cookieMapper.EXPECT().CookieName().Return("my_chef").AnyTimes()

	//just to get the constants
	authConn.EXPECT().ErrorValueName().Return("error")
	authConn.EXPECT().CodeValueName().Return("code")
	authConn.EXPECT().ClientTokenValueName().Return("dontbotherimnotgoingtousethisanyway")

	// this is what happens when google refuses
	v := url.Values{
		//no code!
		"state": []string{state},
		"error": []string{loser},
	}

	returnURLHost := fmt.Sprintf("localhost:%d", port)
	returnURL, err := url.Parse(fmt.Sprintf("http://%s%s?%s", returnURLHost, returl, v.Encode()))
	if err != nil {
		t.Fatalf("Can't understand url: %s", err)
	}

	client := new(http.Client)
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		checkRedirValues(t, "error from goog", via, map[string][]string{
			"path":       []string{req.URL.Path, three},
			"host":       []string{req.URL.Host, returnURLHost},
			"state":      []string{req.URL.Query().Get("state"), ""},
			"error":      []string{req.URL.Query().Get("error"), loser},
			"service":    []string{req.URL.Query().Get("service"), "google"},
			"via url[0]": []string{via[0].URL.String(), returnURL.String()},
		})
		return stopProcessing
	}
	resp := createReqAndDo(t, client, returnURL.String(), nil)
	for k, v := range resp.Header {
		if k == "Set-Cookie" {
			t.Errorf("Should not have set cookie on error: %s\n", v[0])
		}
	}

}
示例#4
0
/*-------------------------------------------------------------------------------*/
func TestLogout(t *testing.T) {
	port := 8203

	//create controller for all mocks
	ctrl := gomock.NewController(t)
	//check mocks at end
	defer ctrl.Finish()

	pageMapper := NewSimplePageMapper("notused", "notused", two)
	sm := NewMockSessionManager(ctrl)
	cookieMapper := NewSimpleCookieMapper(appName)
	serveMux, _ := createDispatcherWithMocks(ctrl, pageMapper, cookieMapper, sm)

	sm.EXPECT().Destroy(gomock.Any()).Return(nil)

	go func() {
		http.ListenAndServe(fmt.Sprintf(":%d", port), serveMux)
	}()

	logoutURLHost := fmt.Sprintf("localhost:%d", port)
	logoutURL, err := url.Parse(fmt.Sprintf("http://%s%s", logoutURLHost, "/fart/google/logout"))
	if err != nil {
		t.Fatalf("Can't understand url: %s", err)
	}

	client := new(http.Client)
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		checkRedirValues(t, "error from goog", via, map[string][]string{
			"path":       []string{req.URL.Path, two},
			"host":       []string{req.URL.Host, logoutURLHost},
			"via url[0]": []string{via[0].URL.String(), logoutURL.String()},
		})
		return stopProcessing
	}
	resp := createReqAndDo(t, client, logoutURL.String(),
		&http.Cookie{
			Name:  cookieMapper.CookieName(),
			Value: "forty-series-tires",
		})
	for k, v := range resp.Header {
		if k == "Set-Cookie" {
			p := strings.Split(v[0], ";")
			for _, piece := range p {
				if strings.Index(piece, cookieMapper.CookieName()) != -1 {
					if strings.TrimSpace(piece) != cookieMapper.CookieName()+"=" {
						t.Errorf("Cookie not destroyed properly! '%s'", piece)
					}
				}
				if strings.Index(piece, "Max-Age") != -1 {
					if strings.TrimSpace(piece) != "Max-Age=0" {
						t.Errorf("Cookie not destroyed properly! '%s'", piece)
					}
				}
			}
		}
	}

}
示例#5
0
文件: http.go 项目: lopaka/rsc
// newRawClient creates an http package Client taking into account both the parameters and package
// variables.
func newRawClient(noredirect bool) *http.Client {
	tr := http.Transport{ResponseHeaderTimeout: ResponseHeaderTimeout, Proxy: http.ProxyFromEnvironment}
	tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: NoCertCheck}
	c := http.Client{Transport: &tr}
	if noredirect {
		c.CheckRedirect = func(*http.Request, []*http.Request) error {
			return fmt.Errorf(noRedirectError)
		}
	}
	return &c
}
示例#6
0
// buildRequest is where most of the magic happens for request processing
func buildRequest(httpMethod, url string, ro *RequestOptions, httpClient *http.Client) (*http.Response, error) {
	if ro == nil {
		ro = &RequestOptions{}
	}
	// Create our own HTTP client

	if httpClient == nil {
		httpClient = BuildHTTPClient(*ro)
	}

	defaultRedirectLimit := 30

	httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		if len(via) > defaultRedirectLimit {
			return fmt.Errorf("%d consecutive requests(redirects)", len(via))
		}
		if len(via) == 0 {
			// No redirects
			return nil
		}
		// mutate the subsequent redirect requests with the first Header
		for key, val := range via[0].Header {
			req.Header[key] = val
		}
		return nil
	}

	// Build our URL

	var (
		err error
	)

	if len(ro.Params) != 0 {
		if url, err = buildURLParams(url, ro.Params); err != nil {
			return nil, err
		}
	}

	// Build the request
	req, err := buildHTTPRequest(httpMethod, url, ro)

	if err != nil {
		return nil, err
	}

	// Do we need to add any HTTP headers or Basic Auth?
	addHTTPHeaders(ro, req)
	addCookies(ro, req)

	return httpClient.Do(req)
}
示例#7
0
func httpDl(uri, fileName string) error {
	fmt.Printf("httpDl: %s\n", uri)
	options := cookiejar.Options{
		PublicSuffixList: publicsuffix.List,
	}
	jar, err := cookiejar.New(&options)
	if err != nil {
		return err
	}
	client := http.Client{Jar: jar}
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		dumpReq(req)
		if len(via) >= 10 {
			return fmt.Errorf("too many redirects")
		}
		if len(via) == 0 {
			return nil
		}
		for attr, val := range via[0].Header {
			if _, ok := req.Header[attr]; !ok {
				req.Header[attr] = val
			}
		}
		return nil
	}

	req, err := http.NewRequest("GET", uri, nil)
	// Note: this is crucial. Dropbox will return some html if User-Agent is not defined
	req.Header.Add("User-Agent", "curl/7.43.0")
	dumpReq(req)
	if err != nil {
		return err
	}
	resp, err := client.Do(req)
	dumpResp(resp)
	if err != nil {
		return err
	}
	d, err := ioutil.ReadAll(resp.Body)
	resp.Body.Close()
	if err != nil {
		return err
	}
	if resp.StatusCode != 200 {
		return fmt.Errorf("httpDl() failed because StatusCode = %d", resp.StatusCode)
	}
	return ioutil.WriteFile(fileName, d, 0644)
}
示例#8
0
func randomPage(command *bot.Cmd) (string, error) {
	var redirectNotAllowed = errors.New("redirect")
	redirectedURL := ""

	client := http.Client{}
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		redirectedURL = req.URL.String()
		return redirectNotAllowed
	}

	_, err := client.Get(randomURL)
	if urlError, ok := err.(*url.Error); ok && urlError.Err == redirectNotAllowed {
		return redirectedURL, nil
	}
	return "", err
}
示例#9
0
func Test_RedirectHandleRedirects(t *testing.T) {
	to := "http://www.yfu.de"
	testStore.Add(&redirect{From: "foo", To: to})

	client := new(http.Client)
	var redirectURL *url.URL
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		redirectURL = req.URL
		return errors.New("") // we don't want to carry out the redirect, just get the target URL
	}
	client.Get(server.URL + "/foo")

	if redirectURL == nil {
		t.Fatalf("no redirect observed!")
	}
	if redirectURL.String() != to {
		t.Errorf("expected %q, got %q", to, redirectURL.String())
	}
}
示例#10
0
func init() {
	_, regex, proxy, _ = parseRule(loadRule("proxy.txt"))
	pool.New = func() interface{} {
		client := new(http.Client)
		client.Transport = &http.Transport{
			Proxy: func(req *http.Request) (*url.URL, error) {
				for i, rule := range regex {
					if rule.MatchString(req.URL.Host) {
						return proxy[i], nil
					}
				}
				return nil, nil
			},
		}
		client.CheckRedirect = func(_ *http.Request, _ []*http.Request) error {
			return disableRedirect
		}
		return client
	}
}
示例#11
0
// proxyRequest does not use the local storage and directly proxies the
// request to the upstream server.
func (ph *Handler) proxyRequest(ctx context.Context,
	w http.ResponseWriter, r *http.Request, vh *types.VirtualHost) {

	//!TODO: use the upstream for the vhost - if the vhost is not a "simple" one
	// or has authentication or is a FS, this will not work
	client := http.Client{}
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		return ErrNoRedirects
	}

	newURL := vh.UpstreamAddress.ResolveReference(r.URL)

	req, err := http.NewRequest("GET", newURL.String(), nil)
	if err != nil {
		log.Printf("[%p] Got error\n %s\n while making request ", r, err)
		return
	}

	for headerName, headerValue := range r.Header {
		req.Header.Set(headerName, strings.Join(headerValue, ","))
	}

	resp, err := client.Do(req)
	if err != nil && err != ErrNoRedirects {
		if urlError, ok := err.(*url.Error); !(ok && urlError.Err == ErrNoRedirects) {
			log.Printf("[%p] Got error\n %s\n while proxying %s to %s", r, err,
				r.URL.String(), newURL.String())
			return
		}
	}

	defer resp.Body.Close()

	respHeaders := w.Header()
	for headerName, headerValue := range resp.Header {
		respHeaders.Set(headerName, strings.Join(headerValue, ","))
	}

	ph.finishRequest(resp.StatusCode, w, r, resp.Body)
}
示例#12
0
func TestResponseURL(t *testing.T) {
	c := new(http.Client)
	req := NewRequest(c)
	url := "http://httpbin.org/get"
	resp, _ := req.Get(url)
	u, _ := resp.URL()
	assert.Equal(t, u.String(), url)

	url = "http://httpbin.org/redirect/3"
	resp, _ = req.Get(url)
	u, _ = resp.URL()
	assert.Equal(t, u.String(), "http://httpbin.org/get")
	url = "http://httpbin.org/redirect/3"

	c.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		return errors.New("redirect")
	}
	resp, _ = req.Get(url)
	u, _ = resp.URL()
	assert.Equal(t, u.String(), "http://httpbin.org/relative-redirect/2")

}
示例#13
0
文件: wget.go 项目: brettanomyces/ici
func main() {
	client := http.Client{}
	client.CheckRedirect =
		func(req *http.Request, via []*http.Request) error {
			fmt.Fprintf(os.Stderr, "Redirect: %v\n", req.URL)
			return nil
		}

	var url string
	if len(os.Args) < 2 {
		url = "http://golang.org"
	} else {
		url = os.Args[2]
	}

	page, err := client.Get(url)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
		return
	}

	io.Copy(os.Stdout, page.Body)
	page.Body.Close()
}
示例#14
0
/*-------------------------------------------------------------------------------*/
func TestGoogleLogin(t *testing.T) {
	port := 8201

	//create controller for all mocks
	ctrl := gomock.NewController(t)
	//check mocks at end
	defer ctrl.Finish()

	//the key values
	st := "/frob bob"
	loginurl := "/fart/google/login"
	code := "barfly"
	one := "/1.html"
	sid := "id of session, sid vicious?"

	//authconn is a wrapper around the google auth connector with all mock methods, except AuthURL
	//pm is a mock for testing that we get a call to LoginLandingPage
	pm := NewMockPageMapper(ctrl)
	sm := NewMockSessionManager(ctrl)
	cm := NewSimpleCookieMapper(appName)
	serveMux, authconn := createDispatcherWithMocks(ctrl, pm, cm, sm)

	session := NewMockSession(ctrl)
	session.EXPECT().SessionId().Return(sid).AnyTimes()
	//when we succeed at logging in, it filters down to the session
	sm.EXPECT().Generate(gomock.Any(), gomock.Any(), gomock.Any(), st, code).Return(session, nil)

	//consumed by the google object under test
	deploy := NewMockDeploymentEnvironment(ctrl)
	deploy.EXPECT().RedirectHost(gomock.Any()).Return(fmt.Sprintf("http://localhost:%d", port))

	detail := NewMockOauthClientDetail(ctrl)
	detail.EXPECT().ClientId(gomock.Any()).Return(id)
	detail.EXPECT().ClientSecret(gomock.Any()).Return(seekret)

	//we are testing the AuthURL method, and NOT testing ExchangeForToken() as it requires a
	//real network and a real client id and seekret
	google := NewGoogleOauth2(SCOPE, PROMPT, detail, deploy)

	//these are just accessing the constants, so don't care how many times
	//authconn.EXPECT().Name().Return("google").AnyTimes()
	authconn.EXPECT().StateValueName().Return("state").AnyTimes()
	authconn.EXPECT().ErrorValueName().Return("error").AnyTimes()
	authconn.EXPECT().CodeValueName().Return("code").AnyTimes()
	authconn.EXPECT().ClientTokenValueName().Return("notused").AnyTimes()

	//phase1 is not used by google because of oauth2
	authconn.EXPECT().Phase1(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()

	//this is actually under test, the google.AuthURL method
	authconn.EXPECT().UserInteractionURL(gomock.Any(), st, returl).Return(google.UserInteractionURL(nil, st, returl))

	//this is mocked out because it has the side effect of a network call... we can use the mocks
	//to return an error which we do in the second case
	gomock.InOrder(
		authconn.EXPECT().Phase2("", code).Return(nil, nil),
		authconn.EXPECT().Phase2("", code).Return(nil, badTransport),
	)

	//testing that page mapper's login method gets called during the login process to generate the
	//final web page to land on
	pm.EXPECT().LoginLandingPage(authconn, st, code).Return(one)
	pm.EXPECT().ErrorPage(authconn, gomock.Any()).Return(three)

	go func() {
		http.ListenAndServe(fmt.Sprintf(":%d", port), serveMux)
	}()

	//we need to compute a return url (stage 2) because we expect to see at redir of stage 1
	returnURLBase := fmt.Sprintf("http://localhost:%d%s", port, returl)

	//we need to compute a login url, with a state value to make sure it is propagated all the
	//way through to LoginLandingPage()
	v := url.Values{
		"state": []string{st},
	}
	loginURL, err := url.Parse(fmt.Sprintf("http://localhost:%d%s?%s", port, loginurl, v.Encode()))
	if err != nil {
		t.Fatalf("Can't understand url: %s", err)
	}

	//setup client to not really do redirects so we can look at what's going on
	client := new(http.Client)
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		checkRedirValues(t, "phase 1 of login", via, map[string][]string{
			"path":       []string{req.URL.Path, GOOGLE_AUTH_URL_PATH},
			"host":       []string{req.URL.Host, GOOGLE_AUTH_URL_HOST[len("https://"):]},
			"scheme":     []string{req.URL.Scheme, "https"},
			"state":      []string{req.URL.Query().Get("state"), st},
			"client_id":  []string{req.URL.Query().Get("client_id"), id},
			"via url[0]": []string{via[0].URL.String(), loginURL.String()},
		})
		if !strings.HasPrefix(req.URL.Query().Get("redirect_uri"), returnURLBase) {
			t.Errorf("Serious problems understanding the callback uri: %s", req.URL.Query().Get("redirect_uri"))
		}
		return stopProcessing
	}

	createReqAndDo(t, client, loginURL.String(), nil)
	// next stage is to test that if we get the callabck we land on the right page
	// in the right state... compute a URL like google would send us
	v = url.Values{
		"code":  []string{code},
		"state": []string{st},
		"error": []string{},
	}

	returnURL, err := url.Parse(fmt.Sprintf("%s?%s", returnURLBase, v.Encode()))
	if err != nil {
		t.Fatalf("Can't understand url: %s", err)
	}

	//now check the value we redirect back to on successful login... this simulates what google
	//would send back to us after successful handshake... again, we don't allow the redir
	//to be processed
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		checkRedirValues(t, "phase 2 of login", via, map[string][]string{
			"path":       []string{req.URL.Path, one},
			"host":       []string{req.URL.Host, fmt.Sprintf("localhost:%d", port)},
			"scheme":     []string{req.URL.Scheme, "http"},
			"state":      []string{req.URL.Query().Get("state"), ""}, //sanity
			"via url[0]": []string{via[0].URL.String(), returnURL.String()},
		})
		return stopProcessing
	}

	//make sure cookie manager sent us something
	resp := createReqAndDo(t, client, returnURL.String(), nil)
	found := false
	for k, v := range resp.Header {
		if k == "Set-Cookie" {
			found = true
			p := strings.Split(v[0], ";")
			if strings.Index(p[0], cm.CookieName()) == -1 {
				t.Errorf("Found a cookie but expected name '%s' but couldn't find it in header: %s",
					cm.CookieName(), p[0])
			}
			if strings.Index(p[0], sid) == -1 {
				t.Errorf("Found a cookie but expected value '%s' but couldn't find it in header: %s",
					sid, p[0])
			}
		}
	}
	if !found {
		t.Errorf("Didn't find cookie '%s'", cm.CookieName())
	}
	//this tests that if the transport connection to the provider fails, we get the error page
	client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
		checkRedirValues(t, "phase 2 (bad network)", via, map[string][]string{
			"path":       []string{req.URL.Path, three},
			"host":       []string{req.URL.Host, fmt.Sprintf("localhost:%d", port)},
			"via url[0]": []string{via[0].URL.String(), returnURL.String()},
			//error parameter is checked in a diff test
		})
		return stopProcessing
	}

	createReqAndDo(t, client, returnURL.String(), nil)

}
示例#15
0
// Wraps a client using WrapCheckRedirect to prevent net-to-Unix redirects.
func RestrictRedirects(c *http.Client) {
	c.CheckRedirect = WrapCheckRedirect(c.CheckRedirect)
}
示例#16
0
//InitWithCustomHTTPClient initializes the underlying client that communicates with Stormpath with a custom http.Client
func InitWithCustomHTTPClient(credentials Credentials, cache Cache, httpClient *http.Client) {
	httpClient.CheckRedirect = checkRedirect
	client = &Client{credentials, httpClient, cache}

	initLog()
}
示例#17
0
func setHTTPClient(c *http.Client) {
	c.Jar = mustInitCookieJar()
	c.CheckRedirect = checkRedirect
	client = c
}