Example #1
0
func (c *Couch) req(method, url string, headers http.Header, body []byte, user *url.Userinfo) (*http.Response, error) {
	if c.send == nil {
		panic("send func not set")
	}
	// Create a new request
	req, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}

	req.Close = true
	req.TransferEncoding = []string{"chunked"}
	req.Body = ioutil.NopCloser(bytes.NewBuffer(body))
	req.ContentLength = int64(len(body))

	// Set headers
	if headers != nil {
		req.Header = headers
	}

	// Set auth credentials
	if user != nil {
		if p, ok := user.Password(); ok {
			req.SetBasicAuth(user.Username(), p)
		}
	}

	resp, err := c.send(req)
	if err != nil {
		return nil, err
	}

	return resp, nil
}
Example #2
0
func getCredentials(a httpRequestArgs,
	hdrCreds *url.Userinfo, auths []string) (datastore.Credentials, errors.Error) {
	var creds datastore.Credentials

	if hdrCreds != nil {
		// Credentials are in the request URL:
		username := hdrCreds.Username()
		password, _ := hdrCreds.Password()
		creds = make(datastore.Credentials)
		creds[username] = password
		return creds, nil
	}
	if len(auths) > 0 {
		// Credentials are in the request header:
		// TODO: implement non-Basic auth (digest, ntlm)
		auth := auths[0]
		if strings.HasPrefix(auth, "Basic ") {
			encoded_creds := strings.Split(auth, " ")[1]
			decoded_creds, err := base64.StdEncoding.DecodeString(encoded_creds)
			if err != nil {
				return creds, errors.NewServiceErrorBadValue(err, CREDS)
			}
			// Authorization header is in format "user:pass"
			// per http://tools.ietf.org/html/rfc1945#section-10.2
			u_details := strings.Split(string(decoded_creds), ":")
			switch len(u_details) {
			case 2:
				creds = make(datastore.Credentials)
				creds[u_details[0]] = u_details[1]
			case 3:
				creds = make(datastore.Credentials)
				// Support usernames like "local:xxx" or "admin:xxx"
				creds[strings.Join(u_details[:2], ":")] = u_details[2]
			default:
				// Authorization header format is incorrect
				return creds, errors.NewServiceErrorBadValue(nil, CREDS)
			}
		}
		return creds, nil
	}
	// Credentials may be in request arguments:
	cred_data, err := a.getCredentials()
	if err == nil && len(cred_data) > 0 {
		creds = make(datastore.Credentials)
		for _, cred := range cred_data {
			user, user_ok := cred["user"]
			pass, pass_ok := cred["pass"]
			if user_ok && pass_ok {
				creds[user] = pass
			} else {
				err = errors.NewServiceErrorMissingValue("user or pass")
				break
			}
		}
	}
	return creds, err
}
Example #3
0
// ApacheUser formats user info in a request in apache style. That is missing
// or empty user name is formatted as '-'
func ApacheUser(user *url.Userinfo) string {
	result := "-"
	if user != nil {
		if name := user.Username(); name != "" {
			result = name
		}
	}
	return result
}
Example #4
0
func basicAuthTestcase(t *testing.T, upstreamUser, clientUser *url.Userinfo) {
	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		u, p, ok := r.BasicAuth()

		if ok {
			w.Write([]byte(u))
		}
		if ok && p != "" {
			w.Write([]byte(":"))
			w.Write([]byte(p))
		}
	}))
	defer backend.Close()

	backURL, err := url.Parse(backend.URL)
	if err != nil {
		t.Fatalf("Failed to parse URL: %v", err)
	}
	backURL.User = upstreamUser

	p := &Proxy{
		Next:      httpserver.EmptyNext,
		Upstreams: []Upstream{newFakeUpstream(backURL.String(), false)},
	}
	r, err := http.NewRequest("GET", "/foo", nil)
	if err != nil {
		t.Fatalf("Failed to create request: %v", err)
	}
	if clientUser != nil {
		u := clientUser.Username()
		p, _ := clientUser.Password()
		r.SetBasicAuth(u, p)
	}
	w := httptest.NewRecorder()

	p.ServeHTTP(w, r)

	if w.Code != 200 {
		t.Fatalf("Invalid response code: %d", w.Code)
	}
	body, _ := ioutil.ReadAll(w.Body)

	if clientUser != nil {
		if string(body) != clientUser.String() {
			t.Fatalf("Invalid auth info: %s", string(body))
		}
	} else {
		if upstreamUser != nil {
			if string(body) != upstreamUser.String() {
				t.Fatalf("Invalid auth info: %s", string(body))
			}
		} else {
			if string(body) != "" {
				t.Fatalf("Invalid auth info: %s", string(body))
			}
		}
	}
}
Example #5
0
func (sm *Manager) Login(ctx context.Context, u *url.Userinfo) error {
	req := types.Login{
		This: sm.Reference(),
	}

	if u != nil {
		req.UserName = u.Username()
		if pw, ok := u.Password(); ok {
			req.Password = pw
		}
	}

	login, err := methods.Login(ctx, sm.client, &req)
	if err != nil {
		return err
	}

	sm.userSession = &login.Returnval
	return nil
}
Example #6
0
// PGUrl returns a postgres connection url which connects to this server with the given user, and a
// cleanup function which must be called after all connections created using the connection url have
// been closed.
//
// In order to connect securely using postgres, this method will create temporary on-disk copies of
// certain embedded security certificates. The certificates will be created in a new temporary
// directory. The returned cleanup function will delete this temporary directory.
// Note that two calls to this function for the same `user` will generate different
// copies of the certificates, so the cleanup function must always be called.
//
// Args:
//  prefix: A prefix to be prepended to the temp file names generated, for debugging.
func PGUrl(t testing.TB, servingAddr, prefix string, user *url.Userinfo) (url.URL, func()) {
	host, port, err := net.SplitHostPort(servingAddr)
	if err != nil {
		t.Fatal(err)
	}

	tempDir, err := ioutil.TempDir("", prefix)
	if err != nil {
		t.Fatal(err)
	}

	caPath := filepath.Join(security.EmbeddedCertsDir, security.EmbeddedCACert)
	certPath := filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.crt", user.Username()))
	keyPath := filepath.Join(security.EmbeddedCertsDir, fmt.Sprintf("%s.key", user.Username()))

	// Copy these assets to disk from embedded strings, so this test can
	// run from a standalone binary.
	tempCAPath := securitytest.RestrictedCopy(t, caPath, tempDir, "ca")
	tempCertPath := securitytest.RestrictedCopy(t, certPath, tempDir, "cert")
	tempKeyPath := securitytest.RestrictedCopy(t, keyPath, tempDir, "key")
	options := url.Values{}
	options.Add("sslmode", "verify-full")
	options.Add("sslrootcert", tempCAPath)
	options.Add("sslcert", tempCertPath)
	options.Add("sslkey", tempKeyPath)

	return url.URL{
			Scheme:   "postgres",
			User:     user,
			Host:     net.JoinHostPort(host, port),
			RawQuery: options.Encode(),
		}, func() {
			if err := os.RemoveAll(tempDir); err != nil {
				// Not Fatal() because we might already be panicking.
				t.Error(err)
			}
		}
}
Example #7
0
// Send constructs and sends an HTTP request.
func (s *Session) Send(r *Request) (response *Response, err error) {
	r.Method = strings.ToUpper(r.Method)
	//
	// Create a URL object from the raw url string.  This will allow us to compose
	// query parameters programmatically and be guaranteed of a well-formed URL.
	//
	u, err := url.Parse(r.Url)
	if err != nil {
		s.log("URL", r.Url)
		s.log(err)
		return
	}
	//
	// Default query parameters
	//
	p := Params{}
	if s.Params != nil {
		for k, v := range *s.Params {
			p[k] = v
		}
	}
	//
	// User-supplied params override default
	//
	if r.Params != nil {
		for k, v := range *r.Params {
			p[k] = v
		}
	}
	//
	// Encode parameters
	//
	vals := u.Query()
	for k, v := range p {
		vals.Set(k, v)
	}
	u.RawQuery = vals.Encode()
	//
	// Create a Request object; if populated, Data field is JSON encoded as
	// request body
	//
	header := http.Header{}
	if s.Header != nil {
		for k, _ := range *s.Header {
			v := s.Header.Get(k)
			header.Set(k, v)
		}
	}
	var req *http.Request
	var buf *bytes.Buffer
	if r.Payload != nil {
		if r.RawPayload {
			var ok bool
			// buf can be nil interface at this point
			// so we'll do extra nil check
			buf, ok = r.Payload.(*bytes.Buffer)
			if !ok {
				err = errors.New("Payload must be of type *bytes.Buffer if RawPayload is set to true")
				return
			}
		} else {
			var b []byte
			b, err = json.Marshal(&r.Payload)
			if err != nil {
				s.log(err)
				return
			}
			buf = bytes.NewBuffer(b)
		}
		if buf != nil {
			req, err = http.NewRequest(r.Method, u.String(), buf)
		} else {
			req, err = http.NewRequest(r.Method, u.String(), nil)
		}
		if err != nil {
			s.log(err)
			return
		}
		header.Add("Content-Type", "application/json")
	} else { // no data to encode
		req, err = http.NewRequest(r.Method, u.String(), nil)
		if err != nil {
			s.log(err)
			return
		}

	}
	//
	// Merge Session and Request options
	//
	var userinfo *url.Userinfo
	if u.User != nil {
		userinfo = u.User
	}
	if s.Userinfo != nil {
		userinfo = s.Userinfo
	}
	// Prefer Request's user credentials
	if r.Userinfo != nil {
		userinfo = r.Userinfo
	}
	if r.Header != nil {
		for k, v := range *r.Header {
			header.Set(k, v[0]) // Is there always guarnateed to be at least one value for a header?
		}
	}
	if header.Get("Accept") == "" {
		header.Add("Accept", "application/json") // Default, can be overridden with Opts
	}
	req.Header = header
	//
	// Set HTTP Basic authentication if userinfo is supplied
	//
	if userinfo != nil {
		pwd, _ := userinfo.Password()
		req.SetBasicAuth(userinfo.Username(), pwd)
		if u.Scheme != "https" {
			s.log("WARNING: Using HTTP Basic Auth in cleartext is insecure.")
		}
	}
	//
	// Execute the HTTP request
	//

	// Debug log request
	s.log("--------------------------------------------------------------------------------")
	s.log("REQUEST")
	s.log("--------------------------------------------------------------------------------")
	s.log(pretty(req))
	s.log("Payload:")
	if r.RawPayload && s.Log && buf != nil {
		s.log(base64.StdEncoding.EncodeToString(buf.Bytes()))
	} else {
		s.log(pretty(r.Payload))
	}
	r.timestamp = time.Now()
	var client *http.Client
	if s.Client != nil {
		client = s.Client
	} else {
		client = &http.Client{}
		s.Client = client
	}
	resp, err := client.Do(req)
	if err != nil {
		s.log(err)
		return
	}
	defer resp.Body.Close()
	r.status = resp.StatusCode
	r.response = resp
	//
	// Unmarshal
	//
	r.body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		s.log(err)
		return
	}
	if string(r.body) != "" {
		if resp.StatusCode < 300 && r.Result != nil {
			err = json.Unmarshal(r.body, r.Result)
		}
		if resp.StatusCode >= 400 && r.Error != nil {
			json.Unmarshal(r.body, r.Error) // Should we ignore unmarshall error?
		}
	}
	rsp := Response(*r)
	response = &rsp

	// Debug log response
	s.log("--------------------------------------------------------------------------------")
	s.log("RESPONSE")
	s.log("--------------------------------------------------------------------------------")
	s.log("Status: ", response.status)
	s.log("Header:")
	s.log(pretty(response.HttpResponse().Header))
	s.log("Body:")

	if response.body != nil {
		raw := json.RawMessage{}
		if json.Unmarshal(response.body, &raw) == nil {
			s.log(pretty(&raw))
		} else {
			s.log(pretty(response.RawText()))
		}
	} else {
		s.log("Empty response body")
	}

	return
}
Example #8
0
func basicAuth(user *url.Userinfo) string {
	username := user.Username()
	password, _ := user.Password()
	return "Basic " + base64.StdEncoding.EncodeToString([]byte(username+":"+password))
}
Example #9
0
// Send constructs and sends an HTTP request.
func (s *Session) SendPB(r *Request) (response *Response, err error) {
	startTime := time.Now()
	r.Method = strings.ToUpper(r.Method)
	u, err := url.Parse(r.Url)
	if err != nil {
		s.log("URL", r.Url)
		s.log(err)
		return
	}
	p := Params{}
	if s.Params != nil {
		for k, v := range *s.Params {
			p[k] = v
		}
	}
	if r.Params != nil {
		for k, v := range *r.Params {
			p[k] = v
		}
	}
	vals := u.Query()
	for k, v := range p {
		vals.Set(k, v)
	}
	u.RawQuery = vals.Encode()
	header := http.Header{}
	if s.Header != nil {
		for k := range *s.Header {
			v := s.Header.Get(k)
			header.Set(k, v)
		}
	}
	var req *http.Request
	var buf *bytes.Buffer
	if r.Payload != nil {
		if r.RawPayload {
			var ok bool
			buf, ok = r.Payload.(*bytes.Buffer)
			if !ok {
				err = errors.New("Payload must be of type *bytes.Buffer if RawPayload is set to true")
				return
			}
		} else {
			var b []byte
			b, err = json.Marshal(&r.Payload)
			if err != nil {
				s.log(err)
				return
			}
			buf = bytes.NewBuffer(b)
		}
		if buf != nil {
			req, err = http.NewRequest(r.Method, u.String(), buf)
		} else {
			req, err = http.NewRequest(r.Method, u.String(), nil)
		}
		if err != nil {
			s.log(err)
			return
		}
		header.Add("Content-Type", "application/json")
	} else { // no data to encode
		req, err = http.NewRequest(r.Method, u.String(), nil)
		if err != nil {
			s.log(err)
			return
		}

	}
	var userinfo *url.Userinfo
	if u.User != nil {
		userinfo = u.User
	}
	if s.Userinfo != nil {
		userinfo = s.Userinfo
	}
	// Prefer Request's user credentials
	if r.Userinfo != nil {
		userinfo = r.Userinfo
	}
	if r.Header != nil {
		for k, v := range *r.Header {
			header.Set(k, v[0]) // Is there always guarnateed to be at least one value for a header?
		}
	}
	if header.Get("Accept") == "" {
		header.Add("Accept", "application/octet-stream")
	}
	req.Header = header
	if userinfo != nil {
		pwd, _ := userinfo.Password()
		req.SetBasicAuth(userinfo.Username(), pwd)
		if u.Scheme != "https" {
			s.log("WARNING: Using HTTP Basic Auth in cleartext is insecure.")
		}
	}
	s.log("--------------------------------------------------------------------------------")
	s.log("REQUEST")
	s.log("--------------------------------------------------------------------------------")
	s.log(pretty(req))
	s.log("Payload:")
	if r.RawPayload && s.Log && buf != nil {
		s.log(base64.StdEncoding.EncodeToString(buf.Bytes()))
	} else {
		s.log(pretty(r.Payload))
	}
	r.timestamp = time.Now()
	var client *http.Client
	if s.Client != nil {
		client = s.Client
	} else {
		//client = NewClientSupportTimeout()
		client = &http.Client{}
	}
	resp, err := client.Do(req)
	if err != nil {
		s.log(err)
		fmt.Printf("[Neo4J-HTTP] | %s | %s | %s \n", r.Url, r.Method, err.Error())
		return
	}
	defer resp.Body.Close()
	r.status = resp.StatusCode
	r.response = resp
	r.body, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		s.log(err)
		return
	}
	if string(r.body) != "" {
		if resp.StatusCode < 300 && r.Result != nil {
			proto.Unmarshal(r.body, r.Result.(proto.Message))
		}
		//ignore 4xx or 5xx response
	}
	rsp := Response(*r)
	response = &rsp
	s.log("--------------------------------------------------------------------------------")
	s.log("RESPONSE")
	s.log("--------------------------------------------------------------------------------")
	s.log("Status: ", response.status)
	s.log("Header:")
	s.log(pretty(response.HttpResponse().Header))
	s.log("Body:")
	if response.body != nil {
		raw := json.RawMessage{}
		if json.Unmarshal(response.body, &raw) == nil {
			s.log(pretty(&raw))
		} else {
			s.log(pretty(response.RawText()))
		}
	} else {
		s.log("Empty response body")
	}
	elapsed := float64(time.Since(startTime).Nanoseconds()) / 1000000.0
	if elapsed > 100 {
		fmt.Printf("[Neo4J-HTTP] | %d | %s | %s | %d | %.2fms | \n", time.Now().UnixNano()/1e6, r.Url, r.Method, resp.StatusCode, elapsed)
	}
	return
}
Example #10
0
// Send constructs and sends an HTTP request.
func (s *Session) Send(inputRequest *Request, responseResult JsonDeserializer) (response *Response, err error) {

	// Allocate a Response object and initialize its Result field with the responseResult we expect to see
	response = &Response{
		Result: responseResult,
	}

	// Extract Url
	parsedUrl, err := url.Parse(inputRequest.Url)
	if err != nil {
		s.log("URL", inputRequest.Url)
		s.log(err)
		return
	}

	// Encode query parameters
	if inputRequest.QueryParams != nil {
		vals := parsedUrl.Query()
		for k, v := range *inputRequest.QueryParams {
			vals.Set(k, v)
		}
		parsedUrl.RawQuery = vals.Encode()
	}

	// Add generic headers
	header := http.Header{}
	if s.Header != nil {
		for k, _ := range *s.Header {
			v := s.Header.Get(k)
			header.Set(k, v)
		}
	}

	//
	// Add Session specific headers
	//
	// Kill Bill Tenant  headers from the Session
	if s.ApiKey != "" && s.ApiSecret != "" {
		header.Set("X-Killbill-ApiKey", s.ApiKey)
		header.Set("X-Killbill-ApiSecret", s.ApiSecret)
	}
	// JSESSIONID
	if s.JsessionId != "" {
		header.Set("Cookie", s.JsessionId)
	}

	if inputRequest.Header != nil {
		for k, v := range *inputRequest.Header {
			header.Set(k, v[0])
		}
	}

	// TODO only accept
	if header.Get("Accept") == "" {
		header.Add("Accept", "application/json")
	}

	// Create the http request
	var req *http.Request
	var buf *bytes.Buffer
	inputRequest.Method = strings.ToUpper(inputRequest.Method)
	if inputRequest.Body != nil {
		var b []byte
		b, err = json.Marshal(&inputRequest.Body)
		if err != nil {
			s.log(err)
			return
		}

		//fmt.Printf("JSON :")
		//fmt.Println(string(b))
		buf = bytes.NewBuffer(b)
		if buf != nil {
			req, err = http.NewRequest(inputRequest.Method, parsedUrl.String(), buf)
		} else {
			req, err = http.NewRequest(inputRequest.Method, parsedUrl.String(), nil)
		}
		if err != nil {
			s.log(err)
			return
		}
		// TODO only support application/json
		header.Add("Content-Type", "application/json")
	} else {
		req, err = http.NewRequest(inputRequest.Method, parsedUrl.String(), nil)
		if err != nil {
			s.log(err)
			return
		}

	}
	// Set all headers in the request
	req.Header = header

	// Basic Auth for the request
	var userInfo *url.Userinfo
	if parsedUrl.User != nil {
		userInfo = parsedUrl.User
	}
	if s.Userinfo != nil {
		userInfo = s.Userinfo
	}
	if userInfo != nil {
		pwd, _ := userInfo.Password()
		req.SetBasicAuth(userInfo.Username(), pwd)
	}

	// Debug log request
	s.log("--------------------------------------------------------------------------------")
	s.log("REQUEST")
	s.log("--------------------------------------------------------------------------------")
	s.log(pretty(req))
	s.log("Body:")

	s.log(pretty(inputRequest.Body))

	// TODO we need to capture elapsed time
	response.timestamp = time.Now()

	//
	// Execute the HTTP request
	//
	var client *http.Client
	if s.Client != nil {
		client = s.Client
	} else {
		client = &http.Client{}
	}
	resp, err := client.Do(req)
	if err != nil {
		s.log(err)
		return
	}
	// Don't forget to close the stream on return
	defer resp.Body.Close()

	// Extract and set JSESSIONID  into session
	s.setJsessionId(resp.Header)

	//
	// Set Response
	//
	response.status = resp.StatusCode
	response.httpResponse = resp
	// Read body if status if good
	if resp.StatusCode < 300 {
		response.body, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			s.log(err)
			return
		}
	} else {
		err = errors.New(fmt.Sprintf("%s%d", "Call failed with http status ", resp.StatusCode))
	}
	// TODO Only work for json
	// Deserialize json if Result was provided
	if string(response.body) != "" && response.Result != nil {
		err = response.Result.FromJson(response.body)
	}

	// Debug log response
	s.log("--------------------------------------------------------------------------------")
	s.log("RESPONSE")
	s.log("--------------------------------------------------------------------------------")
	s.log("Status: ", response.status)
	s.log("Result: ", response.Result)

	return
}
Example #11
0
// Hack based on Napping Send method to allow uploading files
func (s *OSession) Upload(r *napping.Request, file []byte) (response string, err error) {
	r.Method = strings.ToUpper(r.Method)
	//
	// Create a URL object from the raw url string.  This will allow us to compose
	// query parameters programmatically and be guaranteed of a well-formed URL.
	//
	u, err := url.Parse(r.Url)
	if err != nil {
		log.Printf("%v", err)
		return
	}
	//
	// Default query parameters
	//
	p := url.Values{}
	//
	// Encode parameters
	//
	u.RawQuery = p.Encode()
	//
	// Create a Request object; if populated, Data field is JSON encoded as
	// request body
	//
	header := http.Header{}
	if s.Header != nil {
		for k, _ := range *s.Header {
			v := s.Header.Get(k)
			header.Set(k, v)
		}
	}
	var req *http.Request

	buf := new(bytes.Buffer)
	w := multipart.NewWriter(buf)
	part, err := w.CreateFormFile("filename", "dbimport")
	if err != nil {
		log.Printf("FormFile %v", err)
	}
	part.Write(file)

	err = w.Close()

	req, err = http.NewRequest(r.Method, u.String(), buf)

	header.Set("Content-Type", w.FormDataContentType())
	//
	// Merge Session and Request options
	//
	var userinfo *url.Userinfo
	if u.User != nil {
		userinfo = u.User
	}
	if s.Userinfo != nil {
		userinfo = s.Userinfo
	}
	// Prefer Request's user credentials
	if r.Userinfo != nil {
		userinfo = r.Userinfo
	}
	if r.Header != nil {
		for k, v := range *r.Header {
			header.Set(k, v[0]) // Is there always guarnateed to be at least one value for a header?
		}
	}
	if header.Get("Accept") == "" {
		header.Add("Accept", "application/json") // Default, can be overridden with Opts
	}
	req.Header = header
	//
	// Set HTTP Basic authentication if userinfo is supplied
	//
	if userinfo != nil {
		pwd, _ := userinfo.Password()
		req.SetBasicAuth(userinfo.Username(), pwd)
		if u.Scheme != "https" {
			//s.log("WARNING: Using HTTP Basic Auth in cleartext is insecure.")
		}
	}
	//
	// Execute the HTTP request
	//

	var client *http.Client
	if s.Client != nil {
		client = s.Client
	} else {
		client = &http.Client{}
		s.Client = client
	}
	resp, err := client.Do(req)
	if err != nil {
		log.Printf("%v", err)
		return
	}
	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Printf("Body: %v", err)
		return
	}
	response = string(body)

	return
}