Exemple #1
0
func handleGetEnviron(ctx *web.Context) (map[string]string, error) {
	if err := errorIfNotMaster(ctx); err != nil {
		return nil, err
	}
	ctx.ContentType("json")
	s := ctx.User.(*server)
	return s.session.Environ(), nil
}
Exemple #2
0
// List of files nice for tab completion
func handleGetFiles(ctx *web.Context) error {
	if err := errorIfNotMaster(ctx); err != nil {
		return err
	}
	ctx.ContentType("json")
	paths, err := filepath.Glob(ctx.Params["pattern"])
	if err != nil {
		return err
	}
	if paths == nil {
		paths = []string{}
	}
	return json.NewEncoder(ctx).Encode(paths)
}
Exemple #3
0
func handleGetCmdJson(ctx *web.Context, idstr string) error {
	id, _ := liblush.ParseCmdId(idstr)
	s := ctx.User.(*server)
	c := s.session.GetCommand(id)
	if c == nil {
		return web.WebError{404, "no such command: " + idstr}
	}
	md, err := metacmd{c}.Metadata()
	if err != nil {
		return err
	}
	ctx.ContentType("json")
	// Don't hammer me, but don't cache for too long. This resource is not
	// intended for polling, anyway. This may seem race sensitive, but that's
	// because it is. Only matters in big, multi user setups with lots of
	// concurrent changes, which is totally not lush's current intended use
	// case. So a few race conditions here and there are no biggy (for now).
	ctx.Response.Header().Set("cache-control", "max-age=3")
	return json.NewEncoder(ctx).Encode(md)
}
Exemple #4
0
func handleGetCmdidsJson(ctx *web.Context) error {
	s := ctx.User.(*server)
	ids := s.session.GetCommandIds()
	ctx.ContentType("json")
	return json.NewEncoder(ctx).Encode(ids)
}
Exemple #5
0
// Websocket control connection. All connected clients are considered equal.
func handleWsCtrl(ctx *web.Context) error {
	wsconn, err := websocket.Upgrade(ctx.Response, ctx.Request, nil, 1024, 1024)
	if _, ok := err.(websocket.HandshakeError); ok {
		// Get the secret token to include in a websocket request
		ctx.ContentType("txt")
		fmt.Fprint(ctx.Response, getWebsocketKey())
		return nil
	} else if err != nil {
		return err
	}
	s := ctx.User.(*server)
	ws := newWsClient(wsconn)
	defer ws.Close()
	// This is just for the incoming key, after which blocking on read is fine
	err = ws.SetReadDeadline(time.Now().Add(5 * time.Second))
	if err != nil {
		return fmt.Errorf("Couldn't set read deadline for websocket: %v", err)
	}
	// First order of business: see if the client sends me the correct key
	// this could be done lots of ways different, perhaps more elegant ways:
	// HTTP headers, query parameters, secret path, ... BUT! This method is very
	// straight-forward and easy to understand.
	msg, err := ws.ReadTextMessage()
	if err != nil {
		return err
	}
	if string(msg) != getWebsocketKey() {
		// This is a best effort service to help whoever tried to connect to
		// this in debugging, hence no error checking.
		fmt.Fprint(ws, "Invalid lush key")
		return errors.New("Illegal websocket key")
	}
	// Alright I trust this client now, read ops are expected to block
	err = ws.SetReadDeadline(time.Time{})
	if err != nil {
		return fmt.Errorf("Couldn't remove read deadline for websocket: %v", err)
	}
	// tell the client about its Id
	_, err = fmt.Fprint(ws, "clientid;", ws.Id)
	if err != nil {
		return fmt.Errorf("Websocket write error: %v", err)
	}
	// Subscribe this ws client to all future control events. Will be removed
	// automatically when the first Write fails (FlexibleMultiWriter).
	// Therefore, no need to worry about removing: client disconnects -> next
	// Write fails -> removed.
	s.ctrlclients.AddWriter(ws)
	// notify all other clients that a new client has connected
	wseventAllclients(s, "") // pretend somebody generated this event
	// TODO: keep clients updated about disconnects, too
	ws.isMaster = claimMaster(ctx)
	for {
		msg, err := ws.ReadTextMessage()
		if err != nil {
			s.ctrlclients.RemoveWriter(ws)
			return err
		}
		err = parseAndHandleWsEvent(s, ws, msg)
		if err != nil {
			return fmt.Errorf("error handling WS event: %v", err)
		}
	}
	return errors.New("unreachable")
}
Exemple #6
0
func process(ctx *web.Context) string {
	ctx.ContentType("txt")
	return fmt.Sprintf("%#v", ctx.Params)
}