コード例 #1
0
ファイル: connection.go プロジェクト: notedit/webchan
func ServeRequest(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "http://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}

	tid, err := uuid.NewV4()
	if err != nil {
		log.Error("could not create sessionid")
		return
	}
	id := tid.String()

	c := &connection{SessionId: id, send: make(chan []byte, 256), ws: ws}
	h.register <- c
	go c.writePump()
	c.readPump()
}
コード例 #2
0
ファイル: websocket.go プロジェクト: rose312/samples
// Join method handles WebSocket requests for WebSocketController.
func (this *WebSocketController) Join() {
	uname := this.GetString("uname")
	if len(uname) == 0 {
		this.Redirect("/", 302)
		return
	}

	// Upgrade from http request to WebSocket.
	ws, err := websocket.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(this.Ctx.ResponseWriter, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		beego.Error("Cannot setup WebSocket connection:", err)
		return
	}

	// Join chat room.
	Join(uname, ws)
	defer Leave(uname)

	// Message receive loop.
	for {
		_, p, err := ws.ReadMessage()
		if err != nil {
			return
		}
		publish <- newEvent(models.EVENT_MESSAGE, uname, string(p))
	}
}
コード例 #3
0
ファイル: conn.go プロジェクト: napsy/lab
func newconn(w http.ResponseWriter, r *http.Request) (*conn, error) {
	wconn, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if err != nil {
		return nil, err
	}
	hash := fnv.New32()
	hash.Write([]byte(r.RemoteAddr))
	return &conn{Id(hash.Sum32()), make(chan Msg, 64), wconn, time.NewTicker(pingPeriod)}, nil
}
コード例 #4
0
ファイル: server.go プロジェクト: rif/golang-stuff
// echoReadAll echoes messages from the client by reading the entire message
// with ioutil.ReadAll.
func echoReadAll(w http.ResponseWriter, r *http.Request, writeMessage bool) {
	conn, err := websocket.Upgrade(w, r.Header, nil, 4096, 4096)
	if err != nil {
		log.Println("Upgrade:", err)
		http.Error(w, "Bad request", 400)
		return
	}
	defer conn.Close()
	for {
		op, r, err := conn.NextReader()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if op == websocket.OpPong {
			continue
		}
		if op == websocket.OpText {
			r = &validator{r: r}
		}
		b, err := ioutil.ReadAll(r)
		if err != nil {
			if err == errInvalidUTF8 {
				conn.WriteControl(websocket.OpClose,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
			}
			log.Println("ReadAll:", err)
			return
		}
		if writeMessage {
			err = conn.WriteMessage(op, b)
			if err != nil {
				log.Println("WriteMessage:", err)
			}
		} else {
			w, err := conn.NextWriter(op)
			if err != nil {
				log.Println("NextWriter:", err)
				return
			}
			if _, err := w.Write(b); err != nil {
				log.Println("Writer:", err)
				return
			}
			if err := w.Close(); err != nil {
				log.Println("Close:", err)
				return
			}
		}
	}
}
コード例 #5
0
ファイル: chat.go プロジェクト: nuadnoi32/go.websocket-chat
func wsHandler(w http.ResponseWriter, req *http.Request) {
	ws, err := websocket.Upgrade(w, req.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	//When we try to handle this, see if the hub exists.
	id := mux.Vars(req)["id"]
	wshub.Launch(ws, id)
}
コード例 #6
0
ファイル: ws.go プロジェクト: WoLfh0UnD/WiConnect
func (this *WSController) Get() {
	ws, err := websocket.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(this.Ctx.ResponseWriter, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws, username: randomString(10)}
	h.register <- c
	go c.writePump()
	c.readPump()
}
コード例 #7
0
// documentStream handles websocket requests from the client for a particular document
func documentStream(ctx *web.Context, documentId string) {
	w := ctx.ResponseWriter
	r := ctx.Request
	if r.Header.Get("Origin") != "http://"+r.Host {
		ctx.Abort(403, "Origin not allowed")
		// http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		ctx.Abort(400, "Not a websocket handshake")
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	redis_conn, _ := hub.GetRedis()
	defer redis_conn.Close()
	s, err := redis.String(redis_conn.Do("GET", documentId))
	//make new document at that stringId
	if err != nil {
		doc := document.NewDoc(documentId)
		document_hubs[doc.Name] = hub.DocumentHub{
			Document:    doc,
			Broadcast:   make(chan hub.Message),
			Register:    make(chan *hub.DocumentConnection),
			Unregister:  make(chan *hub.DocumentConnection),
			Connections: make(map[*hub.DocumentConnection]bool),
		}
		h := document_hubs[doc.Name]
		go h.Run()
		json_bytes, _ := json.Marshal(doc)
		redis_conn.Do("SET", documentId, string(json_bytes))
		c := &hub.DocumentConnection{Send: make(chan hub.Message, 256), Ws: ws, H: document_hubs[doc.Name]}
		document_hubs[doc.Name].Register <- c
		mainHub.Broadcast <- json_bytes
		go c.WritePump()
		c.ReadPump()
	} else {
		var doc document.Document
		fmt.Println(s)
		err := json.Unmarshal([]byte(s), &doc)
		if err != nil {
			fmt.Println("Error:", err, s)
		}
		c := &hub.DocumentConnection{Send: make(chan hub.Message, 256), Ws: ws, H: document_hubs[doc.Name]}
		document_hubs[doc.Name].Register <- c
		go c.WritePump()
		c.ReadPump()
	}
}
コード例 #8
0
ファイル: server.go プロジェクト: jaekwon/go-websocket
// echoCopy echoes messages from the client using io.Copy.
func echoCopy(w http.ResponseWriter, r *http.Request, writerOnly bool) {
	conn, err := websocket.Upgrade(w, r.Header, nil, 4096, 4096)
	if err != nil {
		log.Println("Upgrade:", err)
		http.Error(w, "Bad request", 400)
		return
	}
	defer conn.Close()
	for {
		op, r, err := conn.NextReader()
		if err != nil {
			if err != io.EOF {
				log.Println("NextReader:", err)
			}
			return
		}
		if op == websocket.OpPong {
			continue
		}
		if op == websocket.OpText {
			r = &validator{r: r}
		}
		w, err := conn.NextWriter(op)
		if err != nil {
			log.Println("NextWriter:", err)
			return
		}
		if op == websocket.OpText {
			r = &validator{r: r}
		}
		if writerOnly {
			_, err = io.Copy(struct{ io.Writer }{w}, r)
		} else {
			_, err = io.Copy(w, r)
		}
		if err != nil {
			if err == errInvalidUTF8 {
				conn.WriteControl(websocket.OpClose,
					websocket.FormatCloseMessage(websocket.CloseInvalidFramePayloadData, ""),
					time.Time{})
			}
			log.Println("Copy:", err)
			return
		}
		err = w.Close()
		if err != nil {
			log.Println("Close:", err)
			return
		}
	}
}
コード例 #9
0
ファイル: view.go プロジェクト: bitland/ngrok
func NewWebView(ctl *ui.Controller, state ui.State, port int) *WebView {
	v := &WebView{
		wsMessages: util.NewBroadcast(),
	}

	switch p := state.GetProtocol().(type) {
	case *proto.Http:
		NewWebHttpView(v, ctl, p)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/http/in", 302)
	})

	http.HandleFunc("/_ws", func(w http.ResponseWriter, r *http.Request) {
		conn, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)

		if err != nil {
			http.Error(w, "Failed websocket upgrade", 400)
			log.Warn("Failed websocket upgrade: %v", err)
			return
		}

		msgs := v.wsMessages.Reg()
		defer v.wsMessages.UnReg(msgs)
		for m := range msgs {
			err := conn.WriteMessage(websocket.OpText, m.([]byte))
			if err != nil {
				// connection is closed
				break
			}
		}
	})

	http.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
		parts := strings.Split(r.URL.Path, "/")
		name := parts[len(parts)-1]
		fn, ok := static.AssetMap[name]
		if !ok {
			http.NotFound(w, r)
			return
		}
		w.Write(fn())
	})

	log.Info("Serving web interface on localhost:%d", port)
	go http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
	return v
}
コード例 #10
0
ファイル: main.go プロジェクト: mysfsnow/ProjectUnlaaser
func handleWs(out http.ResponseWriter, request *http.Request) {
	if request.Method != "GET" {
		http.Error(out, "Method not allowed", 405)
		return
	}

	ws, err := websocket.Upgrade(out, request.Header, nil, 4096, 4096)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(out, "Not a websocket handshake", 400)
	} else if err != nil {
		log.Println(err)
	} else {
		handleChat(ws)
	}
}
コード例 #11
0
ファイル: view.go プロジェクト: yowenter/http_ngrok
func NewWebView(ctl mvc.Controller, addr string) *WebView {
	wv := &WebView{
		Logger:     log.NewPrefixLogger("view", "web"),
		wsMessages: util.NewBroadcast(),
		ctl:        ctl,
	}

	// for now, always redirect to the http view
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		http.Redirect(w, r, "/http/in", 302)
	})

	// handle web socket connections
	http.HandleFunc("/_ws", func(w http.ResponseWriter, r *http.Request) {
		conn, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)

		if err != nil {
			http.Error(w, "Failed websocket upgrade", 400)
			wv.Warn("Failed websocket upgrade: %v", err)
			return
		}

		msgs := wv.wsMessages.Reg()
		defer wv.wsMessages.UnReg(msgs)
		for m := range msgs {
			err := conn.WriteMessage(websocket.OpText, m.([]byte))
			if err != nil {
				// connection is closed
				break
			}
		}
	})

	// serve static assets
	http.HandleFunc("/static/", func(w http.ResponseWriter, r *http.Request) {
		buf, err := assets.ReadAsset(path.Join("assets", "client", r.URL.Path[1:]))
		if err != nil {
			wv.Warn("Error serving static file: %s", err.Error())
			http.NotFound(w, r)
			return
		}
		w.Write(buf)
	})

	wv.Info("Serving web interface on %s", addr)
	wv.ctl.Go(func() { http.ListenAndServe(addr, nil) })
	return wv
}
コード例 #12
0
func (t wsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	t.Log("HELLOOO")
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		t.Logf("bad method: %s", r.Method)
		return
	}
	if r.Header.Get("Origin") != "http://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		t.Logf("bad origin: %s", r.Header.Get("Origin"))
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, "", 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		t.Logf("bad handshake: %v", err)
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		t.Logf("upgrade error: %v", err)
		return
	}
	defer ws.Close()
	for {
		op, r, err := ws.NextReader()
		if err != nil {
			if err != io.EOF {
				t.Logf("NextReader: %v", err)
			}
			return
		}
		if op == websocket.OpPong {
			continue
		}
		w, err := ws.NextWriter(op)
		if err != nil {
			t.Logf("NextWriter: %v", err)
			return
		}
		if _, err = io.Copy(w, r); err != nil {
			t.Logf("Copy: %v", err)
			return
		}
		if err := w.Close(); err != nil {
			t.Logf("Close: %v", err)
			return
		}
	}
}
コード例 #13
0
ファイル: conn.go プロジェクト: qijian0503/go-websocket
// serverWs handles webocket requests from the client.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, "", 1024, 1024)
	if err != nil {
		log.Println(err)
		http.Error(w, "Bad request", 400)
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	h.register <- c
	go c.writePump()
	c.readPump()
}
コード例 #14
0
ファイル: http_handler.go プロジェクト: jasondelponte/Apollo
// creats the webocket http upgrade handler requests from the client.
func (h *HttpHandler) initServeGbWsHndlr(path string, world *World) {
	http.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) {
		if r.Method != "GET" {
			ErrHttpMethodNotAllowed.Report(w)
			return
		}
		ws, err := gbws.Upgrade(w, r.Header, "", 1024, 1024)
		if err != nil {
			log.Println("Unable to upgrade connection,", err)
			ErrHttpBadRequeset.Report(w)
			return
		}

		h.kickOffPlayer(NewGbWsConn(h.nextConnId, ws), world)
		h.nextConnId++
	})
}
コード例 #15
0
ファイル: conn.go プロジェクト: jacobxk/goonaboat
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	c := &connection{send: make(chan []byte, 256), ws: ws}
	wsHub.register <- c
	go c.writePump()
	c.readPump()
}
コード例 #16
0
// serverWs handles websocket requests from the client.
func serveWs(ctx *web.Context) {
	w := ctx.ResponseWriter
	r := ctx.Request
	if r.Header.Get("Origin") != "http://"+r.Host {
		ctx.Abort(403, "Origin not allowed")
		// http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		ctx.Abort(400, "Not a websocket handshake")
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	c := &hub.Connection{Send: make(chan []byte, 256), Ws: ws, H: mainHub}
	mainHub.Register <- c
	go c.WritePump()
	c.ReadPump()
}
コード例 #17
0
ファイル: connection.go プロジェクト: quintenpalmer/attempt
// serverWs handles webocket requests from the client.
func serveWs(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if strings.Split(r.Header.Get("Origin"), ":")[1] != strings.Split("http://"+r.Host, ":")[1] {
		http.Error(w, "Origin not allowed", 403)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	} else if err != nil {
		log.Println(err)
		return
	}
	c := &connection{ws}
	// Hand the connection over to the world to create a player
	world.register <- c
}
コード例 #18
0
ファイル: main.go プロジェクト: NickCapasso/destinychat
func Handler(w http.ResponseWriter, r *http.Request) {
	// Check if method used was GET.
	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}

	user, banned := getUser(r)
	if banned {
		http.Error(w, "Authorization failed", 403)
		return
	}

	socket, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		http.Error(w, "Not a websocket handshake", 400)
		return
	}

	newConnection(socket, user)

}
コード例 #19
0
ファイル: router.go プロジェクト: rrudduck/golang-stuff
// Handler creates a handler function for this router, that can be used with the
// http-package to handle WebSocket-Connections.
func (router *Router) Handler() func(http.ResponseWriter, *http.Request) {
	return func(w http.ResponseWriter, r *http.Request) {
		// Check if method used was GET.
		if r.Method != "GET" {
			http.Error(w, "Method not allowed", 405)
			return
		}
		// Disallow cross-origin connections.
		if r.Header.Get("Origin") != "http://"+r.Host {
			http.Error(w, "Origin not allowed", 403)
			return
		}
		// Check if handshake callback verifies upgrade.
		if !router.handshakeFunc(w, r) {
			http.Error(w, "Authorization failed", 403)
			return
		}
		// Upgrade websocket connection.
		socket, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
		// Check if handshake was successful
		if _, ok := err.(websocket.HandshakeError); ok {
			http.Error(w, "Not a websocket handshake", 400)
			return
		} else if err != nil {
			log.Println(err)
			return
		}

		// Create the connection.
		conn := newConnection(socket, router)
		//
		if router.connExtensionConstructor.IsValid() {
			conn.extend(router.connExtensionConstructor.Call([]reflect.Value{reflect.ValueOf(conn)})[0].Interface())
		}
		// And start reading and writing routines.
		conn.run()
	}
}
コード例 #20
0
ファイル: connection.go プロジェクト: boombuler/tron2go
// serverWs handles webocket requests from the client.
func serveSocket(w http.ResponseWriter, r *http.Request) {

	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	if r.Header.Get("Origin") != "http://"+r.Host {
		http.Error(w, "Origin not allowed", 403)
		return
	}

	ws, err := websocket.Upgrade(w, r.Header, "", 1024, 1024)

	if err != nil {
		http.Error(w, err.Error(), 400)
		log.Println(err)
		return
	}

	roomid, err := strconv.Atoi(r.URL.RawQuery)
	if err != nil {
		ws.WriteControl(websocket.OpClose, websocket.FormatCloseMessage(4000, "Not a valid room id"), time.Now().Add(writeWait))
		ws.Close()
		return
	}

	room := roomserver.GetRoom(roomid)
	if room == nil {
		ws.WriteControl(websocket.OpClose, websocket.FormatCloseMessage(4004, "Room not found"), time.Now().Add(writeWait))
		ws.Close()
		return
	}

	c := &connection{send: make(chan []byte), receive: make(chan []byte), ws: ws, room: room}
	room.Register <- c
	go c.writePump()
	c.readPump()
}
コード例 #21
0
ファイル: main.go プロジェクト: rif/golang-stuff
func echo(w http.ResponseWriter, r *http.Request) {
	conn, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if err != nil {
		http.Error(w, err.Error(), 400)
		return
	}
	defer conn.Close()
	for {
		op, r, err := conn.NextReader()
		if err != nil {
			return
		}
		if op != websocket.OpBinary && op != websocket.OpText {
			continue
		}
		w, err := conn.NextWriter(op)
		if err != nil {
			return
		}
		io.Copy(w, r)
		w.Close()
	}
}
コード例 #22
0
ファイル: ws_server.go プロジェクト: hamin/fayego
func serveWs(w http.ResponseWriter, r *http.Request) {
	fmt.Println("THIS IS REQUEST URL: ", r.URL.Path)
	fmt.Println("THIS IS REQUEST RAW QUERY: ", r.URL.RawQuery)
	fmt.Println("THIS IS REQUEST HEADER!!! ", r.Header)

	if r.Method != "GET" {
		http.Error(w, "Method not allowed", 405)
		return
	}
	ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		//TODO: move this as a condition of the servelongpolling handling. http.Error(w, "Not a websocket handshake", 400)
		fmt.Println("NOT A WEBSOCKET HANDSHAKE")
		serveLongPolling(f, w, r)
		return
	} else if err != nil {
		fmt.Println(err)
		return
	}

	c := &Connection{send: make(chan string, 256), ws: ws}
	go c.writer(f)
	c.reader(f)
}
コード例 #23
0
ファイル: server.go プロジェクト: ngaut/logbase
// Main entry point.  Collect and respond to socket messages.  When this
// function finishes, the websocket is closed.
func (server *Server) WebsocketSession(w http.ResponseWriter, r *http.Request) {
	ws, err :=
		websocket.Upgrade(
			w,                  // any responder that supports http.Hijack
			r.Header,           // request header string->string map
			nil,                // response header string->string map
			WS_READ_BUFF_SIZE,  // buffer sizes for read...
			WS_WRITE_BUFF_SIZE) // and write
	if server.Debug.Error(err) != nil {
		http.Error(w, err.Error(), 400)
		return
	}
	defer ws.Close()
	session := NewWebsocketSession()
	session.ws = ws
	server.Debug.Basic("Enter SocketSession with id = %v", session.Id())
	//inbyts := make([]byte, WS_READ_BUFF_SIZE)
	//var n int
	for {
		op, r, err := ws.NextReader()
		if err != nil {
			server.Debug.Error(err)
			return
		}
		session.io.in = r
		if op != websocket.OpBinary && op != websocket.OpText {
			continue
		}
		w, err := ws.NextWriter(op)
		if err != nil {
			server.Debug.Error(err)
			return
		}
		session.io.out = w
		/*
			if op == websocket.OpBinary {
				n, err = r.Read(inbyts)
				server.Debug.Fine("Msg rx: %v", inbyts[:n])
				bfr := bufio.NewReader(bytes.NewBuffer(inbyts[:n]))
				binary.Read(bfr, binary.BigEndian, &cmd)
				if cmd == CLOSE {
					server.Debug.Fine("SocketSession closed by client")
					break
				}
				go server.RespondToBinary(cmd, inbyts[CMDSIZE:n], w)
			}
		*/
		if op == websocket.OpText {
			bfr := new(bytes.Buffer)
			bfr.ReadFrom(r)
			intxt := bfr.String()
			server.Debug.Basic("SocketSession incoming: %q", intxt)
			words := strings.Split(intxt, " ")
			//decoder := json.NewDecoder(r)
			//err = decoder.Decode(&intxt)
			//if err != nil {
			//	server.Debug.Error(err)
			//	return
			//}
			cmd, ok := CommandCode[words[0]]
			if !ok {
				server.Debug.Error(FmtErrBadCommand("Command %q not recognised", words[0]))
			}
			if cmd == CLOSE {
				server.Debug.Basic("SocketSession closed by user %s", session.user)
				break
			}
			server.Respond(session, cmd, words[1:])
		}
	}
	return
}
コード例 #24
0
ファイル: server.go プロジェクト: pombredanne/httpfstream
// Follow handles FOLLOW requests to retrieve the contents of a file and a
// real-time stream of data that is appended to the file.
func (h Handler) Follow(w http.ResponseWriter, r *http.Request) {
	path := h.resolve(r.URL.Path)
	h.logf("FOLLOW %s", path)

	// If this file isn't currently being written to, we don't need to update to
	// a WebSocket; we can just return the static file.
	if !h.isWriting(path) {
		h.serveFile(w, r)
		return
	}

	c := make(chan []byte)
	h.addFollower(path, r, c)
	defer h.removeFollower(path, r)

	// TODO(sqs): race conditions galore

	f, err := os.Open(path)
	if err != nil {
		http.Error(w, "failed to open file: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer f.Close()

	// Open WebSocket.
	ws, err := websocket.Upgrade(w, r.Header, nil, readBufSize, writeBufSize)
	if err != nil {
		if _, ok := err.(websocket.HandshakeError); ok {
			// Serve file via HTTP (not WebSocket).
			h.serveFile(w, r)
			return
		}
		h.logf("failed to upgrade to WebSocket: %s", err)
		return
	}
	defer ws.Close()

	// Send persisted file contents.
	for {
		sw, err := ws.NextWriter(websocket.OpText)
		if err != nil {
			h.logf("NextWriter for file failed: %s", err)
			return
		}

		n, err := io.Copy(sw, f)
		if err != nil {
			h.logf("File write to WebSocket failed: %s", err)
			sw.Close()
			return
		}

		err = sw.Close()
		if err != nil {
			h.logf("Failed to close WebSocket file writer: %s", err)
			return
		}

		// Finished reading file.
		if n == 0 {
			break
		}
	}

	// Follow new writes to file.
	var lastPing time.Time
	for {
		tick := time.NewTicker(50 * time.Millisecond)
		select {
		case <-tick.C:
			if !h.isWriting(path) {
				goto done
			}
			if time.Since(lastPing) > followKeepaliveInterval {
				ws.WriteMessage(websocket.OpPing, []byte{})
				lastPing = time.Now()
			}
		case data := <-c:
			sw, err := ws.NextWriter(websocket.OpText)
			if err != nil {
				h.logf("NextWriter failed: %s", err)
				return
			}

			_, err = sw.Write(data)
			if err != nil {
				h.logf("Write to WebSocket failed: %s", err)
				sw.Close()
				return
			}

			err = sw.Close()
			if err != nil {
				h.logf("Failed to close WebSocket writer: %s", err)
				return
			}
		}
	}

done:
	err = ws.WriteControl(websocket.OpClose, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""), time.Time{})
	if err != nil {
		h.logf("Failed to close WebSocket: %s", err)
		return
	}

	err = f.Close()
	if err != nil {
		h.logf("Failed to close destination file: %s", err)
		return
	}
}
コード例 #25
0
ファイル: main.go プロジェクト: jacobxk/goonaboat
func serve(w http.ResponseWriter, r *http.Request) {
	session := r.URL.Query().Get(":session")
	if r.Method == "GET" && r.URL.Query().Get("ws") != "" {
		ws, err := websocket.Upgrade(w, r.Header, nil, 1024, 1024)
		if _, ok := err.(websocket.HandshakeError); ok {
			http.Error(w, "Not a websocket handshake", 400)
			return
		} else if err != nil {
			log.Println(err)
			return
		}
		c := &connection{send: make(chan []byte, 256), ws: ws}
		if _, ok := sessionMap[session]; !ok {
			sessionMap[session] = &hub{
				broadcast:   make(chan []byte),
				register:    make(chan *connection),
				unregister:  make(chan *connection),
				connections: make(map[*connection]bool),
			}
			go sessionMap[session].run()
		}
		sessionMap[session].register <- c
		c.writePump()
		return
	}
	url := "http://" + r.Host + "/"
	config := &oauth.Config{
		ClientId:     *clientID,
		ClientSecret: *clientSecret,
		Scope:        "https://www.googleapis.com/auth/userinfo.profile https://www.googleapis.com/auth/userinfo.email",
		AuthURL:      "https://accounts.google.com/o/oauth2/auth",
		TokenURL:     "https://accounts.google.com/o/oauth2/token",
		RedirectURL:  url,
	}
	if r.URL.Query().Get("authenticate") != "" && session == "" {
		http.Redirect(w, r, config.AuthCodeURL(""), http.StatusFound)
		return
	}
	auth := ""
	authHeader := r.Header.Get("Authorization")
	if authHeader != "" {
		parts := strings.SplitN(authHeader, " ", 2)
		if len(parts) != 2 || parts[0] != "OAuth" {
			http.Error(w, "Authorization header not formatted correctly.", 401)
			return
		}
		auth = parts[1]
	}
	if r.URL.Query().Get("code") != "" && session == "" {
		t := &oauth.Transport{Config: config}
		token, err := t.Exchange(r.URL.Query().Get("code"))
		if err != nil {
			log.Println(err)
			http.Error(w, "OAuth error", 401)
			return
		}
		auth = token.AccessToken
	}
	if r.URL.Query().Get("auth") != "" && session != "" {
		auth = r.URL.Query().Get("auth")
	}
	user := ""
	if auth != "" {
		if _, ok := authCache[auth]; ok {
			if _, ok := authExpirations[auth]; !ok {
				delete(authCache, auth)
			} else {
				if authExpirations[auth].Before(time.Now()) {
					delete(authCache, auth)
					delete(authExpirations, auth)
				} else {
					user = authCache[auth]
				}
			}
		}
	}
	if auth != "" && user == "" {
		t := &oauth.Transport{
			Config: config,
			Token: &oauth.Token{
				AccessToken: auth,
			},
		}
		req, err := http.NewRequest("GET", "https://www.googleapis.com/oauth2/v1/userinfo", nil)
		if err != nil {
			log.Println(err)
			http.Error(w, "Error verifying OAuth authorization.", 401)
			return
		}
		resp, err := t.RoundTrip(req)
		if err != nil {
			log.Println(err)
			http.Error(w, "Error verifying OAuth authorization.", 401)
			return
		}
		body, err := ioutil.ReadAll(resp.Body)
		if err != nil {
			log.Println(err)
			http.Error(w, "Error verifying OAuth authorization.", 401)
			return
		}
		var account Account
		err = json.Unmarshal(body, &account)
		if err != nil {
			log.Println(err)
			http.Error(w, "Error verifying OAuth authorization.", 401)
			return
		}
		if account.Error != nil {
			log.Println("Google error.")
			log.Println(account.Error.Message)
			http.Error(w, account.Error.Message, account.Error.StatusCode)
			return
		}
		user = account.Email
	}
	if user != "" && auth != "" {
		authCache[auth] = user
		authExpirations[auth] = time.Now()
	}
	log.Println(auth)
	log.Println(user)
	log.Println(session)
	if user != "" && session == "" {
		http.Redirect(w, r, url+user+"?auth="+auth, http.StatusFound)
	}
	if r.Method == "POST" {
		if user == session && user != "" {
			body, err := ioutil.ReadAll(r.Body)
			if err != nil {
				log.Println(err)
				http.Error(w, "Error reading request body.", 400)
				return
			}
			var slidepos positions
			err = json.Unmarshal(body, &slidepos)
			if err != nil {
				log.Println(err)
				http.Error(w, "Error parsing JSON.", 400)
				return
			}
			bytes, err := json.Marshal(slidepos)
			if err != nil {
				log.Println(err)
				http.Error(w, "Error marshalling response.", 500)
				return
			}
			if _, ok := sessionMap[session]; ok {
				sessionMap[session].broadcast <- bytes
			}
			w.WriteHeader(200)
			w.Write([]byte("success"))
		} else {
			http.Error(w, "Invalid auth.", 401)
			return
		}
	} else {
		err := temp.Execute(w, TemplateData{Controller: user == session, Session: session, Host: r.Host, Auth: auth})
		if err != nil {
			log.Println(err)
		}
	}
}
コード例 #26
0
ファイル: server.go プロジェクト: pombredanne/httpfstream
// Append handles APPEND requests and appends data to a file.
func (h Handler) Append(w http.ResponseWriter, r *http.Request) {
	path := h.resolve(r.URL.Path)
	h.logf("APPEND %s", path)

	defer r.Body.Close()

	err := h.addWriter(path)
	if err != nil {
		h.logf("addWriter %s: %s", err)
		http.Error(w, "addWriter: "+err.Error(), http.StatusForbidden)
		return
	}
	defer h.removeWriter(path)

	err = os.MkdirAll(filepath.Dir(path), 0755)
	if err != nil {
		http.Error(w, "failed to create dir: "+err.Error(), http.StatusInternalServerError)
		return
	}

	f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
	if err != nil {
		http.Error(w, "failed to open destination file for writing: "+err.Error(), http.StatusInternalServerError)
		return
	}
	defer f.Close()

	ws, err := websocket.Upgrade(w, r.Header, nil, readBufSize, writeBufSize)
	if err != nil {
		if _, ok := err.(websocket.HandshakeError); ok {
			h.logf("not a WebSocket handshake: %s", err)
			return
		}
		h.logf("failed to upgrade to WebSocket: %s", err)
		return
	}
	defer ws.Close()

	ws.SetReadDeadline(time.Now().Add(readWait))
	for {
		op, rd, err := ws.NextReader()
		if err != nil {
			if err != io.ErrUnexpectedEOF {
				h.logf("NextReader failed: %s", err)
			}
			break
		}
		switch op {
		case websocket.OpPong:
			ws.SetReadDeadline(time.Now().Add(readWait))
		case websocket.OpText:
			var buf bytes.Buffer
			mw := io.MultiWriter(f, &buf)

			// Persist to file.
			_, err := io.Copy(mw, rd)
			if err != nil {
				h.logf("Read from WebSocket failed: %s", err)
				return
			}

			// Broadcast to followers.
			followers := h.getFollowers(path)
			for _, fc := range followers {
				fc <- buf.Bytes()
			}
			ws.SetReadDeadline(time.Now().Add(readWait))
		}
	}

	err = r.Body.Close()
	if err != nil {
		h.logf("failed to close upload stream: %s", err)
		return
	}

	err = f.Close()
	if err != nil {
		h.logf("failed to close destination file: %s", err)
		return
	}
}
コード例 #27
0
ファイル: web.go プロジェクト: kenshinx/restmq.go
func (wsh *WSQueueHandler) handshake(r *http.Request, w http.ResponseWriter) (ws *websocket.Conn, err error) {
	ws, err = websocket.Upgrade(w, r.Header, nil, 1024, 1024)
	return
}