Пример #1
2
func send(req *http.Request) (resp *http.Response, err os.Error) {
	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":http"
	}
	conn, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

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

	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	r := io.Reader(reader)
	if n := resp.ContentLength; n != -1 {
		r = io.LimitReader(r, n)
	}
	resp.Body = readClose{r, conn}

	return
}
Пример #2
1
func ReadFrom(conn net.Conn, method string) (resp *http.Response, e os.Error) {
	// Read from and proccess the connection
	req := new(http.Request)
	req.Method = method

	reader := bufio.NewReader(conn)
	resp, e = http.ReadResponse(reader, req)
	if e != nil {
		fmt.Println("Error reading response:", e)
	}
	return
}
Пример #3
0
// execute a request; date it, sign it, send it
func (bucket *Bucket) Execute(req *http.Request) (resp *http.Response, err os.Error) {
	// time stamp it
	date := time.LocalTime().Format(time.RFC1123)
	req.Header["Date"] = date

	// sign the request
	bucket.Sign(req)

	// open a connection
	conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme)
	if err != nil {
		return nil, err
	}

	// send the request
	req.Write(conn)

	// now read the response
	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req.Method)
	if err != nil {
		return nil, err
	}

	return
}
Пример #4
0
func send(req *http.Request) (resp *http.Response, err os.Error) {
	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":http"
	}
	conn, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}

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

	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, "GET")
	if err != nil {
		conn.Close()
		return nil, err
	}

	r := io.Reader(reader)
	if v := resp.GetHeader("Content-Length"); v != "" {
		n, err := strconv.Atoi64(v)
		if err != nil {
			//			return nil, &badStringError{"invalid Content-Length", v}
		}
		r = io.LimitReader(r, n)
	}
	resp.Body = readClose{r, conn}

	return
}
Пример #5
0
/*
Handhake described in (soon obsolete)
draft-hixie-thewebsocket-protocol-75.
*/
func draft75handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")
	bw.WriteString("Upgrade: WebSocket\r\n")
	bw.WriteString("Connection: Upgrade\r\n")
	bw.WriteString("Host: " + host + "\r\n")
	bw.WriteString("Origin: " + origin + "\r\n")
	if protocol != "" {
		bw.WriteString("WebSocket-Protocol: " + protocol + "\r\n")
	}
	bw.WriteString("\r\n")
	bw.Flush()
	resp, err := http.ReadResponse(br, "GET")
	if err != nil {
		return
	}
	if resp.Status != "101 Web Socket Protocol Handshake" {
		return ErrBadStatus
	}
	if resp.Header["Upgrade"] != "WebSocket" ||
		resp.Header["Connection"] != "Upgrade" {
		return ErrBadUpgrade
	}
	if resp.Header["Websocket-Origin"] != origin {
		return ErrBadWebSocketOrigin
	}
	if resp.Header["Websocket-Location"] != location {
		return ErrBadWebSocketLocation
	}
	if protocol != "" && resp.Header["Websocket-Protocol"] != protocol {
		return ErrBadWebSocketProtocol
	}
	return
}
Пример #6
0
Файл: main.go Проект: tobi/tinny
func pipeRequestResponse(server, client net.Conn) os.Error {

	// Read request from wire
	req, err := http.ReadRequest(bufio.NewReader(client))
	if err != nil {
		return err
	}

	rawReq, err := http.DumpRequest(req, true)
	if err != nil {
		return err
	}

	// forward it on
	server.Write(rawReq)

	// Read response from wire
	resp, err := http.ReadResponse(bufio.NewReader(server), req)
	if err != nil {
		return err
	}

	rawResp, err := http.DumpResponse(resp, true)
	if err != nil {
		return err
	}

	log.Printf("%s %s [%s]", req.Method, req.RawURL, resp.Status)

	// forward it on
	client.Write(rawResp)

	return nil
}
Пример #7
0
func (bucket *Bucket) GetFile(file *os.FileInfo) (err os.Error) {
	url, e := http.ParseURL(bucket.Url + "/" + file.Name)
	if e != nil {
		return err
	}
	req := &http.Request{Method: "GET", RawURL: bucket.Url + "/" + file.Name, URL: url, Header: make(map[string]string)}
	date := time.LocalTime().Format(time.RFC1123)
	req.Header["Date"] = date
	bucket.sign(req)
	//req.Write(os.Stdout)

	conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme)
	if err != nil {
		return err
	}
	req.Write(conn)
	reader := bufio.NewReader(conn)
	resp, _ := http.ReadResponse(reader, req.Method)
	//resp.Write(os.Stdout)
	filename := strings.TrimLeft(url.Path, "/")
	path := strings.SplitAfter(filename, "/", -1)
	//pid := os.GetPid()

	var b []byte
	b, err = ioutil.ReadAll(resp.Body)
	if err != nil {
		return err
	}
	mode := (file.Mode & 0777)
	fmt.Printf("0%o\n", mode)
	//var dirmode uint32
	//dirmode = (syscall.S_IFDIR^0666)&0777
	resp.Body.Close()

	//create file or dir
	for i := 0; i < len(path); i++ {
		f := i + 1
		if f == len(path) {
			openfile, err := os.Open(filename, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL, mode)
			if err != nil {
				return err
			} else {
				openfile.Chown(file.Uid, file.Gid)
				openfile.Write(b)
				openfile.Close()
				os.Chtimes(filename, file.Mtime_ns, file.Mtime_ns)
			}
		} else {
			err := os.Mkdir(path[i], 0755)
			if err != nil {
				return err
			}
		}
	}

	return nil
}
Пример #8
0
func (proxy *Proxy) ServeHTTP(conn *http.Conn, req *http.Request) {

	// Open a connection to the Hub.
	hubconn, err := net.Dial("tcp", "", remoteAddr)
	if err != nil {
		if debugMode {
			fmt.Printf("Couldn't connect to remote %s: %v\n", remoteHost, err)
		}
		return
	}

	hub := tls.Client(hubconn, tlsconf.Config)
	defer hub.Close()

	// Modify the request Host: header.
	req.Host = remoteHost

	// Send the request to the Hub.
	err = req.Write(hub)
	if err != nil {
		if debugMode {
			fmt.Printf("Error writing to the hub: %v\n", err)
		}
		return
	}

	// Parse the response from the Hub.
	resp, err := http.ReadResponse(bufio.NewReader(hub), req.Method)
	if err != nil {
		if debugMode {
			fmt.Printf("Error parsing response from the hub: %v\n", err)
		}
		return
	}

	// Set the received headers back to the initial connection.
	for k, v := range resp.Header {
		conn.SetHeader(k, v)
	}

	// Read the full response body.
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if debugMode {
			fmt.Printf("Error reading response from the hub: %v\n", err)
		}
		resp.Body.Close()
		return
	}

	// Write the response body back to the initial connection.
	resp.Body.Close()
	conn.WriteHeader(resp.StatusCode)
	conn.Write(body)

}
Пример #9
0
func get(p string, accept string) (r *http.Response, err os.Error) {
	var conn net.Conn
	if conn, err = net.Dial("tcp", fmt.Sprintf("localhost:%v", port())); err == nil {
		req, _ := http.NewRequest("GET", fmt.Sprintf("http://%v", path.Join(fmt.Sprintf("localhost:%v/", port()), p)), nil)
		req.Header.Set("Accept-Encoding", accept)
		req.Write(conn)
		buf := bufio.NewReader(conn)
		r, err = http.ReadResponse(buf, req)
	}
	return
}
Пример #10
0
func send(req *http.Request) (resp *http.Response, err os.Error) {
	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
		return nil, nil
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":" + req.URL.Scheme
	}
	/*info := req.URL.Userinfo
	  if len(info) > 0 {
	      enc := base64.URLEncoding
	      encoded := make([]byte, enc.EncodedLen(len(info)))
	      enc.Encode(encoded, []byte(info))
	      if req.Header == nil {
	          req.Header = make(map[string]string)
	      }
	      req.Header["Authorization"] = "Basic " + string(encoded)
	  }
	*/
	var conn io.ReadWriteCloser
	if req.URL.Scheme == "http" {
		conn, err = net.Dial("tcp", addr)
	} else { // https
		conn, err = tls.Dial("tcp", addr, nil)
	}
	if err != nil {
		return nil, err
	}

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

	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}
