senecajs / seneca-web

Http route mapping for Seneca microservices.
MIT License
76 stars 44 forks source link

Passing random number of params in get request #117

Closed benbonnet closed 5 years ago

benbonnet commented 7 years ago

Sorry if that sounds obvious, but I could not identify the right way to solve the problem i've encountered

I'd like to have some kind of 'index' routes which can receive a random number of params. For example :

http://seneca-host/api/items/index?sortby=id&filterby=somefilter&etc...

sortby and filterby being the optionals ones

Given the following setup :

var items = function( options ) {
  this.add('role:database,model:items,cmd:index',function(args,done){
    stuff...
  });
}

I could get the expected response before using seneca-web calling it so :

http://seneca-host/act?role=database&model=items&cmd=index&sortby=id&filterby=somefilter

I could easily get the sortby and filterby parameters right from the args returned in the function (args.sortBy and args.filterby)

Now exposing it via seneca-web like so :

module.exports = [{
  prefix: '/api/items',
  pin: 'role:database,model:items,cmd:*',
  map: {
    index: { GET: true }
  }
}]

And calling it like so :

http://seneca-host/api/items/index?sortby=id&filterby=somefilter

I have some problems :

I assume that I might not use the right way to get the expected behavior, but at this point i feel that using seneca-web adds a complexity that is unuseful. For now I moved this function to a POST request in seneca-web, which feels cleaner — passing params in a body, but I still have to reach those by calling args.args.body.

I don't understand this difference of returns between the 'raw' setup and the seneca-web setup.

Hope to get some enlightments from experienced users. Best

tswaters commented 7 years ago

You'd typically want to avoid exposing your seneca actions to the outside world. If you have something like /act?cmd=deleteAllUsers and don't protect it, it can be called.

Plus it's harder... the port that act is exposed at would either need to be hard-coded (which makes scaling to, say, multiple microservices on the same host considerably more difficult), or fetched somehow returned so the front-end stuff can hit it.... A malicious actor can view-source on the page, or look at the network tab and see you are hitting the actions directly and hit one of the internal seneca actions that returns registered actions and aw snap, they have a map of all your actions and can call them by using the same url scheme.... if using mesh, a call to role:mesh,get:members will return that information, I'm certain there's other internal actions that can return for an individual service, but off hand I'm not sure what it is.

Typically in a production setup with a front-end web interface, you would only want to expose what the user should actually be able to do via seneca-web. Even then, you'll probably want to create some sort of authentication and authorization mechanism to ensure your actions aren't being hit by public. Using seneca-web gives you a way to do this. You can expose only the port your web server is running on, and anything the user can access is proxied by this server to the underlying seneca actions.

--

I'm not sure why you are only getting one of the querystring parameters. This is very strange -- the express adapter pulls the information from req.query and passes it along so if you don't see it in your seneca action, it likely means it wasn't parsed properly by express.

See here: https://github.com/tswaters/seneca-web-adapter-express/blob/master/seneca-web-adapter-express.js#L65-L66

I'm assuming express, but the other adapters function in a similar fashion.

tswaters commented 5 years ago

Closing old tickets that should be resolved now.