feathersjs / feathers

The API and real-time application framework
https://feathersjs.com
MIT License
14.99k stars 744 forks source link

Service events with parameterized url #217

Closed tinque closed 8 years ago

tinque commented 8 years ago

I've created a service with parameterized url like this :

app.use('/todos/:todosList',todosService);

I post a todo in the list plop for exemple :

POST /todos/plop HTTP/1.1
Host: example.org
Content-Type: application/json; charset=utf-8
Content-Length: 19

{"message": "ok", "extended": true}

To subscribe on the client on the create event, i have to do this :

socket.on('todos/:todosList created', function(todo) {
    console.log('Got a new Todo!', todo);
  });

This following code doesn't work :

socket.on('todos/plop created', function(todo) {
    console.log('Got a new Todo!', todo);
  });

Is it possible to have the event parameterized too ?

Thks

daffl commented 8 years ago

Currently events can not be parameterized since the placeholder just gets processed in HTTP routes and not for websockets. Making what you are suggesting possible wouldn't be too hard though. Basically we just have to format path using hook.params in https://github.com/feathersjs/feathers-socket-commons/blob/739f7205f07db8fb1883932b67e6eb1619f2748d/src/events.js#L69 and then probably send two events.

The inconsistency then would be that it won't work for method calls. For example, if you wanted to find all todos for the list through websockets you'd have to pass the parameter:

socket.emit('todos/:todoList::find', { todoList: 'plop' }, function(error, todoList) {
  console.log('Todo successfully created');
});

The reason is that the server would have to set up an event listener for every possible route otherwise which we can't do because there is no cross-library way to catch all websocket events.

tinque commented 8 years ago

Ok Thanks for your answer.

ekryski commented 8 years ago

Correct me if I'm wrong here @daffl but as an alternative you should be able to listen for todos::find and then just filter for the todoList param in your own code though.

daffl commented 8 years ago

The service name is always the string you pass in app.use. So app.use('/todos/:todosList',todosService); will register a service called todos/:todosList. The todosList parameter will be set as params.todosList not as params.query.todosList so it depends on what your service does with it.

For example if you have something like /users/:userId/todos you may want to set params.query.user_id = params.userId to get all todos for the user.

lock[bot] commented 5 years ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue with a link to this issue for related bugs.