-
Notifications
You must be signed in to change notification settings - Fork 95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
please make Response.Unmarshal to accept io.Reader #80
Comments
The tricky part here would be fault detection Lines 26 to 32 in 3377102
We could potentially use a |
Bufio.reader will defeat the whole purpose of leaving it as a stream
The only way todo it to use the xml.unmarshaler interface
So if it has a property error it should decide error if not try to decode
the success data
…On Sun, Sep 18, 2022 at 8:34 PM Ilia Choly ***@***.***> wrote:
The tricky part here would be fault detection
https://github.com/kolo/xmlrpc/blob/3377102c83bd60413083d5c738173f7db6160698/response.go#L26-L32
We could potentially use a bufio.Reader to peek at the first N bytes of
the stream and use that to figure out if there was a fault.
—
Reply to this email directly, view it on GitHub
<#80 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AIIO4JGC4DDNJJ33IIH5OF3V66YHVANCNFSM5TPFI6CA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Why do you say that? There's no way to avoid using one when using the encoding/xml package. |
I will try to make a demo it might take a day or
Two
…On Sun, Sep 18, 2022 at 10:38 PM Ilia Choly ***@***.***> wrote:
Bufio.reader will defeat the whole purpose of leaving it as a stream
Why do you say that? There's no way to avoid using one when using the
encoding/xml package.
—
Reply to this email directly, view it on GitHub
<#80 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/AIIO4JC2RVTL4AFYI3MNEHLV67GZNANCNFSM5TPFI6CA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
you make a struct liket this type respData struct {
Suc any `xmlrpc:"suc"` // here will go the success data that that need to pe decoded on
Err *XmlRpcErr `xmlrpc:"err"` // here will go the data if the response body is an error
} now you make on it a custom UnmarshalXML method and check if the first element after I made a partial example go playground package main
import (
"encoding/xml"
"fmt"
"io"
"strings"
)
// XML-RPC response success body example
var sucResp = `
<?xml version='1.0'?>
<methodResponse>
<params>
<param>
<value>
<struct>
<member>
<name>name</name>
<value>
<string>jack</string>
</value>
</member>
</struct>
</value>
</param>
</params>
</methodResponse>
`
// XML-RPC response error body example
var errorResp = `
<?xml version='1.0'?>
<methodResponse>
<fault>
<value>
<struct>
<member>
<name>faultCode</name>
<value>
<int>400</int>
</value>
</member>
<member>
<name>faultString</name>
<value>
<string>Account not found</string>
</value>
</member>
</struct>
</value>
</fault>
</methodResponse>
`
func main() {
type SUC struct {
Name string `xmlrpc:"name"`
}
fmt.Println("---- parsing on success body ----")
err := XmlRpcDecoder(strings.NewReader(sucResp), &SUC{})
if err != nil {
fmt.Println("err", err)
}
fmt.Println("---- parsing on error body ----")
err = XmlRpcDecoder(strings.NewReader(errorResp), &SUC{})
if err != nil {
fmt.Println("err", err)
}
}
// XmlRpcErr XML-RPC response error
type XmlRpcErr struct {
FaultCode int `xmlrpc:"faultCode"`
FaultString string `xmlrpc:"faultString"`
}
func (e *XmlRpcErr) Error() string {
return fmt.Sprintf("xmlrpc error: %d - %s", e.FaultCode, e.FaultString)
}
// respData XML-RPC response data that holds both success and error data
type respData struct {
Suc any `xmlrpc:"suc"`
Err *XmlRpcErr `xmlrpc:"err"`
}
// UnmarshalXML checking if the xml-rpc body is a success or error
func (r *respData) UnmarshalXML(d *xml.Decoder, start xml.StartElement) error {
// decode inner elements
for {
t, err := d.Token()
if err != nil {
return fmt.Errorf("getting first element error: %w",err)
}
//var i any
switch tt := t.(type) {
case xml.StartElement:
switch tt.Name.Local {
case "params":
fmt.Printf("you decoding success data on r.Suc %T\n", r.Suc)
return d.DecodeElement(r.Suc, &tt)
case "fault":
fmt.Printf("you decoding error data on r.Err %T\n", r.Err)
return d.DecodeElement(r.Err, &tt)
}
case xml.EndElement:
if tt == start.End() {
return nil
}
}
}
}
// XmlRpcDecoder XML-RPC response decoder
func XmlRpcDecoder(body io.Reader, sucData any) error {
resp := &respData{Suc: sucData}
err := xml.NewDecoder(body).Decode(resp)
if err != nil {
return err
}
if resp.Err != nil {
return resp.Err
}
return nil
} |
sorry I am taking back my statement, I thought you wanted to read the whole body to memory and then decode it |
Please make Response.Unmarshal to accept io.Reader
it is better for performance if the xml.decoder gets a large http repose, it can read it directly from the socket rather then converting the whole response body with
io.ReadAll(resp.body)
to memory and then passing it to the xml.decoderthis is how I need to do it now
this is how it will be used after
The text was updated successfully, but these errors were encountered: