1
0
mirror of https://github.com/MontFerret/ferret.git synced 2025-07-15 01:25:00 +02:00

Fixed headers (#348)

* Fixed headers

* Added e2e for static pages
This commit is contained in:
Tim Voronov
2019-08-04 17:25:47 -04:00
committed by GitHub
parent 5293561a89
commit 11bf8c365a
15 changed files with 107 additions and 36 deletions

View File

@ -3,6 +3,7 @@
### 0.8.2 ### 0.8.2
#### Fixed #### Fixed
- Scrolling position is not centered. - Scrolling position is not centered.
- Unable to set custom headers. [#348](https://github.com/MontFerret/ferret/pull/348)
- Unable to set custom logger fields. - Unable to set custom logger fields.
### 0.8.1 ### 0.8.1

View File

@ -0,0 +1,20 @@
LET url = @static + "/api/ts"
LET page = DOCUMENT(url, {
driver: "cdp",
headers: {
"Access-Control-Allow-Origin": "*",
"X-Request-Id": "foobar"
}
})
LET el = ELEMENT(page, "#headers")
LET actual = JSON_PARSE(el.innerText)
LET expected = {
"Access-Control-Allow-Origin": ["*"],
"X-Request-Id": ["foobar"]
}
RETURN EXPECT(expected, {
"Access-Control-Allow-Origin": actual["Access-Control-Allow-Origin"],
"X-Request-Id": actual["X-Request-Id"]
})

View File

@ -0,0 +1,20 @@
LET url = @static + "/api/ts"
LET page = DOCUMENT(url, {
driver: "http",
headers: {
"Access-Control-Allow-Origin": "*",
"X-Request-Id": "foobar"
}
})
LET el = ELEMENT(page, "#headers")
LET actual = JSON_PARSE(el.innerText)
LET expected = {
"Access-Control-Allow-Origin": ["*"],
"X-Request-Id": ["foobar"]
}
RETURN EXPECT(expected, {
"Access-Control-Allow-Origin": actual["Access-Control-Allow-Origin"],
"X-Request-Id": actual["X-Request-Id"]
})

View File

@ -0,0 +1,19 @@
LET google = DOCUMENT("https://www.google.com/", {
driver: "cdp",
userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
})
INPUT(google, 'input[name="q"]', @criteria)
CLICK(google, 'input[name="btnK"]')
WAIT_NAVIGATION(google)
FOR result IN ELEMENTS(google, '.g')
// filter out extra elements like videos and 'People also ask'
FILTER TRIM(result.attributes.class) == 'g'
RETURN {
title: INNER_TEXT(result, 'h3'),
description: INNER_TEXT(result, '.st'),
url: INNER_TEXT(result, 'cite')
}

View File

@ -166,14 +166,14 @@ func LoadHTMLPage(
} }
} }
if params.Header != nil { if params.Headers != nil {
j, err := json.Marshal(params.Header) j, err := json.Marshal(params.Headers)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for k := range params.Header { for k := range params.Headers {
logger. logger.
Debug(). Debug().
Timestamp(). Timestamp().

View File

@ -15,14 +15,18 @@ import (
"github.com/MontFerret/ferret/pkg/runtime/values/types" "github.com/MontFerret/ferret/pkg/runtime/values/types"
) )
// HTTPHeader HTTP header object // HTTPHeaders HTTP header object
type HTTPHeader map[string][]string type HTTPHeaders map[string][]string
func (h HTTPHeader) Type() core.Type { func NewHTTPHeaders(values map[string][]string) HTTPHeaders {
return HTTPHeaders(values)
}
func (h HTTPHeaders) Type() core.Type {
return HTTPHeaderType return HTTPHeaderType
} }
func (h HTTPHeader) String() string { func (h HTTPHeaders) String() string {
var buf bytes.Buffer var buf bytes.Buffer
for k := range h { for k := range h {
@ -32,12 +36,12 @@ func (h HTTPHeader) String() string {
return buf.String() return buf.String()
} }
func (h HTTPHeader) Compare(other core.Value) int64 { func (h HTTPHeaders) Compare(other core.Value) int64 {
if other.Type() != HTTPHeaderType { if other.Type() != HTTPHeaderType {
return Compare(HTTPHeaderType, other.Type()) return Compare(HTTPHeaderType, other.Type())
} }
oh := other.(HTTPHeader) oh := other.(HTTPHeaders)
if len(h) > len(oh) { if len(h) > len(oh) {
return 1 return 1
@ -56,11 +60,11 @@ func (h HTTPHeader) Compare(other core.Value) int64 {
return 0 return 0
} }
func (h HTTPHeader) Unwrap() interface{} { func (h HTTPHeaders) Unwrap() interface{} {
return h return h
} }
func (h HTTPHeader) Hash() uint64 { func (h HTTPHeaders) Hash() uint64 {
hash := fnv.New64a() hash := fnv.New64a()
hash.Write([]byte(h.Type().String())) hash.Write([]byte(h.Type().String()))
@ -96,12 +100,18 @@ func (h HTTPHeader) Hash() uint64 {
return hash.Sum64() return hash.Sum64()
} }
func (h HTTPHeader) Copy() core.Value { func (h HTTPHeaders) Copy() core.Value {
return *(&h) return *(&h)
} }
func (h HTTPHeader) MarshalJSON() ([]byte, error) { func (h HTTPHeaders) MarshalJSON() ([]byte, error) {
out, err := json.Marshal(map[string][]string(h)) headers := map[string]string{}
for key, val := range h {
headers[key] = strings.Join(val, ", ")
}
out, err := json.Marshal(headers)
if err != nil { if err != nil {
return nil, err return nil, err
@ -110,15 +120,15 @@ func (h HTTPHeader) MarshalJSON() ([]byte, error) {
return out, err return out, err
} }
func (h HTTPHeader) Set(key, value string) { func (h HTTPHeaders) Set(key, value string) {
textproto.MIMEHeader(h).Set(key, value) textproto.MIMEHeader(h).Set(key, value)
} }
func (h HTTPHeader) Get(key string) string { func (h HTTPHeaders) Get(key string) string {
return textproto.MIMEHeader(h).Get(key) return textproto.MIMEHeader(h).Get(key)
} }
func (h HTTPHeader) GetIn(_ context.Context, path []core.Value) (core.Value, error) { func (h HTTPHeaders) GetIn(_ context.Context, path []core.Value) (core.Value, error) {
if len(path) == 0 { if len(path) == 0 {
return values.None, nil return values.None, nil
} }

View File

@ -1,25 +1,26 @@
package drivers_test package drivers_test
import ( import (
"github.com/MontFerret/ferret/pkg/drivers"
"testing" "testing"
. "github.com/smartystreets/goconvey/convey" . "github.com/smartystreets/goconvey/convey"
"github.com/MontFerret/ferret/pkg/drivers"
) )
func TestHTTPHeader(t *testing.T) { func TestHTTPHeader(t *testing.T) {
Convey("HTTPHeader", t, func() { Convey("HTTPHeaders", t, func() {
Convey(".MarshalJSON", func() { Convey(".MarshalJSON", func() {
Convey("Should serialize header values", func() { Convey("Should serialize header values", func() {
headers := make(drivers.HTTPHeader) headers := make(drivers.HTTPHeaders)
headers["content-encoding"] = []string{"gzip"} headers["Content-Encoding"] = []string{"gzip"}
headers["content-type"] = []string{"text/html", "charset=utf-8"} headers["Content-Type"] = []string{"text/html", "charset=utf-8"}
out, err := headers.MarshalJSON() out, err := headers.MarshalJSON()
So(err, ShouldBeNil) So(err, ShouldBeNil)
So(string(out), ShouldEqual, `{"content-encoding":["gzip"],"content-type":["text/html","charset=utf-8"]}`) So(string(out), ShouldEqual, `{"Content-Encoding":"gzip","Content-Type":"text/html, charset=utf-8"}`)
}) })
}) })
}) })

View File

@ -76,9 +76,9 @@ func (drv *Driver) Open(ctx context.Context, params drivers.Params) (drivers.HTM
req.Header.Set("Cache-Control", "no-cache") req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Pragma", "no-cache") req.Header.Set("Pragma", "no-cache")
if params.Header != nil { if params.Headers != nil {
for k := range params.Header { for k := range params.Headers {
req.Header.Add(k, params.Header.Get(k)) req.Header.Add(k, params.Headers.Get(k))
logger. logger.
Debug(). Debug().

View File

@ -14,7 +14,7 @@ type (
UserAgent string UserAgent string
KeepCookies bool KeepCookies bool
Cookies []HTTPCookie Cookies []HTTPCookie
Header HTTPHeader Headers HTTPHeaders
Viewport *Viewport Viewport *Viewport
} }
) )

View File

@ -3,7 +3,7 @@ package drivers
import "github.com/MontFerret/ferret/pkg/runtime/core" import "github.com/MontFerret/ferret/pkg/runtime/core"
var ( var (
HTTPHeaderType = core.NewType("HTTPHeader") HTTPHeaderType = core.NewType("HTTPHeaders")
HTTPCookieType = core.NewType("HTTPCookie") HTTPCookieType = core.NewType("HTTPCookie")
HTMLElementType = core.NewType("HTMLElement") HTMLElementType = core.NewType("HTMLElement")
HTMLDocumentType = core.NewType("HTMLDocument") HTMLDocumentType = core.NewType("HTMLDocument")

View File

@ -27,7 +27,7 @@ type PageLoadParams struct {
// keepCookies (Boolean) - Optional, boolean value indicating whether to use cookies from previous sessions. // keepCookies (Boolean) - Optional, boolean value indicating whether to use cookies from previous sessions.
// i.e. not to open a page in the Incognito mode. // i.e. not to open a page in the Incognito mode.
// cookies (HTTPCookie) - Optional, set of HTTP cookies. // cookies (HTTPCookie) - Optional, set of HTTP cookies.
// header (HTTPHeader) - Optional, HTTP headers. // headers (HTTPHeaders) - Optional, HTTP headers.
// viewport (Viewport) - Optional, viewport params. // viewport (Viewport) - Optional, viewport params.
// @returns (HTMLPage) - Returns loaded HTML page. // @returns (HTMLPage) - Returns loaded HTML page.
func Open(ctx context.Context, args ...core.Value) (core.Value, error) { func Open(ctx context.Context, args ...core.Value) (core.Value, error) {
@ -147,15 +147,15 @@ func newPageLoadParams(url values.String, arg core.Value) (PageLoadParams, error
res.Cookies = cookies res.Cookies = cookies
} }
header, exists := obj.Get(values.NewString("header")) headers, exists := obj.Get(values.NewString("headers"))
if exists { if exists {
if err := core.ValidateType(header, types.Object); err != nil { if err := core.ValidateType(headers, types.Object); err != nil {
return res, err return res, err
} }
header := parseHeader(header.(*values.Object)) header := parseHeader(headers.(*values.Object))
res.Header = header res.Headers = header
} }
viewport, exists := obj.Get(values.NewString("viewport")) viewport, exists := obj.Get(values.NewString("viewport"))
@ -292,10 +292,10 @@ func parseCookie(value core.Value) (drivers.HTTPCookie, error) {
return cookie, err return cookie, err
} }
func parseHeader(header *values.Object) drivers.HTTPHeader { func parseHeader(headers *values.Object) drivers.HTTPHeaders {
res := make(drivers.HTTPHeader) res := make(drivers.HTTPHeaders)
header.ForEach(func(value core.Value, key string) bool { headers.ForEach(func(value core.Value, key string) bool {
res.Set(key, value.String()) res.Set(key, value.String())
return true return true