Exemple #1
1
func (conn *streamConn) connect() (*http.Response, os.Error) {
	if conn.stale {
		return nil, os.NewError("Stale connection")
	}
	tcpConn, err := net.Dial("tcp", "", conn.url.Host+":80")
	if err != nil {
		return nil, err
	}
	conn.clientConn = http.NewClientConn(tcpConn, nil)

	var req http.Request
	req.URL = conn.url
	req.Method = "GET"
	req.Header = map[string]string{}
	req.Header["Authorization"] = "Basic " + conn.authData

	if conn.postData != "" {
		req.Method = "POST"
		req.Body = nopCloser{bytes.NewBufferString(conn.postData)}
		req.ContentLength = int64(len(conn.postData))
		req.Header["Content-Type"] = "application/x-www-form-urlencoded"
	}

	err = conn.clientConn.Write(&req)
	if err != nil {
		return nil, err
	}

	resp, err := conn.clientConn.Read()
	if err != nil {
		return nil, err
	}

	return resp, nil
}
// This function is launched async as a go routine. It tries to send a message
// to a remote server and sends a bool to nextChannel to indicate whether this
// has succeeded or not. It is not allowed to run this function multiple times in parallel
// for the same FederationGateway.
func (self *FederationGateway) sendFromQueue(req *WaveletUpdateRequest) {
	// No HTTP connection open yet?
	if self.connection == nil {
		con, err := net.Dial("tcp", "", fmt.Sprintf("%v:%v", self.manifest.HostName, self.manifest.Port))
		if err != nil {
			// TODO: Good error handling
			log.Println("Failed connecting to ", self.manifest, err)
			self.nextChannel <- false
			return
		}
		self.connection = http.NewClientConn(con, nil)
	}

	// Build the HTTP request
	var hreq http.Request
	hreq.Host = self.manifest.Domain
	hreq.Header = make(map[string]string)
	hreq.RawURL = fmt.Sprintf("http://%v:%v/fed%v", self.manifest.HostName, self.manifest.Port, req.uri)
	hreq.Method = "PUT"
	hreq.Body = NewRequestBody(req.Data)
	hreq.ContentLength = int64(len(req.Data))
	hreq.Header["Content-Type"] = req.MimeType
	log.Println("Sending WaveletUpdate to remote server ", hreq.RawURL)

	// Send the HTTP request
	self.connection.Write(&hreq)
	// Read the HTTP response
	hres, err := self.connection.Read()
	if err != nil {
		log.Println("Error reading HTTP response from ", self.manifest, err)
		// TODO: Better error handling
		self.connection.Close()
		self.connection = nil
		self.nextChannel <- false
		return
	}

	log.Println("After sending WaveletUpdate, status code is ", hres.StatusCode)
	// Success in sending the wavelet update?
	if hres.StatusCode == 200 {
		self.nextChannel <- true
		return
	}
	// Sending the wavelet update failed
	self.nextChannel <- false
}
Exemple #3
0
func YadisRequest(url_ string, method string) (resp *http.Response, err os.Error) {
	resp = nil

	var request = new(http.Request)
	var client = new(http.Client)
	var Header = make(http.Header)

	request.Method = method
	request.RawURL = url_

	request.URL, err = url.Parse(url_)
	if err != nil {
		return
	}

	// Common parameters
	request.Proto = "HTTP/1.0"
	request.ProtoMajor = 1
	request.ProtoMinor = 0
	request.ContentLength = 0
	request.Close = true

	Header.Add("Accept", "application/xrds+xml")
	request.Header = Header

	// Follow a maximum of 5 redirections
	for i := 0; i < 5; i++ {
		response, err := client.Do(request)

		if err != nil {
			return nil, err
		}
		if response.StatusCode == 301 || response.StatusCode == 302 || response.StatusCode == 303 || response.StatusCode == 307 {
			location := response.Header.Get("Location")
			request.RawURL = location
			request.URL, err = url.Parse(location)
			if err != nil {
				return
			}
		} else {
			return response, nil
		}
	}
	return nil, os.NewError("Too many redirections")
}
Exemple #4
0
func nmcPOST(body *bytes.Buffer) (response *http.Response, err os.Error) {
	client := http.Client{}

	var req http.Request
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	req.Body = ioutil.NopCloser(body)
	req.Header = http.Header{
		"Content-Type":   []string{"text/plain"},
		"Content-Length": []string{strconv.Itoa(body.Len())},
	}
	req.ContentLength = int64(body.Len())
	req.URL = options.nmcURL

	return client.Do(&req)
}
Exemple #5
0
func (conn *streamConn) connect() (*http.Response, os.Error) {
	if conn.stale {
		return nil, os.NewError("Stale connection")
	}
	var tcpConn net.Conn
	var err os.Error
	if proxy := os.Getenv("HTTP_PROXY"); len(proxy) > 0 {
		proxy_url, _ := url.Parse(proxy)
		tcpConn, err = net.Dial("tcp", proxy_url.Host)
	} else {
		tcpConn, err = net.Dial("tcp", conn.url.Host+":443")
	}
	if err != nil {
		return nil, err
	}
	cf := &tls.Config{Rand: rand.Reader, Time: time.Nanoseconds}
	ssl := tls.Client(tcpConn, cf)

	conn.clientConn = http.NewClientConn(ssl, nil)

	var req http.Request
	req.URL = conn.url
	req.Method = "GET"
	req.Header = http.Header{}
	req.Header.Set("Authorization", "Basic "+conn.authData)

	if conn.postData != "" {
		req.Method = "POST"
		req.Body = nopCloser{bytes.NewBufferString(conn.postData)}
		req.ContentLength = int64(len(conn.postData))
		req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
	}

	resp, err := conn.clientConn.Do(&req)
	if err != nil {
		return nil, err
	}

	return resp, nil
}
Exemple #6
0
// PostForm issues a POST to the specified URL,
// with data's keys and values urlencoded as the request body.
//
// Caller should close r.Body when done reading from it.
func Post(t *Test) (r *http.Response, finalUrl string, cookies []*http.Cookie, err os.Error) {
	var req http.Request
	var url = t.Url
	req.Method = "POST"
	req.ProtoMajor = 1
	req.ProtoMinor = 1
	req.Close = true
	var body *bytes.Buffer
	var contentType string
	if hasFile(&t.Param) || t.Method == "POST:mp" {
		var boundary string
		body, boundary = multipartBody(&t.Param)
		contentType = "multipart/form-data; boundary=" + boundary
	} else {
		contentType = "application/x-www-form-urlencoded"
		bodystr := http.EncodeQuery(t.Param)
		body = bytes.NewBuffer([]byte(bodystr))
	}

	req.Body = nopCloser{body}
	req.Header = http.Header{
		"Content-Type":   {contentType},
		"Content-Length": {strconv.Itoa(body.Len())},
	}
	addHeadersAndCookies(&req, t)

	req.ContentLength = int64(body.Len())
	req.URL, err = http.ParseURL(url)
	if err != nil {
		return nil, url, cookies, err
	}
	debug("Will post to %s", req.URL.String())

	r, finalUrl, cookies, err = DoAndFollow(&req, t.Dump)
	return
}
Exemple #7
0
// RequestFromMap creates an http.Request from CGI variables.
// The returned Request's Body field is not populated.
func RequestFromMap(params map[string]string) (*http.Request, os.Error) {
	r := new(http.Request)
	r.Method = params["REQUEST_METHOD"]
	if r.Method == "" {
		return nil, os.NewError("cgi: no REQUEST_METHOD in environment")
	}

	r.Proto = params["SERVER_PROTOCOL"]
	var ok bool
	r.ProtoMajor, r.ProtoMinor, ok = http.ParseHTTPVersion(r.Proto)
	if !ok {
		return nil, os.NewError("cgi: invalid SERVER_PROTOCOL version")
	}

	r.Close = true
	r.Trailer = http.Header{}
	r.Header = http.Header{}

	r.Host = params["HTTP_HOST"]
	r.Referer = params["HTTP_REFERER"]
	r.UserAgent = params["HTTP_USER_AGENT"]

	if lenstr := params["CONTENT_LENGTH"]; lenstr != "" {
		clen, err := strconv.Atoi64(lenstr)
		if err != nil {
			return nil, os.NewError("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
		}
		r.ContentLength = clen
	}

	if ct := params["CONTENT_TYPE"]; ct != "" {
		r.Header.Set("Content-Type", ct)
	}

	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
	for k, v := range params {
		if !strings.HasPrefix(k, "HTTP_") || skipHeader[k] {
			continue
		}
		r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
	}

	// TODO: cookies.  parsing them isn't exported, though.

	if r.Host != "" {
		// Hostname is provided, so we can reasonably construct a URL,
		// even if we have to assume 'http' for the scheme.
		r.RawURL = "http://" + r.Host + params["REQUEST_URI"]
		url, err := http.ParseURL(r.RawURL)
		if err != nil {
			return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL)
		}
		r.URL = url
	}
	// Fallback logic if we don't have a Host header or the URL
	// failed to parse
	if r.URL == nil {
		r.RawURL = params["REQUEST_URI"]
		url, err := http.ParseURL(r.RawURL)
		if err != nil {
			return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL)
		}
		r.URL = url
	}

	// There's apparently a de-facto standard for this.
	// http://docstore.mik.ua/orelly/linux/cgi/ch03_02.htm#ch03-35636
	if s := params["HTTPS"]; s == "on" || s == "ON" || s == "1" {
		r.TLS = &tls.ConnectionState{HandshakeComplete: true}
	}

	// Request.RemoteAddr has its port set by Go's standard http
	// server, so we do here too. We don't have one, though, so we
	// use a dummy one.
	r.RemoteAddr = net.JoinHostPort(params["REMOTE_ADDR"], "0")

	return r, nil
}
Exemple #8
0
func (p *Propolis) SendRequest(method string, reduced bool, src string, target *url.URL, body io.ReadCloser, hash string, info *os.FileInfo) (resp *http.Response, err os.Error) {
	defer func() {
		// if anything goes wrong, close the body reader
		// if it ends normally, this will be closed already and set to nil
		if body != nil {
			body.Close()
		}
	}()

	var req *http.Request
	if req, err = http.NewRequest(method, target.String(), body); err != nil {
		return
	}

	// set upload file info if applicable
	if info != nil && body != nil {
		// TODO: 0-length files fail because the Content-Length field is missing
		// a fix is in the works in the Go library
		req.ContentLength = info.Size
	}

	if info != nil {
		p.SetRequestMetaData(req, info)
	}

	// reduced redundancy?
	if reduced {
		req.Header.Set("X-Amz-Storage-Class", "REDUCED_REDUNDANCY")
	}

	// are we uploading a file with a content hash?
	if hash != "" {
		req.Header.Set("Content-MD5", hash)
	}

	// is this a copy/metadata update?
	if src != "" {
		// note: src should already be a full bucket + path name
		u := new(url.URL)
		u.Path = src
		req.Header.Set("X-Amz-Copy-Source", u.String())
		req.Header.Set("X-Amz-Metadata-Directive", "REPLACE")
	}

	// sign and execute the request
	// note: 2nd argument is temporary hack to set Content-Length: 0 when needed
	if resp, err = p.SignAndExecute(req, method == "PUT" && body == nil || (info != nil && info.Size == 0)); err != nil {
		return
	}

	// body was closed when the request was written out,
	// so nullify the deferred close
	body = nil

	if resp.StatusCode < 200 || resp.StatusCode > 299 {
		err = os.NewError(resp.Status)
		return
	}

	return
}
Exemple #9
0
func (s Session) perform(method, url, data string) {
	var req http.Request
	req.URL, _ = http.ParseURL(url)
	req.Method = method
	req.Header = s.headers
	req.ContentLength = int64(len(data))
	req.Body = myCloser{bytes.NewBufferString(data)}
	if *verbose {
		req.Write(os.Stderr)
	}
	retry := 0
request:
	req.Body = myCloser{bytes.NewBufferString(data)} // recreate anew, in case of retry
	err := s.conn.Write(&req)
	if err != nil {
		if retry < 2 {
			if err == io.ErrUnexpectedEOF {
				// the underlying connection has been closed "gracefully"
				retry++
				s.conn.Close()
				s.conn = dial(s.host)
				goto request
			} else if protoerr, ok := err.(*http.ProtocolError); ok && protoerr == http.ErrPersistEOF {
				// the connection has been closed in an HTTP keepalive sense
				retry++
				s.conn.Close()
				s.conn = dial(s.host)
				goto request
			}
		}
		fmt.Fprintln(os.Stderr, "http-gonsole: could not send request:", err)
		os.Exit(1)
	}
	r, err := s.conn.Read(&req)
	if err != nil {
		if protoerr, ok := err.(*http.ProtocolError); ok && protoerr == http.ErrPersistEOF {
			// the remote requested that this be the last request serviced,
			// we proceed as the response is still valid
			defer s.conn.Close()
			defer func() { s.conn = dial(s.host) }()
			goto output
		}
		fmt.Fprintln(os.Stderr, "http-gonsole: could not read response:", err)
		os.Exit(1)
	}
output:
	if len(data) > 0 {
		fmt.Println()
	}
	if r.StatusCode >= 500 {
		fmt.Printf(colorize(C_5xx, "%s %s\n"), r.Proto, r.Status)
	} else if r.StatusCode >= 400 {
		fmt.Printf(colorize(C_4xx, "%s %s\n"), r.Proto, r.Status)
	} else if r.StatusCode >= 300 {
		fmt.Printf(colorize(C_3xx, "%s %s\n"), r.Proto, r.Status)
	} else if r.StatusCode >= 200 {
		fmt.Printf(colorize(C_2xx, "%s %s\n"), r.Proto, r.Status)
	}
	if len(r.Header) > 0 {
		for key, arr := range r.Header {
			for _, val := range arr {
				fmt.Printf(colorize(C_Header, "%s: "), key)
				fmt.Println(val)
			}
		}
		fmt.Println()
	}
	if *rememberCookies {
		if cookies, found := r.Header["Set-Cookie"]; found {
			for _, h := range cookies {
				cookie := new(Cookie)
				cookie.Items = map[string]string{}
				re, _ := regexp.Compile("^[^=]+=[^;]+(; *(expires=[^;]+|path=[^;,]+|domain=[^;,]+|secure))*,?")
				rs := re.FindAllString(h, -1)
				for _, ss := range rs {
					m := strings.Split(ss, ";", -1)
					for _, n := range m {
						t := strings.Split(n, "=", 2)
						if len(t) == 2 {
							t[0] = strings.Trim(t[0], " ")
							t[1] = strings.Trim(t[1], " ")
							switch t[0] {
							case "domain":
								cookie.domain = t[1]
							case "path":
								cookie.path = t[1]
							case "expires":
								tm, err := time.Parse("Fri, 02-Jan-2006 15:04:05 MST", t[1])
								if err != nil {
									tm, err = time.Parse("Fri, 02-Jan-2006 15:04:05 -0700", t[1])
								}
								cookie.expires = tm
							case "secure":
								cookie.secure = true
							case "HttpOnly":
								cookie.httpOnly = true
							default:
								cookie.Items[t[0]] = t[1]
							}
						}
					}
				}
				*s.cookies = append(*s.cookies, cookie)
			}
		}
	}
	h := r.Header.Get("Content-Length")
	if len(h) > 0 {
		n, _ := strconv.Atoi64(h)
		b := make([]byte, n)
		io.ReadFull(r.Body, b)
		fmt.Println(string(b))
	} else if method != "HEAD" {
		b, _ := ioutil.ReadAll(r.Body)
		fmt.Println(string(b))
	} else {
		// TODO: streaming?
	}
}
Exemple #10
0
func requestFromEnvironment(env map[string]string) (*http.Request, os.Error) {
	r := new(http.Request)
	r.Method = env["REQUEST_METHOD"]
	if r.Method == "" {
		return nil, os.NewError("cgi: no REQUEST_METHOD in environment")
	}
	r.Close = true
	r.Trailer = http.Header{}
	r.Header = http.Header{}

	r.Host = env["HTTP_HOST"]
	r.Referer = env["HTTP_REFERER"]
	r.UserAgent = env["HTTP_USER_AGENT"]

	// CGI doesn't allow chunked requests, so these should all be accurate:
	r.Proto = "HTTP/1.0"
	r.ProtoMajor = 1
	r.ProtoMinor = 0
	r.TransferEncoding = nil

	if lenstr := env["CONTENT_LENGTH"]; lenstr != "" {
		clen, err := strconv.Atoi64(lenstr)
		if err != nil {
			return nil, os.NewError("cgi: bad CONTENT_LENGTH in environment: " + lenstr)
		}
		r.ContentLength = clen
		r.Body = ioutil.NopCloser(io.LimitReader(os.Stdin, clen))
	}

	// Copy "HTTP_FOO_BAR" variables to "Foo-Bar" Headers
	for k, v := range env {
		if !strings.HasPrefix(k, "HTTP_") || skipHeader[k] {
			continue
		}
		r.Header.Add(strings.Replace(k[5:], "_", "-", -1), v)
	}

	// TODO: cookies.  parsing them isn't exported, though.

	if r.Host != "" {
		// Hostname is provided, so we can reasonably construct a URL,
		// even if we have to assume 'http' for the scheme.
		r.RawURL = "http://" + r.Host + env["REQUEST_URI"]
		url, err := http.ParseURL(r.RawURL)
		if err != nil {
			return nil, os.NewError("cgi: failed to parse host and REQUEST_URI into a URL: " + r.RawURL)
		}
		r.URL = url
	}
	// Fallback logic if we don't have a Host header or the URL
	// failed to parse
	if r.URL == nil {
		r.RawURL = env["REQUEST_URI"]
		url, err := http.ParseURL(r.RawURL)
		if err != nil {
			return nil, os.NewError("cgi: failed to parse REQUEST_URI into a URL: " + r.RawURL)
		}
		r.URL = url
	}
	return r, nil
}
Exemple #11
0
func (self *FederationProxy) sendFromQueue() {
	if len(self.queue) == 0 {
		return
	}

	log.Println("Sending message from queue")

	// No HTTP connection open yet?
	if self.connection == nil {
		con, err := net.Dial("tcp", "", fmt.Sprintf("%v:%v", self.manifest.HostName, self.manifest.Port))
		if err != nil {
			// TODO: Good error handling
			log.Println("Failed connecting to ", self.manifest, err)
			return
		}
		self.connection = http.NewClientConn(con, nil)
	}

	// Dequeue a message
	req := self.queue.At(0).(FederationRequest)
	// Build the HTTP request
	var hreq http.Request
	hreq.Host = self.manifest.Domain
	hreq.Header = make(map[string]string)
	switch req.(type) {
	case *PostRequest:
		preq := req.(*PostRequest)
		hreq.RawURL = fmt.Sprintf("http://%v:%v/fed/%v", self.manifest.HostName, self.manifest.Port, preq.URI.String())
		hreq.Method = "POST"
		hreq.Body = NewRequestBody(preq.Data)
		hreq.ContentLength = int64(len(preq.Data))
		hreq.Header["Content-Type"] = preq.MimeType
	case *GetRequest:
		greq := req.(*GetRequest)
		hreq.Method = "GET"
		hreq.RawURL = fmt.Sprintf("http://%v:%v/fed/%v", self.manifest.HostName, self.manifest.Port, greq.URI.String())
	default:
		log.Println(req)
		panic("Unsupported kind of message forwarded internally to the federation proxy")
	}
	log.Println("Sending request to ", hreq.RawURL)

	// Send the HTTP request
	self.connection.Write(&hreq)
	// Read the HTTP response
	hres, err := self.connection.Read()
	if err != nil {
		log.Println("Error reading HTTP response from ", self.manifest, err)
		// TODO: Better error handling
		self.connection.Close()
		self.connection = nil
		return
	}

	// Success. Remove the request from the queue
	self.queue.Delete(0)

	// Send the result back to the client
	_, err = io.Copy(req.GetResponseWriter(), hres.Body)
	hres.Body.Close()
	if err != nil {
		log.Println("Error sending result of federated message back to the client")
		req.SendFinishSignal(false)
	}
	req.SendFinishSignal(true)
}