rde*_*ges 47 rest redirect http go
我目前正在Go中编写一些与REST API交互的软件.我正在尝试查询的REST API端点返回HTTP 302重定向以及指向资源URI的HTTP Location标头.
我正在尝试使用Go脚本来获取HTTP Location标头以供以后处理.
以下是我目前正在实现的功能:
package main
import (
"errors"
"fmt"
"io/ioutil"
"net/http"
)
var BASE_URL = "https://api.stormpath.com/v1"
var STORMPATH_API_KEY_ID = "xxx"
var STORMPATH_API_KEY_SECRET = "xxx"
func noRedirect(req *http.Request, via []*http.Request) error {
return errors.New("Don't redirect!")
}
func main() {
client := &http.Client{
CheckRedirect: noRedirect
}
req, err := http.NewRequest("GET", BASE_URL+"/tenants/current", nil)
req.SetBasicAuth(STORMPATH_API_KEY_ID, STORMPATH_API_KEY_SECRET)
resp, err := client.Do(req)
// If we get here, it means one of two things: either this http request
// actually failed, or we got an http redirect response, and should process it.
if err != nil {
if resp.StatusCode == 302 {
fmt.Println("got redirect")
} else {
panic("HTTP request failed.")
}
}
defer resp.Body.Close()
}
Run Code Online (Sandbox Code Playgroud)
这对我来说有点像黑客.通过重写http.Client
的CheckRedirect
功能,我基本上是被迫把HTTP重定向错误一样(他们不是).
我已经看到其他几个地方建议使用HTTP传输而不是HTTP客户端 - 但我不知道如何使这项工作,因为我需要HTTP客户端,因为我需要使用HTTP Basic Auth与此REST通信API.
您是否可以告诉我一种使用基本身份验证发出HTTP请求的方法 - 虽然不遵循重定向 - 但这不涉及抛出错误和错误处理?
谢谢.
Eti*_*nes 97
现在有一个更简单的解决方案:
client: &http.Client{
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
Run Code Online (Sandbox Code Playgroud)
这样,http
包自动知道:"啊,我不应该遵循任何重定向",但不会抛出任何错误.来自源代码中的评论:
作为一种特殊情况,如果CheckRedirect返回ErrUseLastResponse,则返回最近的响应,其主体未闭合,并返回nil错误.
uvg*_*ovy 11
另一种选择,使用客户端本身,没有RoundTrip:
// create a custom error to know if a redirect happened
var RedirectAttemptedError = errors.New("redirect")
client := &http.Client{}
// return the error, so client won't attempt redirects
client.CheckRedirect = func(req *http.Request, via []*http.Request) error {
return RedirectAttemptedError
}
// Work with the client...
resp, err := client.Head(urlToAccess)
// test if we got the custom error
if urlError, ok := err.(*url.Error); ok && urlError.Err == RedirectAttemptedError{
err = nil
}
Run Code Online (Sandbox Code Playgroud)
更新:此解决方案适用于<1.7
这是可能的,但解决方案稍微扭转了问题.这是一个写为golang测试的示例.
package redirects
import (
"github.com/codegangsta/martini-contrib/auth"
"github.com/go-martini/martini"
"net/http"
"net/http/httptest"
"testing"
)
func TestBasicAuthRedirect(t *testing.T) {
// Start a test server
server := setupBasicAuthServer()
defer server.Close()
// Set up the HTTP request
req, err := http.NewRequest("GET", server.URL+"/redirect", nil)
req.SetBasicAuth("username", "password")
if err != nil {
t.Fatal(err)
}
transport := http.Transport{}
resp, err := transport.RoundTrip(req)
if err != nil {
t.Fatal(err)
}
// Check if you received the status codes you expect. There may
// status codes other than 200 which are acceptable.
if resp.StatusCode != 200 && resp.StatusCode != 302 {
t.Fatal("Failed with status", resp.Status)
}
t.Log(resp.Header.Get("Location"))
}
// Create an HTTP server that protects a URL using Basic Auth
func setupBasicAuthServer() *httptest.Server {
m := martini.Classic()
m.Use(auth.Basic("username", "password"))
m.Get("/ping", func() string { return "pong" })
m.Get("/redirect", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "/ping", 302)
})
server := httptest.NewServer(m)
return server
}
Run Code Online (Sandbox Code Playgroud)
您应该能够将上面的代码放入它自己的名为"redirects"的包中,并在获取所需的依赖项之后运行它
mkdir redirects
cd redirects
# Add the above code to a file with an _test.go suffix
go get github.com/codegangsta/martini-contrib/auth
go get github.com/go-martini/martini
go test -v
Run Code Online (Sandbox Code Playgroud)
希望这可以帮助!
要使用不遵循重定向的基本身份验证发出请求,请使用接受 *请求的RoundTrip函数
这段代码
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
)
func main() {
var DefaultTransport http.RoundTripper = &http.Transport{}
req, _ := http.NewRequest("GET", "http://httpbin.org/headers", nil)
req.SetBasicAuth("user", "password")
resp, _ := DefaultTransport.RoundTrip(req)
defer resp.Body.Close()
contents, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Printf("%s", err)
os.Exit(1)
}
fmt.Printf("%s\n", string(contents))
}
Run Code Online (Sandbox Code Playgroud)
输出
{
"headers": {
"Accept-Encoding": "gzip",
"Authorization": "Basic dXNlcjpwYXNzd29yZA==",
"Connection": "close",
"Host": "httpbin.org",
"User-Agent": "Go 1.1 package http",
"X-Request-Id": "45b512f1-22e9-4e49-8acb-2f017e0a4e35"
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
28692 次 |
最近记录: |