I'm calling the Wikipedia API in Go using the http
package. However, the response from Wikipedia is 200 OK and an empty body.
My code is below:
package main
import (
"fmt"
"net/http"
"net/url"
"os"
"strings"
)
const SECRET = "secret.txt"
const BASE = "https://en.wikipedia.org/w/api.php"
func main() {
secret, err := os.ReadFile(SECRET)
if err != nil {
panic(err)
}
userAgent := strings.TrimSpace(string(secret))
u, err := url.Parse(BASE)
if err != nil {
panic(err)
}
params := url.Values{
"action": {"query"},
"list": {"categorymembers"},
"cmtitle": {"Category:Physics"},
"cmlimit": {"10"},
"format": {"json"},
"formatversion": {"2"},
}
u.RawQuery = params.Encode()
req, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
panic(err)
}
req.Header.Set("User-Agent", userAgent)
fmt.Println(req.URL)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
fmt.Println(resp.StatusCode, resp.ContentLength)
fmt.Println(resp)
var body []byte
_, err = resp.Body.Read(body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}
When I use the generated URL in a web browser, it gives me a JSON output as expected. Why is this?
Using var body []byte
like this creates slice with a capacity 0. Passing this into Read()
means that it will try to fill the capacity-0 slice with bytes. Since the slice has no more capacity, it returns with no error, and with the "empty" slice.
Replacing it with body, err := io.ReadAll(resp.Body)
works, since io.ReadAll()
consumes the entire Reader and returns it as a []byte
.