コード例 #1
0
ファイル: http.go プロジェクト: crackcomm/go-core
// 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
}