在golang中,如何确定一系列重定向后的最终URL?

huangapple go评论102阅读模式
英文:

In golang, how to determine the final URL after a series of redirects?

问题

所以,我正在使用net/http包。我正在GET一个我确定会重定向的URL。它甚至可能在最终URL之前重定向几次。重定向在后台自动处理。

有没有一种简单的方法可以找出最终的URL,而不需要使用hackish的解决方法,比如设置http.Client对象上的CheckRedirect字段?

我想我应该提到我想出了一个解决方法,但它有点hackish,因为它涉及使用全局变量并设置自定义http.Client上的CheckRedirect字段。

肯定有一种更简洁的方法来做到这一点。我希望有像这样的东西:

package main

import (
  "fmt"
  "log"
  "net/http"
)

func main() {
  // 尝试GET一些重定向的URL。这里可能有5或6个看不见的重定向。
  resp, err := http.Get("http://some-server.com/a/url/that/redirects.html")
  if err != nil {
    log.Fatalf("http.Get => %v", err.Error())
  }

  // 找出我们最终到达的URL
  finalURL := magicFunctionThatTellsMeTheFinalURL(resp)

  fmt.Printf("你最终到达的URL是:%v", finalURL)
}
英文:

So, I'm using the net/http package. I'm GETting a URL that I know for certain is redirecting. It may even redirect a couple of times before landing on the final URL. Redirection is handled automatically behind the scenes.

Is there an easy way to figure out what the final URL was without a hackish workaround that involves setting the CheckRedirect field on a http.Client object?

I guess I should mention that I think I came up with a workaround, but it's kind of hackish, as it involves using a global variable and setting the CheckRedirect field on a custom http.Client.

There's got to be a cleaner way to do it. I'm hoping for something like this:

package main

import (
  "fmt"
  "log"
  "net/http"
)

func main() {
  // Try to GET some URL that redirects.  Could be 5 or 6 unseen redirections here.
  resp, err := http.Get("http://some-server.com/a/url/that/redirects.html")
  if err != nil {
    log.Fatalf("http.Get => %v", err.Error())
  }

  // Find out what URL we ended up at
  finalURL := magicFunctionThatTellsMeTheFinalURL(resp)

  fmt.Printf("The URL you ended up at is: %v", finalURL)
}

答案1

得分: 86

package main

import (
"fmt"
"log"
"net/http"
)

func main() {
resp, err := http.Get("http://stackoverflow.com/q/16784419/727643")
if err != nil {
log.Fatalf("http.Get => %v", err.Error())
}

// Your magic function. The Request in the Response is the last URL the
// client tried to access.
finalURL := resp.Request.URL.String()

fmt.Printf("The URL you ended up at is: %v\n", finalURL)

}

Output:

The URL you ended up at is: http://stackoverflow.com/questions/16784419/in-golang-how-to-determine-the-final-url-after-a-series-of-redirects

英文:
package main

import (
	"fmt"
	"log"
	"net/http"
)

func main() {
	resp, err := http.Get("http://stackoverflow.com/q/16784419/727643")
	if err != nil {
		log.Fatalf("http.Get => %v", err.Error())
	}

    // Your magic function. The Request in the Response is the last URL the
    // client tried to access.
	finalURL := resp.Request.URL.String()

	fmt.Printf("The URL you ended up at is: %v\n", finalURL)
}

Output:

The URL you ended up at is: http://stackoverflow.com/questions/16784419/in-golang-how-to-determine-the-final-url-after-a-series-of-redirects

答案2

得分: 3

我想要添加一条注释,即http.Head方法应该足够获取最终的URL。理论上来说,与http.Get相比,它应该更快,因为服务器只会返回一个头部信息:

resp, err := http.Head("http://stackoverflow.com/q/16784419/727643")
...
finalURL := resp.Request.URL.String()
...
英文:

I would add a note that http.Head method should be enough to retrieve the final URL. Theoretically it should be faster comparing to http.Get as a server is expected to send back just a header:

resp, err := http.Head("http://stackoverflow.com/q/16784419/727643")
...
finalURL := resp.Request.URL.String()
...

答案3

得分: 0

这是我对超时问题的两分建议最佳答案。 (已测试:Go v1.20.4,darwin/amd64)

import (
	"net/http"
	"time"
)

// FindRedirectURL返回重定向后的最终URL。在15秒后超时时会出错。
func FindRedirectURL(url string) (string, error) {
	client := &http.Client{
		Timeout: 15 * time.Second,
	}

	resp, err := client.Get(url)
	if err != nil {
		return "", err
	}

	finalURL := resp.Request.URL.String()

	return finalURL, nil
}
英文:

Here's my two cents with time-out over the best answer. (Tested: Go v1.20.4, darwin/amd64)

import (
	"net/http"
	"time"
)

// FindRedirectURL returns the final URL after redirection. It will
// error with time-out after 15 seconds.
func FindRedirectURL(url string) (string, error) {
	client := &http.Client{
		Timeout: 15 * time.Second,
	}

	resp, err := client.Get(url)
	if err != nil {
		return "", err
	}

	finalURL := resp.Request.URL.String()

	return finalURL, nil
}

huangapple
  • 本文由 发表于 2013年5月28日 13:23:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/16784419.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定