mirror of
https://github.com/aclindsa/ofxgo.git
synced 2024-11-24 20:10:06 -05:00
Add Hack for Discover
Discover requires an exact set of headers in exact order, or it returns HTTP 403.
This commit is contained in:
parent
77b154695f
commit
22a6d65b98
@ -63,6 +63,7 @@ func GetClient(URL string, bc *BasicClient) Client {
|
|||||||
URL string
|
URL string
|
||||||
Func clientCreationFunc
|
Func clientCreationFunc
|
||||||
}{
|
}{
|
||||||
|
{"https://ofx.discovercard.com", NewDiscoverCardClient},
|
||||||
{"https://vesnc.vanguard.com/us/OfxDirectConnectServlet", NewVanguardClient},
|
{"https://vesnc.vanguard.com/us/OfxDirectConnectServlet", NewVanguardClient},
|
||||||
}
|
}
|
||||||
for _, client := range clients {
|
for _, client := range clients {
|
||||||
|
103
discovercard_client.go
Normal file
103
discovercard_client.go
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package ofxgo
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"crypto/tls"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DiscoverCardClient provides a Client implementation which handles
|
||||||
|
// DiscoverCard's broken HTTP header behavior. DiscoverCardClient uses default,
|
||||||
|
// non-zero settings, if its fields are not initialized.
|
||||||
|
type DiscoverCardClient struct {
|
||||||
|
*BasicClient
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewDiscoverCardClient returns a Client interface configured to handle
|
||||||
|
// Discover Card's brand of idiosyncracy
|
||||||
|
func NewDiscoverCardClient(bc *BasicClient) Client {
|
||||||
|
return &DiscoverCardClient{bc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func discoverCardHTTPPost(URL string, r io.Reader) (*http.Response, error) {
|
||||||
|
// Either convert or copy to a bytes.Buffer to be able to determine the
|
||||||
|
// request length for the Content-Length header
|
||||||
|
buf, ok := r.(*bytes.Buffer)
|
||||||
|
if !ok {
|
||||||
|
buf = &bytes.Buffer{}
|
||||||
|
_, err := io.Copy(buf, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
url, err := url.Parse(URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
path := url.Path
|
||||||
|
if path == "" {
|
||||||
|
path = "/"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Discover requires only these headers and in this exact order, or it
|
||||||
|
// returns HTTP 403
|
||||||
|
headers := fmt.Sprintf("POST %s HTTP/1.1\r\n"+
|
||||||
|
"Content-Type: application/x-ofx\r\n"+
|
||||||
|
"Host: %s\r\n"+
|
||||||
|
"Content-Length: %d\r\n"+
|
||||||
|
"Connection: Keep-Alive\r\n"+
|
||||||
|
"\r\n", path, url.Hostname(), buf.Len())
|
||||||
|
|
||||||
|
host := url.Host
|
||||||
|
if url.Port() == "" {
|
||||||
|
host += ":443"
|
||||||
|
}
|
||||||
|
|
||||||
|
// BUGBUG: cannot do defer conn.Close() until body is read,
|
||||||
|
// we are "leaking" a socket here, but it will be finalized
|
||||||
|
conn, err := tls.Dial("tcp", host, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprint(conn, headers)
|
||||||
|
_, err = io.Copy(conn, buf)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return http.ReadResponse(bufio.NewReader(conn), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscoverCardClient) RawRequest(URL string, r io.Reader) (*http.Response, error) {
|
||||||
|
if !strings.HasPrefix(URL, "https://") {
|
||||||
|
return nil, errors.New("Refusing to send OFX request with possible plain-text password over non-https protocol")
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := discoverCardHTTPPost(URL, r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
return nil, errors.New("OFXQuery request status: " + response.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscoverCardClient) RequestNoParse(r *Request) (*http.Response, error) {
|
||||||
|
return clientRequestNoParse(c, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *DiscoverCardClient) Request(r *Request) (*Response, error) {
|
||||||
|
return clientRequest(c, r)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user