Get request returns data in Thunder client/Postman but gives blank data in Golang code

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

Get request returns data in Thunder client/Postman but gives blank data in Golang code

问题

我正在尝试使用Golang的net/http从API获取数据。当我使用VS Code的Thunder客户端或者Postman时,我可以得到正确的数据,但是当我尝试从Golang代码中获取数据时,我得到一个空的响应。

数据的获取分为两步:

  1. 使用初始的GET请求获取cookies(这部分在两种情况下都正常工作)
  2. 使用cookies发起另一个GET请求来获取所需的数据(这一步在Golang中返回空响应,在下面的Postman链接中被称为Historical Data)

Get request returns data in Thunder client/Postman but gives blank data in Golang code

以下是Golang代码。代码可能有点长,因为有多行添加头部信息。

var BaseURL string = "https://www.nseindia.com"

func ReqConfig() *http.Request {
	req, _ := http.NewRequest("GET", BaseURL, nil)
	req.Header.Add("Accept", "*/*")
	req.Header.Add("Accept-Encoding", "gzip, deflate, br")
	req.Header.Add("Accept-Language", "en-GB,en-US;q=0.9,en;q=0.8")
	req.Header.Add("Connection", "keep-alive")
	req.Header.Add("Host", "www.nseindia.com")
	req.Header.Add("Referer", "https://www.nseindia.com/get-quotes/equity")
	req.Header.Add("X-Requested-With", "XMLHttpRequest")
	req.Header.Add("sec-fetch-dest", "empty")
	req.Header.Add("sec-fetch-mode", "cors")
	req.Header.Add("pragma", "no-cache")
	req.Header.Add("sec-fetch-site", "same-origin")
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36")
	fmt.Println(1, req.Header.Get("Cookie"))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	for _, cookie := range res.Cookies() {
		req.AddCookie(cookie)
	}

	// TODO: Remove the need to call this API twice. This is just a temporary fix.
	res, err = http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	for _, cookie := range res.Cookies() {
		req.AddCookie(cookie)
	}


	cookies := req.Cookies()
	for i := 0; i < len(cookies); i++ {
		for j := i + 1; j < len(cookies); j++ {
			if cookies[i].Name == cookies[j].Name {
				cookies = append(cookies[:j], cookies[j+1:]...)
				j--
			}
		}
	}
	req.Header.Del("Cookie")
	for _, cookie := range cookies {
		req.AddCookie(cookie)
	}
	fmt.Println("Fetched cookies")

	return req
}


func HistoricalEQ(symbol string, from string, to string, series string) {
	req := ReqConfig()

	query := req.URL.Query()
	query.Add("symbol", symbol)
	query.Add("from", from)
	query.Add("to", to)
	query.Add("series", `["`+series+`"]`)
	req.URL.RawQuery = query.Encode()
	req.URL.Path = "/api/historical/cm/equity"

	client := &http.Client{Timeout: 40 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var data map[string]interface{}
	json.NewDecoder(res.Body).Decode(&data)

        // 打印 `map[]` 而不是在Postman请求中提供的整个json数据
	fmt.Println(data)
}


func main() {
	symbol := "PAYTM"
	series := "EQ"
	from_date := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local).Format("02-01-2006")
	to_date := time.Date(2023, 1, 24, 0, 0, 0, 0, time.Local).Format("02-01-2006")
	HistoricalEQ(symbol, from_date, to_date, series)
}

如果你能够以仅限于Golang的方式从GET https://www.nseindia.com/api/historical/cm/equity?symbol=PAYTM&amp;series=[%22EQ%22]&amp;from=28-12-2022&amp;to=28-01-2023获取数据,那么这也可以解决我的问题。你可以在https://www.nseindia.com/get-quotes/equity?symbol=PAYTM查看网站前端。我所要求的GET请求可以通过转到Historical data选项卡并点击筛选按钮来触发。

类似的Python代码:https://github.com/jugaad-py/jugaad-data/blob/47bbf1aa39ebec3a260579c76ff427ea06e42acd/jugaad_data/nse/history.py#L61

