Go lang RPC return EOF error
Я использую http для вызова RPC с кодом ниже
func (c *CallClient) Wallet(method string, req, rep interface{}) error {
client := &http.Client{}
data, _ := EncodeClientRequest(method, req)
reqest, _ := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
resp, err := client.Do(reqest)
if err != nil {
return err
}
defer resp.Body.Close()
io.Copy(ioutil.Discard, resp.Body)
return DecodeClientResponse(resp.Body, rep)
}
с EncodeClientRquest && DecodeClientResponse
// EncodeClientRequest кодирует параметры для запроса клиента JSON-RPC.
func EncodeClientRequest(method string, args interface{}) ([]byte, error) {
c := &clientRequest{
Version: "2.0",
Method: method,
Params: [1]interface{}{args},
Id: uint64(rand.Int63()),
}
return json.Marshal(c)
}
// DecodeClientResponse декодирует тело ответа клиентского запроса // в ответ интерфейса.
func DecodeClientResponse(r io.Reader, reply interface{}) error {
var c clientResponse
if err := json.NewDecoder(r).Decode(&c); err != nil {
return err
}
if c.Error != nil {
return fmt.Errorf("%v", c.Error)
}
if c.Result == nil {
return errors.New("result is null")
}
return json.Unmarshal(*c.Result, reply)
}
И я получил ошибку EOF.
1 ответ
Эта строка:
io.Copy(ioutil.Discard, resp.Body)
читает весь resp.Body
оставляя читателю больше нет байтов для чтения. Поэтому любые последовательные призывы к resp.Body.Read
вернет EOF и json.Decoder.Decode
метод использует io.Reader.Read
метод при декодировании содержимого данного читателя, так что...
И с тех пор resp.Body
является io.ReadCloser
Интерфейс, который не поддерживает "перемотку", и вы хотите читать содержимое тела более одного раза (ioutil.Discard и json.Decode), вам придется читать тело в переменную, которую вы можете перезаписать. прочитайте потом. Это зависит от вас, как вы это делаете, кусок байтов или bytes.Reader
, или что-то другое.
Пример использования bytes.Reader
:
func (c *CallClient) Wallet(method string, req, rep interface{}) error {
client := &http.Client{}
data, err := EncodeClientRequest(method, req)
if err != nil {
return err
}
reqest, err := http.NewRequest("POST", c.endpoint, bytes.NewBuffer(data))
if err != nil {
return err
}
resp, err := client.Do(reqest)
if err != nil {
return err
}
defer resp.Body.Close()
// get a reader that can be "rewound"
buf := bytes.NewBuffer(nil)
if _, err := io.Copy(buf, resp.Body); err != nil {
return err
}
br := bytes.NewReader(buf.Bytes())
if _, err := io.Copy(ioutil.Discard, br); err != nil {
return err
}
// rewind
if _, err := br.Seek(0, 0); err != nil {
return err
}
return DecodeClientResponse(br, rep)
}