forked from Versent/saml2aws
-
Notifications
You must be signed in to change notification settings - Fork 0
/
form.go
90 lines (74 loc) · 2.09 KB
/
form.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package page
import (
"fmt"
"net/http"
"net/url"
"strings"
"github.com/pkg/errors"
"github.com/PuerkitoBio/goquery"
"github.com/versent/saml2aws/pkg/provider"
)
type Form struct {
URL string
Method string
Values *url.Values
}
func (form *Form) BuildRequest() (*http.Request, error) {
values := strings.NewReader(form.Values.Encode())
req, err := http.NewRequest(form.Method, form.URL, values)
if err != nil {
return nil, errors.Wrap(err, "error building request")
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
return req, nil
}
func (form *Form) Submit(client *provider.HTTPClient) (*http.Response, error) {
if req, err := form.BuildRequest(); err != nil {
return nil, errors.Wrap(err, "error building request")
} else if res, err := client.Do(req); err != nil {
return nil, errors.Wrap(err, "error submitting form")
} else {
return res, nil
}
}
// If the document has multiple forms, the first form with an `action` attribute will be parsed.
// You can specify the exact form using a CSS filter.
func NewFormFromDocument(doc *goquery.Document, formFilter string) (*Form, error) {
form := Form{Method: "POST"}
if formFilter == "" {
formFilter = "form[action]"
}
formSelection := doc.Find(formFilter).First()
if formSelection.Size() != 1 {
return nil, fmt.Errorf("could not find form")
}
attrValue, ok := formSelection.Attr("action");
if !ok {
return nil, fmt.Errorf("could not extract form action")
}
form.URL = attrValue
attrValue, ok = formSelection.Attr("method")
if ok {
form.Method = strings.ToUpper(attrValue)
}
form.Values = &url.Values{}
formSelection.Find("input").Each(func(_ int, s *goquery.Selection) {
name, ok := s.Attr("name")
if !ok {
return
}
val, ok := s.Attr("value")
if !ok {
return
}
form.Values.Add(name, val)
})
return &form, nil
}
func NewFormFromResponse(res *http.Response, formFilter string) (*Form, error) {
doc, err := goquery.NewDocumentFromResponse(res)
if err != nil {
return nil, errors.Wrap(err, "failed to build document from response")
}
return NewFormFromDocument(doc, formFilter)
}