-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathqurl.go
73 lines (66 loc) · 1.71 KB
/
qurl.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
// Copyright 2017 The qurl Authors. All rights reserved.
package qurl
import (
"net/http"
"net/url"
"github.com/PuerkitoBio/goquery"
)
// QURL is the main interface for the microservice.
type QURL struct {
}
// Query queries the URL and process all the data we want to fetch.
func (q *QURL) Query(ir IRequest, params url.Values) (*Response, error) {
url := params.Get("url")
response := NewResponse()
response.URL = url
// Fetch URL content
resp, err := ir.Fetch(url)
if err != nil {
return response, err
}
response.Status = resp.StatusCode
err = q.processHeaders(params, resp.Header, response)
if err != nil {
return nil, err
}
err = q.processSelectors(params, resp, response)
if err != nil {
return nil, err
}
return response, nil
}
// processHeaders ...
func (q *QURL) processHeaders(params url.Values, headers http.Header, response *Response) error {
for _, v := range params["header"] {
response.Headers[v] = headers[v]
}
return nil
}
// processSelectors ...
func (q *QURL) processSelectors(params url.Values, resp *http.Response, response *Response) error {
// Build a DOM from response
doc, err := goquery.NewDocumentFromResponse(resp)
if err != nil {
return err
}
// Query the DOM with all selectors
for _, v := range params["selector"] {
// Process matching nodes
doc.Find(v).Each(func(index int, selection *goquery.Selection) {
// Node text
element := &element{
Text: selection.Text(),
}
// Node attributes
for _, v := range selection.Nodes[0].Attr {
attr := &attribute{
Key: v.Key,
Value: v.Val,
}
element.Attributes = append(element.Attributes, attr)
}
response.Selectors[v] = append(response.Selectors[v], element)
})
}
return nil
}