resource-router-middleware icon indicating copy to clipboard operation
resource-router-middleware copied to clipboard

Any suggestion for not very "standard" rest API?

Open MnHung opened this issue 8 years ago • 5 comments

Hi~

I want to do something like: GET /resources/:id/latest POST /resources/:id

or GET /resources/:id/sub-resource/:sid

I know maybe these APIs are not very restful, but how can I do it?

Thanks

MnHung avatar Mar 06 '17 01:03 MnHung

You can add routes to the middleware after creation - it just returns an Express Router.

https://expressjs.com/en/guide/routing.html

Not sure if there is a way to add new verbs as paths in this lib. Open to a PR though!

developit avatar Mar 06 '17 05:03 developit

Hi~ thank for your reply. I am not so sure if I got your point. Actually I am using your express-es6-rest-api. Take facets.js as example. Do you mean I should do something like the followings?

import resource from 'resource-router-middleware';

export default ({ config, db }) => {

    var router = resource({
        id: 'facet',
        /* functions: load, index, create, read, update and delete */
    });

    /** GET /facet/:id/latest */
    router.get('/:id/latest', function (req, res) {
    });

    /** POST /facet/:id */
    router.post('/:id/', function (req, res) {
    });

    return router;
}

I've tried this way. It works, but it is not pretty like resource-router-middleware

MnHung avatar Mar 12 '17 13:03 MnHung

Yup, that was what I was suggesting. The issue is that resource-router-middleware uses a mapping to figure out how to bind URLs for functions you pass it - for arbitrary function names, it wouldn't know what to map them to:

resource({
  // is this /:id/latest
  // ... or /latest
  // can't really know!
  latest() { }
})

developit avatar Mar 12 '17 15:03 developit

Yeah... I think the mapping is the most simple way to register the routes, since a verb can represent two meanings: HTTP verb and HTTP path. resource-router-middleware is useful for most common cases, but for arbitrary path, I can't figure out a better approach yet.

MnHung avatar Mar 13 '17 04:03 MnHung

I add a search endpoint to the rest in the end:

import resource from 'resource-router-middleware';

export default ({ config, db }) => resource({

	/** Property name to store preloaded entity on `request`. */
	id : 'todo',

	/** GET / - List all entities */
	index({ params }, res) {
		db.todo.findAll().then(function(todos) {
			res.json(todos)
		})
	},

	/** POST / - Create a new entity */
	create({ body }, res) {
		db.todo.create({
			text: 'this is simple todo text',
			done: false
		}).then(function(result) {
			res.json(result)
		})
	},

	/** GET /:id - Return a given entity */
	read({ params }, res) {
		db.todo.findOne({ where: {id: params.todo} }).then(function(todo) {
			res.json(todo)
		})
	},

	/** PUT /:id - Update a given entity */
	update({ params, body }, res) {
		db.todo.update(body, {
			where: {
				id: params.todo
			}
		}).then(function(result) {
			res.json(result)
		})
	},

	/** DELETE /:id - Delete a given entity */
	delete({ params }, res) {
		db.todo.destroy({where: {id: params.todo}}).then(result => {
			res.json(result)
		})
	}
}).get('/search/:keywords', function(req,res) {
	db.todo.findAll({where: 
		{text: 
			{$like: `%${req.params.keywords}%`}
		}
	}).then(result => {
		res.json(result)
	})
})

suhaotian avatar Apr 14 '17 03:04 suhaotian