Пример #11
0
// ReadResponse waits for a signal that the reqid request is complete.
// It uses http.ReadResponse to read and return an http.Response object from reqid's
// response buffer.
// After the response is read, the reqid is freed, and might immediately be used
// again for a new request.
func (ws *wsConn) ReadResponse(reqid uint16, method string) (ret *http.Response, err os.Error) {
	<-ws.signals[reqid] // wait for this reqid to be finished
	defer ws.freeReqId(reqid)
	buf := ws.buffers[reqid]
	content := buf.Bytes()
	findBytes := []byte("\r\n\r\n")
	i := bytes.Index(content, findBytes)
	if i >= 0 {
		length := "\r\nContent-Length: " + strconv.Itoa(len(content[i+4:]))
		newContent := make([]byte, 0, len(content)+len(length))
		buf = bytes.NewBuffer(newContent)
		buf.Write(content[:i])
		buf.Write([]byte(length))
		buf.Write(content[i:])
	}
	return http.ReadResponse(bufio.NewReader(buf), method)
}
Пример #12
0
func send(req *http.Request) (resp *http.Response, err os.Error) {
	//dump, _ := http.DumpRequest(req, true)
	//fmt.Fprintf(os.Stderr, "%s", dump)
	//fmt.Fprintf(os.Stderr, "\n--- body:\n%s\n---", bodyString(req.Body))
	if req.URL.Scheme != "http" && req.URL.Scheme != "https" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	var conn net.Conn
	switch req.URL.Scheme {
	case "http":
		if !hasPort(addr) {
			addr += ":http"
		}

		conn, err = net.Dial("tcp", addr)
	case "https":
		if !hasPort(addr) {
			addr += ":https"
		}

		conn, err = tls.Dial("tcp", addr, nil)
	}
	if err != nil {
		return nil, err
	}

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

	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}
