Example #1
0
// NewServer creates a new server.
func NewServer(addr string) (*Server, error) {
	if (Conf == Config{}) {
		InitConf("")
	}

	s := Server{
		server: neptulon.NewServer(addr),
		db:     NewInMemDB(),
		queue:  NewQueue(),
	}

	s.server.MiddlewareFunc(middleware.Logger)
	s.pubRoutes = middleware.NewRouter()
	s.server.Middleware(s.pubRoutes)
	initPubRoutes(s.pubRoutes, s.db, Conf.App.JWTPass())

	//all communication below this point is authenticated
	s.server.MiddlewareFunc(jwt.HMAC(Conf.App.JWTPass()))
	s.server.Middleware(&s.queue)
	s.privRoutes = middleware.NewRouter()
	s.server.Middleware(s.privRoutes)
	initPrivRoutes(s.privRoutes, &s.queue)
	// r.Middleware(NotFoundHandler()) - 404-like handler

	// todo: research a better way to handle inner-circular dependencies so remove these lines back into Server contructor
	// (maybe via dereferencing: http://openmymind.net/Things-I-Wish-Someone-Had-Told-Me-About-Go/, but then initializers
	// actually using the pointer values would have to be lazy!)
	s.queue.SetServer(s.server)

	s.server.DisconnHandler(func(c *neptulon.Conn) {
		// only handle this event for previously authenticated
		if id, ok := c.Session.GetOk("userid"); ok {
			s.queue.RemoveConn(id.(string))
		}
	})

	return &s, nil
}
Example #2
0
// NewClient creates a new Client object.
func NewClient() (*Client, error) {
	c, err := neptulon.NewConn()
	if err != nil {
		return nil, err
	}

	r := middleware.NewRouter()
	c.Middleware(r)

	return &Client{
		ID:      c.ID,
		Session: c.Session,
		conn:    c,
		router:  r,
	}, nil
}
Example #3
0
// InMsgHandler registers a handler to accept incoming messages from the server.
func (c *Client) InMsgHandler(handler func(m []Message) error) {
	r := middleware.NewRouter()
	c.conn.Middleware(r)
	r.Request("msg.recv", func(ctx *neptulon.ReqCtx) error {
		var msg []Message
		if err := ctx.Params(&msg); err != nil {
			return fmt.Errorf("client: msg.recv: error reading request params: %v", err)
		}

		if err := handler(msg); err != nil {
			return err
		}

		ctx.Res = ACK
		return ctx.Next()
	})
}
Example #4
0
func TestEcho(t *testing.T) {
	sh := NewServerHelper(t)
	route := middleware.NewRouter()
	sh.Server.MiddlewareFunc(middleware.Logger)
	sh.Server.Middleware(route)
	route.Request("echo", middleware.Echo)
	defer sh.ListenAndServe().CloseWait()

	ch := sh.GetConnHelper().Connect()
	defer ch.CloseWait()

	m := "Hello!"
	ch.SendRequestSync("echo", echoMsg{Message: m}, func(ctx *neptulon.ResCtx) error {
		var msg echoMsg
		if err := ctx.Result(&msg); err != nil {
			t.Fatal(err)
		}
		if msg.Message != m {
			t.Fatalf("expected: %v got: %v", m, msg.Message)
		}
		return nil
	})
}
Example #5
0
// Helper method for testing client implementations in other languages.
// Flow of events for this function is:
// * Send a {"method":"echo", "params":{"message": "..."}} request to client upon first 'echo' request from client,
//   and verify that message body is echoed properly in the response body.
// * Echo any incoming request message body as is within a response message.
// * Repeat ad infinitum, until {"method":"close", "params":"{"message": "..."}"} is received. Close message body is logged.
func TestExternalClient(t *testing.T) {
	sh := NewServerHelper(t)
	sh.Server.MiddlewareFunc(middleware.Logger)
	var wg sync.WaitGroup
	m := "Hello from Neptulon server!"

	// handle 'echo' requests via the 'echo middleware'
	srout := middleware.NewRouter()
	sh.Server.Middleware(srout)
	srout.Request("echo", func(ctx *neptulon.ReqCtx) error {
		// send 'echo' request to client upon connection (blocks test if no response is received)
		wg.Add(1)
		ctx.Conn.SendRequest("echo", echoMsg{Message: m}, func(ctx *neptulon.ResCtx) error {
			defer wg.Done()
			var msg echoMsg
			if err := ctx.Result(&msg); err != nil {
				t.Fatal(err)
			}
			if msg.Message != m {
				t.Fatalf("server: expected: %v got: %v", m, msg.Message)
			}
			t.Logf("server: client sent response to our 'echo' request: %v", msg.Message)
			return nil
		})

		// unmarshall incoming message into response directly
		if err := ctx.Params(&ctx.Res); err != nil {
			return err
		}
		return ctx.Next()
	})

	// handle 'close' request (blocks test if no response is received)
	wg.Add(1)
	srout.Request("close", func(ctx *neptulon.ReqCtx) error {
		defer wg.Done()
		if err := ctx.Params(&ctx.Res); err != nil {
			return err
		}
		err := ctx.Next()
		// ctx.Conn.Close() // todo: investigate the error message!!!
		t.Logf("server: closed connection with message from client: %v\n", ctx.Res)
		return err
	})

	defer sh.ListenAndServe().CloseWait()

	if *extFlog {
		t.Log("Started server and waiting for external client integration test since -ext flag is provided.")
		wg.Wait()
		return
	}

	// use internal conn implementation instead to test the test case itself
	t.Log("Skipping external client integration test since -ext flag is not provided.")
	ch := sh.GetConnHelper()
	ch.Conn.MiddlewareFunc(middleware.Logger)

	// handle 'echo' requests via the 'echo middleware'
	crout := middleware.NewRouter()
	ch.Conn.Middleware(crout)
	crout.Request("echo", middleware.Echo)
	defer ch.Connect().CloseWait()

	// handle 'echo' request and send 'close' request upon echo response
	mc := "Hello from Neptulon Go client!"
	ch.SendRequestSync("echo", echoMsg{Message: mc}, func(ctx *neptulon.ResCtx) error {
		var msg echoMsg
		if err := ctx.Result(&msg); err != nil {
			t.Fatal(err)
		}
		if msg.Message != mc {
			t.Fatalf("client: expected: %v got: %v", mc, msg.Message)
		}
		t.Log("client: server accepted and echoed 'echo' request message body")

		// send close request after getting our echo message back
		mb := "Thanks for echoing! Over and out."
		ch.SendRequestSync("close", echoMsg{Message: mb}, func(ctx *neptulon.ResCtx) error {
			var msg echoMsg
			if err := ctx.Result(&msg); err != nil {
				t.Fatal(err)
			}
			if msg.Message != mb {
				t.Fatalf("client: expected: %v got: %v", mb, msg.Message)
			}
			t.Log("client: server accepted and echoed 'close' request message body. bye!")
			return nil
		})

		return nil
	})
}