// Write - Writes body to a log - `log.write`. func Write(ctx action.Map) (action.Map, error) { // Get string body from arguments if body, ok := ctx.Get("body").String(); ok { glog.Info(body) } return ctx, nil }
// Extract - Extracts patterns from context. func Extract(ctx action.Map) (action.Map, error) { // Pop regexp value containig RegexpMap value := ctx.Pop("regexp") // If value is nil return error if value.IsNil() { return nil, fmt.Errorf("Regexp value can not be empty.") } // Convert value to a map remap, ok := value.Map() if !ok { return nil, fmt.Errorf("Regexp value `%#v` is not valid.", ctx.Get("regexp").Value) } // Convert a map to RegexpMap re := mapToRegexpMap(remap) // Extract all Regexps result := re.Extract(ctx) // Merge result into context ctx.Merge(result) // Return context return ctx, nil }
// mapToRegexpMap - Converts a map to RegexpMap. func mapToRegexpMap(m action.Map) (remap RegexpMap) { remap = make(RegexpMap) for name := range m { // Get and convert value to a Map if m, ok := m.Get(name).Map(); ok { // Convert Map to Regexp re := mapToRegexp(m) // If Regexp name is empty use key value if re.Name == "" { re.Name = name } // Add Regexp to RegexpMap remap[name] = re } } return }
// mapToSelector - Creates an Extractor ouf of action.Map. func mapToSelector(m action.Map) selector.Extractor { // Selector path path, _ := m.Get("$path").String() // Selector extractor (it can be a string (attribute extractor), empty (text extractor)) // it can be another selector or map of selectors extract := m.Get("$extract") // If $extract is empty - extractor is TextExtractor if extract.IsNil() { return &selector.Selector{ Extractor: selector.TextExtractor, Path: path, } } // If $extract is a string, extractor is an attribute Extractor if name, ok := extract.String(); ok { return &selector.Selector{ Path: path, Extractor: selector.GetExtractor(name), } } // If $extract is a selector we have to create deep selector if IsSelector(extract) { return &selector.Selector{ Path: path, Extractor: ToSelector(extract), } } // Or a map of selectors if m, ok := extract.Map(); ok { return &selector.Selector{ Path: path, Extractor: MapSelectors(m), } } // $extract is not expected value return nil }
// Extract - Extracts pattern from value under Name key in ctx. func (r *Regexp) Extract(ctx action.Map) interface{} { // Get value `r.Name` from context value := ctx.Get(r.Name) // Pass if empty value if value.IsNil() { return nil } // Compile regular expression re, err := r.Compile() if err != nil { return nil } // If it's a string - use in it if strvalue, ok := value.String(); ok { // Find all if r.All { return re.FindAllString(strvalue, -1) } // Find one return re.FindString(strvalue) } // If it's a byte array - use in it if bytes, ok := value.Bytes(); ok { // Find all if r.All { return re.FindAll(bytes, -1) } // Find one return re.Find(bytes) } // If it's nothing else - pass return nil }
// MapSelectors - Iterates over map of selectors initializaing proper structures. func MapSelectors(selectors action.Map) (res selector.SelectorsMap) { res = selector.SelectorsMap{} // Map all values in selectors map for name := range selectors { // Get value by name value := selectors.Get(name) // If value is a selector create structures and continue if IsSelector(value) { res[name] = ToSelector(value) continue } // If it's not a selector but a map it's a map of selectors if m, ok := value.Map(); ok { res[name] = MapSelectors(m) } } // Return result return }
// mapToRegexp - Converts a map to Regexp. func mapToRegexp(m action.Map) *Regexp { var ( pattern, _ = m.Get("pattern").String() name, _ = m.Get("name").String() all, _ = m.Get("all").Bool() ) return &Regexp{ Pattern: pattern, Name: name, All: all, } }
// mapToAction - Converts a map to action. func mapToAction(m action.Map) *action.Action { if m == nil { return nil } var ( name, _ = m.Get("name").String() context, _ = m.Get("ctx").Map() next, _ = m.Get("next").Map() ) return &action.Action{ Name: name, Ctx: context, Next: mapToAction(next), } }
// Request - Sends a http request. func Request(ctx action.Map) (action.Map, error) { var ( uri, _ = ctx.Get("url").String() query = ctx.Pop("query") method = "GET" ) // Parse URL and join query u, err := joinURL(uri, query) if err != nil { return ctx, err } // Get method from context if m, ok := ctx.Pop("method").String(); ok { method = strings.ToUpper(m) } // Set scheme from context if scheme, ok := ctx.Pop("scheme").String(); ok { u.Scheme = scheme } // Set pathname from context if pathname, ok := ctx.Pop("pathname").String(); ok { u.Path = pathname } // Set hostname from context if hostname, ok := ctx.Pop("hostname").String(); ok { u.Host = hostname } // Set http scheme if empty if u.Scheme == "" { u.Scheme = "http" } // HTTP Request structure req := &http.Request{ URL: u, Method: method, } // Set header from context if reqhead, ok := ctx.Pop("header").Map(); ok { req.Header = make(http.Header) for key := range reqhead { if strvalue, ok := reqhead.Get(key).String(); ok { req.Header.Add(key, strvalue) } else if listvalue, ok := reqhead.Get(key).StringList(); ok { req.Header[key] = listvalue } } } if glog.V(3) { glog.Infof("http.request %s %s\n", method, u) } // Request body body := ctx.Pop("body") // Set request body if any and method is not GET if reqbody, ok := body.Reader(); ok && method != "GET" { defer func() { err := reqbody.Close() if err != nil && glog.V(2) { glog.Infof("error closing request body %v\n", err) } }() switch body.Value.(type) { case []byte: v, _ := body.Value.([]byte) req.ContentLength = int64(len(v)) case string: v, _ := body.Value.(string) req.ContentLength = int64(len(v)) default: if length, ok := ctx.Get("Content-Length").Int(); ok { req.ContentLength = int64(length) } else { // TODO: HTTP CHUNK return nil, ErrEmptyContentLength } } req.Body = reqbody } // Send request resp, err := http.DefaultClient.Do(req) if err != nil { if glog.V(2) { glog.Infof("http.response error %s %s - %v\n", method, u, err) } return ctx, err } // Response ctx.Add("status", resp.StatusCode) ctx.Add("header", headerToMap(resp.Header)) ctx.Add("body", resp.Body) ctx.Add("url", u.String()) // Log response if glog.V(3) { glog.Infof("http.response %s %s - %s\n", method, u, resp.Status) } // Return result return ctx, err }