Пример #13
0
// DialHTTP connects to an HTTP RPC server at the specified network address.
func DialHTTP(network, address string) (*Client, os.Error) {
	conn, err := net.Dial(network, "", address);
	if err != nil {
		return nil, err;
	}
	io.WriteString(conn, "CONNECT " + rpcPath + " HTTP/1.0\n\n");

	// Require successful HTTP response
	// before switching to RPC protocol.
	resp, err := http.ReadResponse(bufio.NewReader(conn));
	if err == nil && resp.Status == connected {
		return NewClient(conn), nil;
	}
	if err == nil {
		err = os.ErrorString("unexpected HTTP response: " + resp.Status);
	}
	conn.Close();
	return nil, &net.OpError{"dial-http", network+" "+address, nil, err};
}
Пример #14
0
func sendPost(postRequest *http.Request) (body string, err os.Error) {
	// Create and use TCP connection (lifted mostly wholesale from http.send)
	conn, err := net.Dial("tcp", "api.flickr.com:80")
	defer conn.Close()

	if err != nil {
		return "", err
	}
	postRequest.Write(conn)

	reader := bufio.NewReader(conn)
	resp, err := http.ReadResponse(reader, postRequest.Method)
	if err != nil {
		return "", err
	}
	rawBody, _ := ioutil.ReadAll(resp.Body)

	return string(rawBody), nil
}
Пример #15
0
func main() {
	url := "http://twitter.com/statuses/public_timeline.json"
	var req http.Request
	req.URL, _ = http.ParseURL(url)
	addr := req.URL.Host
	addr += ":http"
	conn, _ := net.Dial("tcp", "", addr)
	_ = req.Write(conn)
	reader := bufio.NewReader(conn)
	resp, _ := http.ReadResponse(reader)
	r := io.Reader(reader)
	if v := resp.GetHeader("Content-Length"); v != "" {
		n, _ := strconv.Atoi64(v)
		r = io.LimitReader(r, n)
	}
	resp.Body = readClose{r, conn}
	b, _ := io.ReadAll(resp.Body)
	resp.Body.Close()
	fmt.Println(string(b))
}
Пример #16
0
// DialHTTPPath connects to an HTTP RPC server
// at the specified network address and path.
func DialHTTPPath(network, address, path string) (*Client, os.Error) {
	var err os.Error
	conn, err := net.Dial(network, address)
	if err != nil {
		return nil, err
	}
	io.WriteString(conn, "CONNECT "+path+" HTTP/1.0\n\n")

	// Require successful HTTP response
	// before switching to RPC protocol.
	resp, err := http.ReadResponse(bufio.NewReader(conn), &http.Request{Method: "CONNECT"})
	if err == nil && resp.Status == connected {
		return NewClient(conn), nil
	}
	if err == nil {
		err = os.NewError("unexpected HTTP response: " + resp.Status)
	}
	conn.Close()
	return nil, &net.OpError{"dial-http", network + " " + address, nil, err}
}
Пример #17
0
func send(req *http.Request) (resp *http.Response, err os.Error) {
	if req.URL.Scheme != "http" {
		return nil, &badStringError{"unsupported protocol scheme", req.URL.Scheme}
	}

	addr := req.URL.Host
	if !hasPort(addr) {
		addr += ":http"
	}
	info := req.URL.Userinfo
	if len(info) > 0 {
		enc := base64.URLEncoding
		encoded := make([]byte, enc.EncodedLen(len(info)))
		enc.Encode(encoded, strings.Bytes(info))
		if req.Header == nil {
			req.Header = make(map[string]string)
		}
		req.Header["Authorization"] = "Basic " + string(encoded)
	}
	conn, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}

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

	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req.Method)
	if err != nil {
		conn.Close()
		return nil, err
	}

	resp.Body = readClose{resp.Body, conn}

	return
}
Пример #18
0
// Client Handshake described in (soon obsolete)
// draft-hixie-thewebsocket-protocol-75.
func hixie75ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	if config.Version != ProtocolVersionHixie75 {
		panic("wrong protocol version.")
	}
	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")
	bw.WriteString("Upgrade: WebSocket\r\n")
	bw.WriteString("Connection: Upgrade\r\n")
	bw.WriteString("Host: " + config.Location.Host + "\r\n")
	bw.WriteString("Origin: " + config.Origin.String() + "\r\n")
	if len(config.Protocol) > 0 {
		if len(config.Protocol) != 1 {
			return ErrBadWebSocketProtocol
		}
		bw.WriteString("WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
	}
	bw.WriteString("\r\n")
	bw.Flush()
	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
	if err != nil {
		return
	}
	if resp.Status != "101 Web Socket Protocol Handshake" {
		return ErrBadStatus
	}
	if resp.Header.Get("Upgrade") != "WebSocket" ||
		resp.Header.Get("Connection") != "Upgrade" {
		return ErrBadUpgrade
	}
	if resp.Header.Get("Websocket-Origin") != config.Origin.String() {
		return ErrBadWebSocketOrigin
	}
	if resp.Header.Get("Websocket-Location") != config.Location.String() {
		return ErrBadWebSocketLocation
	}
	if len(config.Protocol) > 0 && resp.Header.Get("Websocket-Protocol") != config.Protocol[0] {
		return ErrBadWebSocketProtocol
	}
	return
}
Пример #19
0
// execute a request; date it, sign it, send it
// note: specialcase is temporary hack to set Content-Length: 0 when needed
func (p *Propolis) SignAndExecute(req *http.Request, specialcase bool) (resp *http.Response, err os.Error) {
	// time stamp it
	date := time.LocalTime().Format(time.RFC1123)
	req.Header.Set("Date", date)

	// sign the request
	p.SignRequest(req)

	// open a connection
	conn, err := net.Dial("tcp", req.URL.Host+":"+req.URL.Scheme)
	if err != nil {
		return nil, err
	}

	// send the request
	if specialcase {
		var buf bytes.Buffer
		req.Write(&buf)
		fixed := bytes.Replace(buf.Bytes(),
			[]byte("User-Agent: Go http package\r\n"),
			[]byte("User-Agent: Go http package\r\nContent-Length: 0\r\n"), 1)
		_, err = conn.Write(fixed)
	} else {
		err = req.Write(conn)
	}
	if err != nil {
		return
	}

	// now read the response
	reader := bufio.NewReader(conn)
	resp, err = http.ReadResponse(reader, req)
	if err != nil {
		return nil, err
	}

	return
}
Пример #20
0
func (frontend *Frontend) ServeHTTP(conn http.ResponseWriter, req *http.Request) {

	originalHost := req.Host

	// Redirect all requests to the "official" public host if the Host header
	// doesn't match.
	if !frontend.isValidHost(originalHost) {
		conn.Header().Set("Location", frontend.RedirectURL)
		conn.WriteHeader(http.StatusMovedPermanently)
		conn.Write(frontend.RedirectHTML)
		frontend.Log(HTTPS_REDIRECT, http.StatusMovedPermanently, originalHost, req)
		return
	}

	// Return the HTTP 503 error page if we're in maintenance mode.
	if frontend.MaintenanceMode {
		headers := conn.Header()
		headers.Set("Content-Type", "text/html; charset=utf-8")
		headers.Set("Content-Length", frontend.Error503Length)
		conn.WriteHeader(http.StatusServiceUnavailable)
		conn.Write(frontend.Error503)
		frontend.Log(HTTPS_MAINTENANCE, http.StatusServiceUnavailable, originalHost, req)
		return
	}

	reqPath := req.URL.Path

	// Handle requests for any files exposed within the static directory.
	if staticFile, ok := frontend.StaticFiles[reqPath]; ok {
		expires := time.SecondsToUTC(time.Seconds() + frontend.StaticMaxAge)
		headers := conn.Header()
		headers.Set("Expires", expires.Format(http.TimeFormat))
		headers.Set("Cache-Control", frontend.StaticCache)
		headers.Set("Etag", staticFile.ETag)
		if req.Header.Get("If-None-Match") == staticFile.ETag {
			conn.WriteHeader(http.StatusNotModified)
			frontend.Log(HTTPS_STATIC, http.StatusNotModified, originalHost, req)
			return
		}
		// Special case /.well-known/oauth.json?callback= requests.
		if reqPath == "/.well-known/oauth.json" && req.URL.RawQuery != "" {
			query, err := http.ParseQuery(req.URL.RawQuery)
			if err != nil {
				logging.Error("Error parsing oauth.json query string %q: %s",
					req.URL.RawQuery, err)
				frontend.ServeError400(conn, originalHost, req)
				return
			}
			if callbackList, found := query["callback"]; found {
				callback := callbackList[0]
				if callback != "" {
					respLen := len(callback) + len(staticFile.Content) + 2
					headers.Set("Content-Type", "text/javascript")
					headers.Set("Content-Length", fmt.Sprintf("%d", respLen))
					conn.WriteHeader(http.StatusOK)
					conn.Write([]byte(callback))
					conn.Write([]byte{'('})
					conn.Write(staticFile.Content)
					conn.Write([]byte{')'})
					frontend.Log(HTTPS_STATIC, http.StatusOK, originalHost, req)
					return
				}
			}
		}
		headers.Set("Content-Type", staticFile.Mimetype)
		headers.Set("Content-Length", staticFile.Size)
		conn.WriteHeader(http.StatusOK)
		conn.Write(staticFile.Content)
		frontend.Log(HTTPS_STATIC, http.StatusOK, originalHost, req)
		return
	}

	if frontend.LiveMode {

		// Handle WebSocket requests.
		if strings.HasPrefix(reqPath, frontend.WebsocketPrefix) {
			websocket.Handler(frontend.getWebSocketHandler()).ServeHTTP(conn, req)
			return
		}

		// Handle long-polling Comet requests.
		if strings.HasPrefix(reqPath, frontend.CometPrefix) {
			query, err := http.ParseQuery(req.URL.RawQuery)
			if err != nil {
				logging.Error("Error parsing Comet query string %q: %s",
					req.URL.RawQuery, err)
				frontend.ServeError400(conn, originalHost, req)
				return
			}
			queryReq, found := query["q"]
			if !found {
				frontend.ServeError400(conn, originalHost, req)
				return
			}
			response, status := getLiveItems(queryReq[0])
			headers := conn.Header()
			headers.Set("Content-Type", "application/json")
			headers.Set("Content-Length", fmt.Sprintf("%d", len(response)))
			conn.WriteHeader(status)
			conn.Write(response)
			frontend.Log(HTTPS_COMET, status, originalHost, req)
			return
		}

	}

	// Open a connection to the upstream server.
	upstreamConn, err := net.Dial("tcp", frontend.upstreamAddr)
	if err != nil {
		logging.Error("Couldn't connect to upstream: %s", err)
		frontend.ServeError502(conn, originalHost, req)
		return
	}

	var clientIP string
	var upstream net.Conn

	splitPoint := strings.LastIndex(req.RemoteAddr, ":")
	if splitPoint == -1 {
		clientIP = req.RemoteAddr
	} else {
		clientIP = req.RemoteAddr[0:splitPoint]
	}

	if frontend.upstreamTLS {
		upstream = tls.Client(upstreamConn, tlsconf.Config)
		defer upstream.Close()
	} else {
		upstream = upstreamConn
	}

	// Modify the request Host: and User-Agent: headers.
	req.Host = frontend.upstreamHost
	req.Header.Set(
		"User-Agent",
		fmt.Sprintf("%s, %s, %s", req.UserAgent(), clientIP, originalHost))

	// Send the request to the upstream server.
	err = req.Write(upstream)
	if err != nil {
		logging.Error("Error writing to the upstream server: %s", err)
		frontend.ServeError502(conn, originalHost, req)
		return
	}

	// Parse the response from upstream.
	resp, err := http.ReadResponse(bufio.NewReader(upstream), req)
	if err != nil {
		logging.Error("Error parsing response from upstream: %s", err)
		frontend.ServeError502(conn, originalHost, req)
		return
	}

	defer resp.Body.Close()

	// Get the original request header.
	headers := conn.Header()

	// Set a variable to hold the X-Live header value if present.
	var liveLength int

	if frontend.LiveMode {
		xLive := resp.Header.Get("X-Live")
		if xLive != "" {
			// If the X-Live header was set, parse it into an int.
			liveLength, err = strconv.Atoi(xLive)
			if err != nil {
				logging.Error("Error converting X-Live header value %q: %s", xLive, err)
				frontend.ServeError500(conn, originalHost, req)
				return
			}
			resp.Header.Del("X-Live")
		}
	}

	var body []byte

	if liveLength > 0 {

		var gzipSet bool
		var respBody io.ReadCloser

		// Check Content-Encoding to see if upstream sent gzipped content.
		if resp.Header.Get("Content-Encoding") == "gzip" {
			gzipSet = true
			respBody, err = gzip.NewReader(resp.Body)
			if err != nil {
				logging.Error("Error reading gzipped response from upstream: %s", err)
				frontend.ServeError500(conn, originalHost, req)
				return
			}
			defer respBody.Close()
		} else {
			respBody = resp.Body
		}

		// Read the X-Live content from the response body.
		liveMessage := make([]byte, liveLength)
		n, err := respBody.Read(liveMessage)
		if n != liveLength || err != nil {
			logging.Error("Error reading X-Live response from upstream: %s", err)
			frontend.ServeError500(conn, originalHost, req)
			return
		}

		// Read the response to send back to the original request.
		body, err = ioutil.ReadAll(respBody)
		if err != nil {
			logging.Error("Error reading non X-Live response from upstream: %s", err)
			frontend.ServeError500(conn, originalHost, req)
			return
		}

		// Re-encode the response if it had been gzipped by upstream.
		if gzipSet {
			buffer := &bytes.Buffer{}
			encoder, err := gzip.NewWriter(buffer)
			if err != nil {
				logging.Error("Error creating a new gzip Writer: %s", err)
				frontend.ServeError500(conn, originalHost, req)
				return
			}
			n, err = encoder.Write(body)
			if n != len(body) || err != nil {
				logging.Error("Error writing to the gzip Writer: %s", err)
				frontend.ServeError500(conn, originalHost, req)
				return
			}
			err = encoder.Close()
			if err != nil {
				logging.Error("Error finalising the write to the gzip Writer: %s", err)
				frontend.ServeError500(conn, originalHost, req)
				return
			}
			body = buffer.Bytes()
		}

		resp.Header.Set("Content-Length", fmt.Sprintf("%d", len(body)))
		liveChannel <- liveMessage

	} else {
		// Read the full response body.
		body, err = ioutil.ReadAll(resp.Body)
		if err != nil {
			logging.Error("Error reading response from upstream: %s", err)
			frontend.ServeError502(conn, originalHost, req)
			return
		}
	}

	// Set the received headers back to the initial connection.
	for k, values := range resp.Header {
		for _, v := range values {
			headers.Add(k, v)
		}
	}

	// Write the response body back to the initial connection.
	conn.WriteHeader(resp.StatusCode)
	conn.Write(body)
	frontend.Log(HTTPS_UPSTREAM, resp.StatusCode, originalHost, req)

}
Пример #21
0
/*
Web Socket protocol handshake based on
http://www.whatwg.org/specs/web-socket-protocol/
(draft of http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol)
*/
func handshake(resourceName, host, origin, location, protocol string, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	// 4.1. Opening handshake.
	// Step 5.  send a request line.
	bw.WriteString("GET " + resourceName + " HTTP/1.1\r\n")

	// Step 6-14. push request headers in fields.
	var fields vector.StringVector
	fields.Push("Upgrade: WebSocket\r\n")
	fields.Push("Connection: Upgrade\r\n")
	fields.Push("Host: " + host + "\r\n")
	fields.Push("Origin: " + origin + "\r\n")
	if protocol != "" {
		fields.Push("Sec-WebSocket-Protocol: " + protocol + "\r\n")
	}
	// TODO(ukai): Step 15. send cookie if any.

	// Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
	key1, number1 := generateKeyNumber()
	key2, number2 := generateKeyNumber()
	fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n")
	fields.Push("Sec-WebSocket-Key2: " + key2 + "\r\n")

	// Step 24. shuffle fields and send them out.
	for i := 1; i < len(fields); i++ {
		j := rand.Intn(i)
		fields[i], fields[j] = fields[j], fields[i]
	}
	for i := 0; i < len(fields); i++ {
		bw.WriteString(fields[i])
	}
	// Step 25. send CRLF.
	bw.WriteString("\r\n")

	// Step 26. genearte 8 bytes random key.
	key3 := generateKey3()
	// Step 27. send it out.
	bw.Write(key3)
	if err = bw.Flush(); err != nil {
		return
	}

	// Step 28-29, 32-40. read response from server.
	resp, err := http.ReadResponse(br, "GET")
	if err != nil {
		return err
	}
	// Step 30. check response code is 101.
	if resp.StatusCode != 101 {
		return ErrBadStatus
	}

	// Step 41. check websocket headers.
	if resp.Header["Upgrade"] != "WebSocket" ||
		strings.ToLower(resp.Header["Connection"]) != "upgrade" {
		return ErrBadUpgrade
	}

	if resp.Header["Sec-Websocket-Origin"] != origin {
		return ErrBadWebSocketOrigin
	}

	if resp.Header["Sec-Websocket-Location"] != location {
		return ErrBadWebSocketLocation
	}

	if protocol != "" && resp.Header["Sec-Websocket-Protocol"] != protocol {
		return ErrBadWebSocketProtocol
	}

	// Step 42-43. get expected data from challange data.
	expected, err := getChallengeResponse(number1, number2, key3)
	if err != nil {
		return err
	}

	// Step 44. read 16 bytes from server.
	reply := make([]byte, 16)
	if _, err = io.ReadFull(br, reply); err != nil {
		return err
	}

	// Step 45. check the reply equals to expected data.
	if !bytes.Equal(expected, reply) {
		return ErrChallengeResponse
	}
	// WebSocket connection is established.
	return
}
Пример #22
0
// TestCopyError tests that we kill the process if there's an error copying
// its output. (for example, from the client having gone away)
func TestCopyError(t *testing.T) {
	if skipTest(t) || runtime.GOOS == "windows" {
		return
	}
	h := &Handler{
		Path: "testdata/test.cgi",
		Root: "/test.cgi",
	}
	ts := httptest.NewServer(h)
	defer ts.Close()

	conn, err := net.Dial("tcp", ts.Listener.Addr().String())
	if err != nil {
		t.Fatal(err)
	}
	req, _ := http.NewRequest("GET", "http://example.com/test.cgi?bigresponse=1", nil)
	err = req.Write(conn)
	if err != nil {
		t.Fatalf("Write: %v", err)
	}

	res, err := http.ReadResponse(bufio.NewReader(conn), req)
	if err != nil {
		t.Fatalf("ReadResponse: %v", err)
	}

	pidstr := res.Header.Get("X-CGI-Pid")
	if pidstr == "" {
		t.Fatalf("expected an X-CGI-Pid header in response")
	}
	pid, err := strconv.Atoi(pidstr)
	if err != nil {
		t.Fatalf("invalid X-CGI-Pid value")
	}

	var buf [5000]byte
	n, err := io.ReadFull(res.Body, buf[:])
	if err != nil {
		t.Fatalf("ReadFull: %d bytes, %v", n, err)
	}

	childRunning := func() bool {
		p, err := os.FindProcess(pid)
		if err != nil {
			return false
		}
		return p.Signal(os.UnixSignal(0)) == nil
	}

	if !childRunning() {
		t.Fatalf("pre-conn.Close, expected child to be running")
	}
	conn.Close()

	if tries := 0; childRunning() {
		for tries < 15 && childRunning() {
			time.Sleep(50e6 * int64(tries))
			tries++
		}
		if childRunning() {
			t.Fatalf("post-conn.Close, expected child to be gone")
		}
	}
}
Пример #23
0
func (frontend *Frontend) ServeHTTP(conn *http.Conn, req *http.Request) {

	if frontend.enforceHost && req.Host != frontend.officialHost {
		conn.SetHeader("Location", frontend.officialRedirectURL)
		conn.WriteHeader(http.StatusMovedPermanently)
		conn.Write(frontend.officialRedirectHTML)
		logRequest(http.StatusMovedPermanently, req.Host, conn)
		return
	}

	originalHost := req.Host

	// Open a connection to the App Engine server.
	gaeConn, err := net.Dial("tcp", "", frontend.gaeAddr)
	if err != nil {
		if debugMode {
			fmt.Printf("Couldn't connect to remote %s: %v\n", frontend.gaeHost, err)
		}
		serveError502(conn, originalHost)
		return
	}

	var gae net.Conn

	if frontend.gaeTLS {
		gae = tls.Client(gaeConn, tlsconf.Config)
		defer gae.Close()
	} else {
		gae = gaeConn
	}

	// Modify the request Host: header.
	req.Host = frontend.gaeHost

	// Send the request to the App Engine server.
	err = req.Write(gae)
	if err != nil {
		if debugMode {
			fmt.Printf("Error writing to App Engine: %v\n", err)
		}
		serveError502(conn, originalHost)
		return
	}

	// Parse the response from App Engine.
	resp, err := http.ReadResponse(bufio.NewReader(gae), req.Method)
	if err != nil {
		if debugMode {
			fmt.Printf("Error parsing response from App Engine: %v\n", err)
		}
		serveError502(conn, originalHost)
		return
	}

	// Read the full response body.
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		if debugMode {
			fmt.Printf("Error reading response from App Engine: %v\n", err)
		}
		serveError502(conn, originalHost)
		resp.Body.Close()
		return
	}

	// Set the received headers back to the initial connection.
	for k, v := range resp.Header {
		conn.SetHeader(k, v)
	}

	// Write the response body back to the initial connection.
	resp.Body.Close()
	conn.WriteHeader(resp.StatusCode)
	conn.Write(body)

	logRequest(resp.StatusCode, originalHost, conn)

}
Пример #24
0
// Client handhake described in draft-ietf-hybi-thewebsocket-protocol-17
func hybiClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	if !isHybiVersion(config.Version) {
		panic("wrong protocol version.")
	}

	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")

	bw.WriteString("Host: " + config.Location.Host + "\r\n")
	bw.WriteString("Upgrade: websocket\r\n")
	bw.WriteString("Connection: Upgrade\r\n")
	nonce := generateNonce()
	if config.handshakeData != nil {
		nonce = []byte(config.handshakeData["key"])
	}
	bw.WriteString("Sec-WebSocket-Key: " + string(nonce) + "\r\n")
	if config.Version == ProtocolVersionHybi13 {
		bw.WriteString("Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
	} else if config.Version == ProtocolVersionHybi08 {
		bw.WriteString("Sec-WebSocket-Origin: " + strings.ToLower(config.Origin.String()) + "\r\n")
	}
	bw.WriteString("Sec-WebSocket-Version: " + fmt.Sprintf("%d", config.Version) + "\r\n")
	if len(config.Protocol) > 0 {
		bw.WriteString("Sec-WebSocket-Protocol: " + strings.Join(config.Protocol, ", ") + "\r\n")
	}
	// TODO(ukai): send extensions.
	// TODO(ukai): send cookie if any.

	bw.WriteString("\r\n")
	if err = bw.Flush(); err != nil {
		return err
	}

	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
	if err != nil {
		return err
	}
	if resp.StatusCode != 101 {
		return ErrBadStatus
	}
	if strings.ToLower(resp.Header.Get("Upgrade")) != "websocket" ||
		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
		return ErrBadUpgrade
	}
	expectedAccept, err := getNonceAccept(nonce)
	if err != nil {
		return err
	}
	if resp.Header.Get("Sec-WebSocket-Accept") != string(expectedAccept) {
		return ErrChallengeResponse
	}
	if resp.Header.Get("Sec-WebSocket-Extensions") != "" {
		return ErrUnsupportedExtensions
	}
	offeredProtocol := resp.Header.Get("Sec-WebSocket-Protocol")
	if offeredProtocol != "" {
		protocolMatched := false
		for i := 0; i < len(config.Protocol); i++ {
			if config.Protocol[i] == offeredProtocol {
				protocolMatched = true
				break
			}
		}
		if !protocolMatched {
			return ErrBadWebSocketProtocol
		}
		config.Protocol = []string{offeredProtocol}
	}

	return nil
}
Пример #25
0
// NewClient creates a new connection to a host given as "hostname" or "hostname:port".
// If host is not specified, the  DNS SRV should be used to find the host from the domainpart of the JID.
// Default the port to 5222.
func NewClient(host, user, passwd string) (*Client, os.Error) {
	addr := host

	if strings.TrimSpace(host) == "" {
		a := strings.Split(user, "@", 2)
		if len(a) == 2 {
			host = a[1]
		}
	}
	a := strings.Split(host, ":", 2)
	if len(a) == 1 {
		host += ":5222"
	}
	proxy := os.Getenv("HTTP_PROXY")
	if proxy == "" {
		proxy = os.Getenv("http_proxy")
	}
	if proxy != "" {
		url, err := http.ParseRequestURL(proxy)
		if err == nil {
			addr = url.Host
		}
	}
	c, err := net.Dial("tcp", addr)
	if err != nil {
		return nil, err
	}

	if proxy != "" {
		fmt.Fprintf(c, "CONNECT %s HTTP/1.1\r\n", host)
		fmt.Fprintf(c, "Host: %s\r\n", host)
		fmt.Fprintf(c, "\r\n")
		br := bufio.NewReader(c)
		req, _ := http.NewRequest("CONNECT", host, nil)
		resp, err := http.ReadResponse(br, req)
		if err != nil {
			return nil, err
		}
		if resp.StatusCode != 200 {
			f := strings.Split(resp.Status, " ", 2)
			return nil, os.ErrorString(f[1])
		}
	}

	tlsconn := tls.Client(c, &DefaultConfig)
	if err = tlsconn.Handshake(); err != nil {
		return nil, err
	}

	if strings.LastIndex(host, ":") > 0 {
		host = host[:strings.LastIndex(host, ":")]
	}
	if err = tlsconn.VerifyHostname(host); err != nil {
		return nil, err
	}

	client := new(Client)
	client.tls = tlsconn
	if err := client.init(user, passwd); err != nil {
		client.Close()
		return nil, err
	}
	return client, nil
}
Пример #26
0
// Cilent handhake described in (soon obsolete)
// draft-ietf-hybi-thewebsocket-protocol-00
// (draft-hixie-thewebsocket-protocol-76)
func hixie76ClientHandshake(config *Config, br *bufio.Reader, bw *bufio.Writer) (err os.Error) {
	switch config.Version {
	case ProtocolVersionHixie76, ProtocolVersionHybi00:
	default:
		panic("wrong protocol version.")
	}
	// 4.1. Opening handshake.
	// Step 5.  send a request line.
	bw.WriteString("GET " + config.Location.RawPath + " HTTP/1.1\r\n")

	// Step 6-14. push request headers in fields.
	var fields vector.StringVector
	fields.Push("Upgrade: WebSocket\r\n")
	fields.Push("Connection: Upgrade\r\n")
	fields.Push("Host: " + config.Location.Host + "\r\n")
	fields.Push("Origin: " + config.Origin.String() + "\r\n")
	if len(config.Protocol) > 0 {
		if len(config.Protocol) != 1 {
			return ErrBadWebSocketProtocol
		}
		fields.Push("Sec-WebSocket-Protocol: " + config.Protocol[0] + "\r\n")
	}
	// TODO(ukai): Step 15. send cookie if any.

	// Step 16-23. generate keys and push Sec-WebSocket-Key<n> in fields.
	key1, number1 := generateKeyNumber()
	key2, number2 := generateKeyNumber()
	if config.handshakeData != nil {
		key1 = config.handshakeData["key1"]
		n, err := strconv.Atoui(config.handshakeData["number1"])
		if err != nil {
			panic(err)
		}
		number1 = uint32(n)
		key2 = config.handshakeData["key2"]
		n, err = strconv.Atoui(config.handshakeData["number2"])
		if err != nil {
			panic(err)
		}
		number2 = uint32(n)
	}
	fields.Push("Sec-WebSocket-Key1: " + key1 + "\r\n")
	fields.Push("Sec-WebSocket-Key2: " + key2 + "\r\n")

	// Step 24. shuffle fields and send them out.
	for i := 1; i < len(fields); i++ {
		j := rand.Intn(i)
		fields[i], fields[j] = fields[j], fields[i]
	}
	for i := 0; i < len(fields); i++ {
		bw.WriteString(fields[i])
	}
	// Step 25. send CRLF.
	bw.WriteString("\r\n")

	// Step 26. generate 8 bytes random key.
	key3 := generateKey3()
	if config.handshakeData != nil {
		key3 = []byte(config.handshakeData["key3"])
	}
	// Step 27. send it out.
	bw.Write(key3)
	if err = bw.Flush(); err != nil {
		return
	}

	// Step 28-29, 32-40. read response from server.
	resp, err := http.ReadResponse(br, &http.Request{Method: "GET"})
	if err != nil {
		return err
	}
	// Step 30. check response code is 101.
	if resp.StatusCode != 101 {
		return ErrBadStatus
	}

	// Step 41. check websocket headers.
	if resp.Header.Get("Upgrade") != "WebSocket" ||
		strings.ToLower(resp.Header.Get("Connection")) != "upgrade" {
		return ErrBadUpgrade
	}

	if resp.Header.Get("Sec-Websocket-Origin") != config.Origin.String() {
		return ErrBadWebSocketOrigin
	}

	if resp.Header.Get("Sec-Websocket-Location") != config.Location.String() {
		return ErrBadWebSocketLocation
	}

	if len(config.Protocol) > 0 && resp.Header.Get("Sec-Websocket-Protocol") != config.Protocol[0] {
		return ErrBadWebSocketProtocol
	}

	// Step 42-43. get expected data from challenge data.
	expected, err := getChallengeResponse(number1, number2, key3)
	if err != nil {
		return err
	}

	// Step 44. read 16 bytes from server.
	reply := make([]byte, 16)
	if _, err = io.ReadFull(br, reply); err != nil {
		return err
	}

	// Step 45. check the reply equals to expected data.
	if !bytes.Equal(expected, reply) {
		return ErrChallengeResponse
	}
	// WebSocket connection is established.
	return
}
Пример #27
0
func (bucket *Bucket) GetFileInfo(filename string) (file *os.FileInfo, err os.Error) {
	url, e := http.ParseURL(bucket.Url + "/" + filename)
	if e != nil {
		fmt.Println("Error parsing URL", e)
	}
	req := &http.Request{Method: "HEAD", RawURL: bucket.Url + "/" + filename, URL: url, Header: make(map[string]string)}
	date := time.LocalTime().Format(time.RFC1123)
	req.Header["Date"] = date
	bucket.sign(req)
	//req.Write(os.Stdout)

	conn, err := net.Dial("tcp", "", req.URL.Host+":"+req.URL.Scheme)
	req.Write(conn)
	reader := bufio.NewReader(conn)
	resp, _ := http.ReadResponse(reader, req.Method)
	//resp.Write(os.Stdout)

	name := filename

	var mtime int64
	var mode uint

	if resp.Header["x-amz-meta-mtime"] == "" {
		mtime, _ = strconv.Atoi64(resp.GetHeader("Last-Modified"))
	} else {
		mtime, _ = strconv.Atoi64(resp.GetHeader("x-amz-meta-mtime"))
	}

	if resp.Header["X-Amz-Meta-Mode"] == "" {
		if temp := resp.GetHeader("Content-Type"); temp == "application/x-directory" {
			mode = syscall.S_IFDIR
		} else {
			mode = syscall.S_IFREG
		}
	} else {
		fmt.Println(resp.GetHeader("X-Amz-Meta-Mode"))
		mode, _ = strconv.Atoui(resp.GetHeader("X-Amz-Meta-Mode"))
		/*if((mode & syscall.S_IFMT) == syscall.S_IFDIR){
			mode = syscall.S_IFDIR
		} else {
			mode = syscall.S_IFREG
		}*/
	}

	mode2 := uint32(mode)
	//fmt.Print(mode2)

	size, _ := strconv.Atoi64(resp.GetHeader("content-Length"))
	uid, _ := strconv.Atoi(resp.GetHeader("x-amz-meta-uid"))
	gid, _ := strconv.Atoi(resp.GetHeader("x-amz-meta-gid"))

	file = &os.FileInfo{
		Name:     name,
		Mtime_ns: mtime,
		Mode:     mode2,
		Size:     size,
		Uid:      uid,
		Gid:      gid,
	}
	return file, err
}