LoginSignup
0
0

More than 1 year has passed since last update.

Goのhttp.Clientでリダイレクトを判定して処理を行う方法

Posted at

TL;DR

GoでHTTPリクエストを送信送るnet/httpライブラリのhttp.Clientはデフォルトだと自動リダイレクトする仕様ですが、http.Client.CheckRedirectをオーバーライドすればリダイレクトする前の結果を返すことができます。

外部要因でリダイレクトがかかる際にシステムでエラーが起きる

Amazonの商品の分類によって処理を変えるようなシステムを実装していました。
Amazonの商品は「靴」などの分類を「BrowseNodes」という単位で管理しており、こちらはAPIのドキュメントにも書かれています。

メンズスニーカーの場合、「https://www.amazon.co.jp/b?node=2221112051」というURLの「2221112051」がメンズスニーカーのBrowseNodeのIDに相当します。

スクリーンショット 2022-12-18 14.02.37.png

このBrowseNodeのIDをもとにしたシステムをGoにて作成していたところ、このIDがときどき変更されて、リダイレクトされていることがわかりました。事前にシステムにIDを登録しておくと、そのIDで上記のAPIを利用した際にエラーになってしまいます。

このリダイレクトをシステムで検知することができないかを考えてみたので、今回はその方法を紹介したいと思います。

リダイレクト時にリダイレクト先を表示させるコード

こちらが実際に実装したコードです。

main.go
package main

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

func main() {
	targetUrl := os.Args[1]
	c := &http.Client{
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			return http.ErrUseLastResponse
		},
	}
	resp, err := c.Get(targetUrl)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	if resp.StatusCode == 301 {
		fmt.Println(resp.Header["Location"][0])
	}
}

$ go run main.go "https://www.amazon.co.jp/b?node=15326491"
/b?node=2231280051

http.Client.CheckRedirectをオーバーライドしてリダイレクト前のレスポンスを返す

HTTPのリクエストを送信するnet/httpライブラリのhttp.Clientはデフォルトだと自動リダイレクトする仕様ですが、http.Client.CheckRedirectをオーバーライドして、エラーを返すようにすればClientのGetメソッドは、bodyが閉る前のレスポンスとCheckRedirectの結果を返してくれます。

今回のケースではErrUseLastResponseを返していて、これが返されると次のリクエストの前の最新の応答を返してくれます。

http.GETの結果がリダイレクト前のものになる

これによってhttp.GETで返される結果が、リダイレクトされている場合にはリダイレクトされる前の結果が返るようになったので、ステータスコードによる分岐を追加することで、リダイレクト先のパスも取得することができるようになりました。

留意点

今回のコードに関しては、検討した結果として実際のプロダクションコード等では使っておりません。
スクレイピング等に使う用途を想定しておりませんので、ご注意ください。

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0