英文:

I am trying to fetch data from an API using Golang net/http. When I am using Thunder client from VS Code or even Postman, I am getting proper data but when I am trying to fetch the data from Golang code, I get an empty response.

The data is fetched in 2 steps:

  1. Fetch cookies using an initial GET req (this part is working fine in both)
  2. Use the cookies to make another GET req for fetching the required data. (This is the step which is giving blank response in Golang and is named Historical Data in the Postman link given below)

Get request returns data in Thunder client/Postman but gives blank data in Golang code

Here's the Golang code. The code might be a little long but just because of multiple lined of adding headers.

var BaseURL string = &quot;https://www.nseindia.com&quot;

func ReqConfig() *http.Request {
	req, _ := http.NewRequest(&quot;GET&quot;, BaseURL, nil)
	req.Header.Add(&quot;Accept&quot;, &quot;*/*&quot;)
	req.Header.Add(&quot;Accept-Encoding&quot;, &quot;gzip, deflate, br&quot;)
	req.Header.Add(&quot;Accept-Language&quot;, &quot;en-GB,en-US;q=0.9,en;q=0.8&quot;)
	req.Header.Add(&quot;Connection&quot;, &quot;keep-alive&quot;)
	req.Header.Add(&quot;Host&quot;, &quot;www.nseindia.com&quot;)
	req.Header.Add(&quot;Referer&quot;, &quot;https://www.nseindia.com/get-quotes/equity&quot;)
	req.Header.Add(&quot;X-Requested-With&quot;, &quot;XMLHttpRequest&quot;)
	req.Header.Add(&quot;sec-fetch-dest&quot;, &quot;empty&quot;)
	req.Header.Add(&quot;sec-fetch-mode&quot;, &quot;cors&quot;)
	req.Header.Add(&quot;pragma&quot;, &quot;no-cache&quot;)
	req.Header.Add(&quot;sec-fetch-site&quot;, &quot;same-origin&quot;)
	req.Header.Add(&quot;User-Agent&quot;, &quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36&quot;)
	fmt.Println(1, req.Header.Get(&quot;Cookie&quot;))

	res, err := http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	for _, cookie := range res.Cookies() {
		req.AddCookie(cookie)
	}

	// TODO: Remove the need to call this API twice. This is just a temporary fix.
	res, err = http.DefaultClient.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	for _, cookie := range res.Cookies() {
		req.AddCookie(cookie)
	}


	cookies := req.Cookies()
	for i := 0; i &lt; len(cookies); i++ {
		for j := i + 1; j &lt; len(cookies); j++ {
			if cookies[i].Name == cookies[j].Name {
				cookies = append(cookies[:j], cookies[j+1:]...)
				j--
			}
		}
	}
	req.Header.Del(&quot;Cookie&quot;)
	for _, cookie := range cookies {
		req.AddCookie(cookie)
	}
	fmt.Println(&quot;Fetched cookies&quot;)

	return req
}


func HistoricalEQ(symbol string, from string, to string, series string) {
	req := ReqConfig()

	query := req.URL.Query()
	query.Add(&quot;symbol&quot;, symbol)
	query.Add(&quot;from&quot;, from)
	query.Add(&quot;to&quot;, to)
	query.Add(&quot;series&quot;, &quot;[\&quot;&quot;+series+&quot;\&quot;]&quot;)
	req.URL.RawQuery = query.Encode()
	req.URL.Path = &quot;/api/historical/cm/equity&quot;

	client := &amp;http.Client{Timeout: 40 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()

	var data map[string]interface{}
	json.NewDecoder(res.Body).Decode(&amp;data)

        // Prints `map[]` and not the whole json data which is provided in Postman req
	fmt.Println(data)
}


func main() {
	symbol := &quot;PAYTM&quot;
	series := &quot;EQ&quot;
	from_date := time.Date(2023, 1, 1, 0, 0, 0, 0, time.Local).Format(&quot;02-01-2006&quot;)
	to_date := time.Date(2023, 1, 24, 0, 0, 0, 0, time.Local).Format(&quot;02-01-2006&quot;)
	HistoricalEQ(symbol, from_date, to_date, series)
}

If you are able to fetch data from some other way in Golang only from GET https://www.nseindia.com/api/historical/cm/equity?symbol=PAYTM&amp;series=[%22EQ%22]&amp;from=28-12-2022&amp;to=28-01-2023, then that would also solve my issue. You can check out the website frontend at https://www.nseindia.com/get-quotes/equity?symbol=PAYTM. The GET req I am asking can be triggered by going to Historical data tab and clicking on filter button

Similar code in python: https://github.com/jugaad-py/jugaad-data/blob/47bbf1aa39ebec3a260579c76ff427ea06e42acd/jugaad_data/nse/history.py#L61

答案1

得分: 1

1️⃣ 解码错误处理被忽略了

err := json.NewDecoder(res.Body).Decode(&data)
if err != nil {
	log.Fatalf("解码请求:%v", err)
}
寻找值的开头时出现无效字符 '\x1f'

2️⃣ 看起来响应数据已经被压缩了(gzip 数据以魔术序列 0x1f 0x8b 开头)。如果你检查响应的 Headers,你会看到

...
Content-Encoding:[gzip] 🐧🐧🐧
Content-Length:[1890] 
Content-Type:[application/json; charset=utf-8] 
...

看起来是真的

3️⃣ 尝试手动处理压缩(compress/gzip

client := &http.Client{Timeout: 40 * time.Second}
res, err := client.Do(req)
if err != nil {
	log.Fatal(err)
}
fmt.Println(res.Header)

var reader io.ReadCloser
switch res.Header.Get("Content-Encoding") {
case "gzip":
	reader, err = gzip.NewReader(res.Body)
default:
	reader = res.Body
}
defer reader.Close()

var data map[string]interface{}
err = json.NewDecoder(reader).Decode(&data)
if err != nil {
	log.Fatalf("解码请求:%v", err)
}

fmt.Println(data) 🐧🐧 // map[data:[map[CH_52WEEK_HIGH_PRICE:994 CH_52WEEK_LOW_PRICE:438.35 CH_CLOSING_PRICE:543.55 CH_ISIN:INE982J01020 CH_LAST_TRADED_PRICE:542.2 CH_MARKET_TYPE:N ...
英文:

1️⃣ decoding error handling was missed

err := json.NewDecoder(res.Body).Decode(&amp;data)
if err != nil {
log.Fatalf(&quot;decode request: %v&quot;, err)
}
invalid character &#39;\x1f&#39; looking for beginning of value

2️⃣ looks like the response data has been compressed (gzip data start with the magic sequence 0x1f 0x8b). If you check response's Headers you see

...
Content-Encoding:[gzip] &#128072;&#127995;&#128072;&#127995;&#128072;&#127995;
Content-Length:[1890] 
Content-Type:[application/json; charset=utf-8] 
...

that it looks like the truth

3️⃣ try to manually handling compression (compress/gzip)

	client := &amp;http.Client{Timeout: 40 * time.Second}
res, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
fmt.Println(res.Header)
var reader io.ReadCloser
switch res.Header.Get(&quot;Content-Encoding&quot;) {
case &quot;gzip&quot;:
reader, err = gzip.NewReader(res.Body)
default:
reader = res.Body
}
defer reader.Close()
var data map[string]interface{}
err = json.NewDecoder(reader).Decode(&amp;data)
if err != nil {
log.Fatalf(&quot;decode request: %v&quot;, err)
}
fmt.Println(data) &#128072;&#127995; // map[data:[map[CH_52WEEK_HIGH_PRICE:994 CH_52WEEK_LOW_PRICE:438.35 CH_CLOSING_PRICE:543.55 CH_ISIN:INE982J01020 CH_LAST_TRADED_PRICE:542.2 CH_MARKET_TYPE:N ...

huangapple
  • 本文由 发表于 2023年1月27日 00:12:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75248772.html
匿名

发表评论

匿名网友

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

确定