// 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 }