mirror of
https://github.com/aclindsa/ofxgo.git
synced 2024-10-30 05:20:05 -04:00
Aaron Lindsay
119c01f99b
This also makes it possible to call this method for testing without making an HTTP request.
116 lines
3.2 KiB
Go
116 lines
3.2 KiB
Go
package ofxgo
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"net/http"
|
|
)
|
|
|
|
type Client struct {
|
|
// Request fields to overwrite with the client's values. If nonempty,
|
|
// defaults are used
|
|
SpecVersion string // VERSION in header
|
|
AppId string // SONRQ>APPID
|
|
AppVer string // SONRQ>APPVER
|
|
|
|
// Don't insert newlines or indentation when marshalling to SGML/XML
|
|
NoIndent bool
|
|
}
|
|
|
|
var defaultClient Client
|
|
|
|
func (c *Client) OfxVersion() string {
|
|
if len(c.SpecVersion) > 0 {
|
|
return c.SpecVersion
|
|
} else {
|
|
return "203"
|
|
}
|
|
}
|
|
|
|
func (c *Client) Id() String {
|
|
if len(c.AppId) > 0 {
|
|
return String(c.AppId)
|
|
} else {
|
|
return String("OFXGO")
|
|
}
|
|
}
|
|
|
|
func (c *Client) Version() String {
|
|
if len(c.AppVer) > 0 {
|
|
return String(c.AppVer)
|
|
} else {
|
|
return String("0001")
|
|
}
|
|
}
|
|
|
|
// Returns true if the marshaled XML should be indented (and contain newlines,
|
|
// since the two are linked in the current implementation)
|
|
func (c *Client) IndentRequests() bool {
|
|
return !c.NoIndent
|
|
}
|
|
|
|
// RawRequest is little more than a thin wrapper around http.Post
|
|
//
|
|
// In most cases, you should probably be using Request() instead, but
|
|
// RawRequest can be useful if you need to read the raw unparsed http response
|
|
// yourself (perhaps for downloading an OFX file for use by an external
|
|
// program, or debugging server behavior), or have a handcrafted request you'd
|
|
// like to try.
|
|
//
|
|
// Caveats: RawRequest does *not* take client settings into account as
|
|
// Request() does, so your particular server may or may not like whatever we
|
|
// read from 'r'. The caller is responsible for closing the http Response.Body
|
|
// (see the http module's documentation for more information)
|
|
func RawRequest(URL string, r io.Reader) (*http.Response, error) {
|
|
response, err := http.Post(URL, "application/x-ofx", r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if response.StatusCode != 200 {
|
|
return nil, errors.New("OFXQuery request status: " + response.Status)
|
|
}
|
|
|
|
return response, nil
|
|
}
|
|
|
|
// RequestNoParse marshals a Request object into XML, makes an HTTP request,
|
|
// and returns the raw HTTP response. Unlike RawRequest(), it takes client
|
|
// settings into account. Unlike Request(), it doesn't parse the response into
|
|
// a Request object.
|
|
//
|
|
// Caveat: The caller is responsible for closing the http Response.Body (see
|
|
// the http module's documentation for more information)
|
|
func (c *Client) RequestNoParse(r *Request) (*http.Response, error) {
|
|
r.SetClientFields(c)
|
|
|
|
b, err := r.Marshal()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return RawRequest(r.URL, b)
|
|
}
|
|
|
|
// Request marshals a Request object into XML, makes an HTTP request against
|
|
// it's URL, and then unmarshals the response into a Response object.
|
|
//
|
|
// Before being marshaled, some of the the Request object's values are
|
|
// overwritten, namely those dictated by the Client's configuration (Version,
|
|
// AppId, AppVer fields), and the client's curren time (DtClient). These are
|
|
// updated in place in the supplied Request object so they may later be
|
|
// inspected by the caller.
|
|
func (c *Client) Request(r *Request) (*Response, error) {
|
|
response, err := c.RequestNoParse(r)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer response.Body.Close()
|
|
|
|
ofxresp, err := ParseResponse(response.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ofxresp, nil
|
|
}
|