使用Go语言的net/http包连接YouTube API时遇到的问题

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

Issues connecting to YouTube API with Go's net/http package

问题

我认为这可能是我在SO上的第一个问题。我刚刚沉浸在Go语言中。我刚刚读完《Go语言编程入门》这本书,想写一个简单的程序来查询YT Data API v3。

问题是:当我执行go run request.go时,我得到一个404 Not Found错误。但是当我将传递的URL粘贴到浏览器或Postman中时,请求正常工作。这是我的func main() {}的样子:

func main() {
    // 读取API密钥
    key, error_ := ioutil.ReadFile("user_data.txt")
    if error_ != nil {
        log.Fatal(error_)
    }
    api_key += string(key)

    // 构建URL
    url := base_url + query + api_key
    // 取消下一行的注释以证明我没有疯狂。
    // url = "http://ip.jsontest.com/"

    // 发送请求
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    body, error_g := ioutil.ReadAll(resp.Body)
    if error_g != nil {
        fmt.Println(error_g)
    }
    fmt.Println(resp.Status)
    fmt.Println(resp.Request)
    fmt.Println(string(body))
    defer resp.Body.Close()
    // 解析响应
    var vs Videos
    err = json.NewDecoder(resp.Body).Decode(&vs)
    if err != nil {
        fmt.Printf("%T\n", err)
        // fmt.Println("Error:", err)
        log.Fatal(err)
    }
    for _, v := range vs.Items {
        fmt.Println(v.Id.VideoId, v.Snippet.Title)
    }
}

这是我存储库中程序的链接request.go

英文:

I think this may be my first question on SO. I've just been immersing myself in Go. I just got done reading An Introduction to Programming in Go and I wanted to just write a simple program that would query the YT Data API v3.

The issue: when I execute go run request.go I get a 404 Not Found error. However when I take the URL that's passed and paste in my browser or Postman the request works fine. Here's what my func main() {} looks like:

func main() {
    // read in API key
    key, error_ := ioutil.ReadFile("user_data.txt")
    if error_ != nil {
        log.Fatal(error_)
    }
    api_key += string(key)

    // buil url
    url := base_url + query + api_key
    // Uncomment the next line to show that I'm not insane.
    // url = "http://ip.jsontest.com/"

    // make request
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    body, error_g := ioutil.ReadAll(resp.Body)
    if error_g != nil {
        fmt.Println(error_g)
    }
    fmt.Println(resp.Status)
    fmt.Println(resp.Request)
    fmt.Println(string(body))
    defer resp.Body.Close()
    // parse response
    var vs Videos
    err = json.NewDecoder(resp.Body).Decode(&vs)
    if err != nil {
        fmt.Printf("%T\n", err)
        // fmt.Println("Error:", err)
        log.Fatal(err)
    }
    for _, v := range vs.Items {
        fmt.Println(v.Id.VideoId, v.Snippet.Title)
    }
}

And here is the link to the program in my repo request.go

答案1

得分: 2

我很惊讶你的示例代码能够正常工作,假设这是完整的代码,因为你没有定义base_urlquery来构建url := base_url + query + api_key。我更倾向于将这部分作为注释而不是答案,但是我没有足够的声望来这样做。

我猜你可能已经尝试过这个了,但是我建议你打印出你构建的URL并仔细检查它是否类似于:

https://www.googleapis.com/youtube/v3/videos?id=7lCDEYXw3mM&key=YOUR_API_KEY

另外一个你应该考虑使用的东西是 net/url 包来构建你的URL。然后你可以这样做:

params := url.Values{}
params.Add("id", video_id)
params.Add("key", api_key)

url := &url.URL{
    Host: 'https://www.googleapis.com/youtube/v3/videos',
    Query: params.Encode()
}

get_url := url.String()

这样做可能会有点繁琐,但好处是它会自动处理所有的编码和查询构建工作。我猜这可能是出错的地方,假设你正确读取了你的API密钥,并且它确实对数据API有效。显然,你应该将这个逻辑封装成一个函数调用,以使其更可重用,但你明白我的意思。

英文:

I'm surprised your example works, assuming that is the whole thing, as you haven't defined base_url or query for url := base_url + query + api_key. I'd rather leave that as a comment than an answer, but I don't have enough rep to do so.

I'm assuming that you've tried this, but I'd print out your built url and double check it looks something like

https://www.googleapis.com/youtube/v3/videos?id=7lCDEYXw3mM&key=YOUR_API_KEY

The other thing you should consider using, which might indirectly solve your problem, is the net/url package to build your URLs. Then you can do something like:

params := url.Values{}
params.Add("id", video_id)
params.Add("key", api_key)

url := &url.Url{
    Host: 'https://www.googleapis.com/youtube/v3/videos',
    Query: params.Encode()
}

get_url := url.String()

It's a bit more tedious, but the advantage here is that it takes care of all of the encoding and query building for you. My guess is that this is probably where something is going wrong, assuming you're reading in your API key properly, and it is indeed valid for the Data API. Obviously you'd want to bust that logic out into a function call to make it more reusable, but you get the idea.

huangapple
  • 本文由 发表于 2014年11月6日 23:01:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/26782572.html
匿名

发表评论

匿名网友

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

确定