func (c *Context) makeHttpRequest(method string, call otto.FunctionCall) otto.Value { val := c.sendHttpRequest(method, call) callback := call.Argument(len(call.ArgumentList) - 1) if callback.IsFunction() { callback.Call(otto.Value{}, val) } return val }
func (c *Context) htmlParse(call otto.FunctionCall) otto.Value { doc, err := html.Parse(strings.NewReader(call.Argument(0).String())) if err != nil { c.Errorf("error parsing HTML: %s\n", err) return otto.Value{} } val, err := c.vm.ToValue(asNode(doc, c.vm)) if err != nil { panic(err) } return val }
func (c *Context) htmlParseFragment(call otto.FunctionCall) otto.Value { fragment := call.Argument(0).String() var ctx *html.Node arg1, _ := call.Argument(1).Export() if c, ok := arg1.(*node); ok { ctx = c.node } nodes, err := html.ParseFragment(strings.NewReader(fragment), ctx) if err != nil { c.Errorf("error parsing HTML fragment: %s\n", err) return otto.Value{} } values := make([]*node, len(nodes)) for ii, v := range nodes { values[ii] = asNode(v, c.vm) } val, err := c.vm.ToValue(values) if err != nil { panic(err) } return val }
func (n *node) Visit(call otto.FunctionCall) otto.Value { fn := call.Argument(0) if fn.IsFunction() { thisVal, err := n.vm.ToValue(nil) if err != nil { panic(err) } n.visit(n.node, func(node *html.Node) bool { nodeVal, err := n.vm.ToValue(asNode(node, n.vm)) if err != nil { panic(err) } res, err := fn.Call(thisVal, nodeVal) if err != nil { panic(err) } if b, _ := res.ToBoolean(); b { return true } return false }) } return otto.Value{} }
func (c *Context) sendHttpRequest(method string, call otto.FunctionCall) otto.Value { idx := 0 if method == "" { method = call.Argument(0).String() idx = 1 } method = strings.ToUpper(method) u := call.Argument(idx).String() idx++ var qs string data := call.Argument(idx) idx++ if data.IsObject() { values := make(url.Values) obj := data.Object() for _, k := range obj.Keys() { val, err := obj.Get(k) if err != nil { c.Errorf("error getting object key %q: %s", k, err) return otto.Value{} } values.Add(k, val.String()) qs = values.Encode() } } else if !data.IsUndefined() && !data.IsNull() { qs = data.String() } if len(qs) > 0 && !methodHasBody(method) { sep := "?" if strings.IndexByte(u, '?') >= 0 { sep = "&" } u += sep + qs } c.Debugf("%s - %s\n", method, u) req, err := http.NewRequest(method, u, nil) if err != nil { return c.responseError(err) } opts := call.Argument(idx) idx++ var cache bool if opts.IsObject() { obj := opts.Object() for _, k := range obj.Keys() { val, err := obj.Get(k) if err != nil { c.Errorf("error getting object key %q: %s", k, err) return otto.Value{} } switch strings.ToLower(k) { case "headers": if !val.IsObject() { c.Errorf("headers must be an object") return otto.Value{} } hobj := val.Object() for _, hk := range hobj.Keys() { hval, err := hobj.Get(hk) if err != nil { c.Errorf("error getting object key %q: %s", k, err) return otto.Value{} } req.Header.Add(hk, hval.String()) } case "cache": cache, _ = val.ToBoolean() } } } if len(qs) > 0 && methodHasBody(method) { req.Body = &readerCloser{strings.NewReader(qs)} if method == "POST" && len(req.Header["Content-Type"]) == 0 { req.Header.Set("Content-Type", "application/x-www-form-urlencoded") } } if cache && !methodHasBody(method) { // Try cache if entry, err := c.cache.cachedEntry(u); err == nil { c.Debugf("cached response from %s\n", u) return c.newHTTPResponse(u, entry.URL, entry.Data, entry.StatusCode, entry.Header) } } resp, err := c.httpClient().Do(req) if err != nil { return c.responseError(err) } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return c.responseError(err) } if cache && !methodHasBody(method) { // Save into cache if err := c.cache.cacheData(u, body, resp); err != nil { c.Debugf("error caching response from %s: %s\n", u, err) } } return c.newHTTPResponse(u, resp.Request.URL.String(), body, resp.StatusCode, resp.Header) }
func imageReader(call otto.FunctionCall) (io.Reader, error) { return strings.NewReader(call.Argument(0).String()), nil }