golang redirect时设置cookie

golang redirect时设置cookiegolangredirect时设置cookie参考http://www.sohu.com/a/122147787_505779上面作者说了原理,然后我贴一下自己写的代码funcsetCookieTest()error{ client:=NewHttpClient() //golanghttp自动302跳转,但是不会在302时设置cookie //所以如下代码…

golang redirect时设置cookie

func setCookieTest() error { 
   

	client := NewHttpClient()

	// golang http自动302跳转,但是不会在302时设置cookie
	// 所以如下代码取消自动跳转,然后手动设置cookie
	client.CheckRedirect(func(req *http.Request, via []*http.Request) error { 
   
		return http.ErrUseLastResponse
	})

	testUrl := "http://a.b.c/test"
	resp, err := client.Post(testUrl, nil, nil)

	if err != nil { 
   
		return fmt.Errorf("request error '%s', cause by %v", testUrl, err)
	}

	Redirect:
	if resp.HttpCode() != 200 && resp.HttpCode() != 302 { 
   
		return fmt.Errorf("request error[%d] %s ", resp.HttpCode(), testUrl)
	}

	if resp.HttpCode() == 200 { 
   
		//最后请求成功

	} else if resp.HttpCode() == 302 { 
   
		// xWiki /oauth/login
		location := resp.Headers.Get("location")
		if location == "" { 
   
			location = resp.Headers.Get("location")
		}
		u, err := url.Parse(testUrl)
		if err != nil { 
   
			return fmt.Errorf("parse host error '%s', cause by %v", u.Host, err)
		}
		setCookieWhenRedirect(client, u, resp)
		resp, _ = client.Get(location, nil)
		//可能多次跳转
		goto Redirect
	}

	return nil
}

func setCookieWhenRedirect(client *HttpClient ,domain *url.URL, resp *Response) { 
   

	//get cookie (JSESSIONID=MDJkZDFkMjItZTc3OS00ZWY5LTkzZWUtODI3MDBmYWFkMzg2; path=/oauth; HttpOnly)
	cookieInHeader := resp.Headers[textproto.CanonicalMIMEHeaderKey("Set-Cookie")]
	var cookieStr string
	if len(cookieInHeader) != 0 { 
   
		cookieStr = cookieInHeader[len(cookieInHeader)-1]
	}
	if cookieStr == "" { 
   
		return
	}
	//build cookie
	cookie := &http.Cookie{ 
   }
	parts := strings.Split(cookieStr, ";")
	for _, item := range parts { 
   
		if item == "" { 
   
			continue
		}
		item = strings.Trim(item, " ")
		if item == "HttpOnly" { 
   
			cookie.HttpOnly = true
			continue
		}
		subItems := strings.Split(item, "=")
		if len(subItems) != 2 { 
   
			continue
		}
		if subItems[0] == "Path" || subItems[0] == "path" { 
   
			cookie.Path = subItems[1]
			continue
		}
		cookie.Name 	= subItems[0]
		cookie.Value 	= subItems[1]
	}
	// set cookie
	jar := client.CookieJar()
	if jar == nil { 
   
		jar, _ = cookiejar.New(nil)
	}
	jar.SetCookies(domain, []*http.Cookie{ 
   cookie})
	client.SetCookieJar(jar)
	// 设置成功后下次请求domain就会带上cookie
}
  • 简单封装的httpclient, 后台用来调用第三方平台的
type Response struct { 
   
	Headers http.Header
	Data []byte
}

func (resp *Response) HttpCodeIs200()(bool, error){ 
   
	code := resp.HttpCode()
	if code != 200 { 
   
		return false, fmt.Errorf("http-code: %d", code)
	}
	return true, nil
}

func (resp *Response) HttpCode()(int){ 
   
	code := resp.Headers.Get("StatusCode")
	if code == "" { 
   
		return 0
	}

	intCode, _ := strconv.Atoi(code)

	return intCode
}

type HttpClient struct { 
   
	client *http.Client
}

func NewHttpClient()*HttpClient{ 
   
	tr := &http.Transport{ 
   
		TLSClientConfig: &tls.Config{ 
   InsecureSkipVerify: true},
	}

	client := &http.Client{ 
   
		Transport: tr,
	}

	return &HttpClient{ 
   client:client}
}

func (httpClient *HttpClient) CheckRedirect(fn func(req *http.Request, via []*http.Request) error) { 
   
	httpClient.client.CheckRedirect = fn
}

func (httpClient *HttpClient) SetCookieJar(jar http.CookieJar) { 
   
	httpClient.client.Jar = jar
}

func (httpClient *HttpClient) CookieJar() http.CookieJar { 
   
	return httpClient.client.Jar
}

func (httpClient *HttpClient) Get(url string, header map[string]string)(*Response, error){ 
   
	return httpClient.Call(http.MethodGet, url, header, nil)
}

func (httpClient *HttpClient) Post(url string, header map[string]string, body io.Reader)(*Response, error){ 
   
	return httpClient.Call(http.MethodPost, url, header, body)
}

func (httpClient *HttpClient) Put(url string, header map[string]string, body io.Reader)(*Response, error){ 
   
	return httpClient.Call(http.MethodPut, url, header, body)
}

func (httpClient *HttpClient) Delete(url string, header map[string]string)(*Response, error){ 
   
	return httpClient.Call(http.MethodDelete, url, header, nil)
}


func (httpClient *HttpClient) Call(method, url string, header map[string]string, body io.Reader)(*Response, error){ 
   
	req,err := http.NewRequest(method, url, body)

	if err != nil { 
   
		return nil, err
	}

	if header != nil { 
   
		for k, v := range header { 
   
			req.Header.Set(k, v)
		}
	}

	resp ,err := httpClient.client.Do(req)
	if err != nil { 
   
		return nil, err
	}

	respHeader := resp.Header

	defer resp.Body.Close()

	respCode := resp.StatusCode
	respHeader.Set("StatusCode", strconv.Itoa(respCode))
	respHeader.Set("Status", resp.Status)

	content, err := ioutil.ReadAll(resp.Body)
	if err != nil { 
   
		return nil, fmt.Errorf("read from response'body error. response code %v. response content: %v",
			respCode, string(content))
	}

	return &Response{ 
   Headers: respHeader, Data: content}, nil
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/34685.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注