如何最好地在 Node.js 中创建 RESTful API
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14990544/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to best create a RESTful API in Node.js
提问by
I'm a beginner in Node (and generally all back-end web development), and I have started to write a RESTful API in Node. There are a few things I'm trying to get my head around.
我是 Node 的初学者(通常都是后端 Web 开发),并且我已经开始在 Node 中编写 RESTful API。有几件事我正在努力解决。
My application uses Express and Mongoose, and I am using the express-resourcemodule to easily create my CRUD routes for the API resources. But there are a couple of things I am unhappy about, and think I could do better.
我的应用程序使用 Express 和 Mongoose,并且我正在使用该express-resource模块为 API 资源轻松创建我的 CRUD 路由。但是有几件事我不满意,我认为我可以做得更好。
The first is Mongoose. If I want to write tests for my API, I have no way of stubbing Mongoose to force it to in memory data. All of the tutorials out there seem to point to Mongoose, however, and I'm really not sure what I should be using.
第一个是猫鼬。如果我想为我的 API 编写测试,我无法通过 stub Mongoose 将其强制写入内存数据。然而,那里的所有教程似乎都指向 Mongoose,而且我真的不确定我应该使用什么。
Secondly, my resource seems to have a lot of boilerplate code. Is this really the best way to create a RESTful API in Node.js? Are there other modules that will help me to create my CRUD routes? I believe there are ways you can create CRUD routes right from your schema, without anymore code, but I'm really not sure how.
其次,我的资源似乎有很多样板代码。这真的是在 Node.js 中创建 RESTful API 的最佳方式吗?是否有其他模块可以帮助我创建 CRUD 路由?我相信有一些方法可以直接从您的架构创建 CRUD 路由,而无需更多代码,但我真的不确定如何。
I have seen projects out there such as Tower.js and CompoundJS (formally RailwayJS) that seem to be these comprehensive solutions that solve much more than my issues here. Perhaps I should be using them, but I really only want the Node.js application to be an API and nothing more. I am dealing with the front-end independently of the API.
我见过一些项目,例如 Tower.js 和 CompoundJS(正式名称为 RailroadJS),它们似乎是这些综合解决方案,解决的问题比我在这里的问题要多得多。也许我应该使用它们,但我真的只希望 Node.js 应用程序是一个 API,仅此而已。我正在独立于 API 处理前端。
To provide some context, here is my current situation. Currently, I have a model defined in Mongoose:
为了提供一些背景,这是我目前的情况。目前,我在 Mongoose 中定义了一个模型:
var mongoose = require('mongoose')
, Schema = mongoose.Schema
, Link
var LinkSchema = new Schema({
uri: String,
meta: {
title: String,
desc: String
},
shares: [{
uid: Schema.Types.ObjectId,
date: Date,
message: String
}]
})
Link = module.exports = mongoose.model('Link')
Next, I define the controllers for the CRUD routes:
接下来,我为 CRUD 路由定义控制器:
var mongoose = require('mongoose')
, _ = require('underscore')
, Link = mongoose.model('Link')
exports.load = function (req, id, fn) {
Link.findById(req.params.link, function (err, link) {
if (err) {
return res.send(err)
}
fn(null, link)
})
}
exports.index = function (req, res) {
var filterByUser = req.query.user ? { 'shares.uid': req.query.user } : {}
Link.find(filterByUser, function (err, links) {
if (err) {
return res.send(err)
}
res.send(links)
})
}
exports.create = function (req, res) {
var link = new Link(req.body)
link.save(function (err) {
if (err) {
// TODO: send 404
return res.send(err)
}
res.send(link)
})
}
exports.show = function (req, res) {
res.send(req.link)
}
exports.update = function (req, res) {
req.link = _(req.link).extend(req.body)
req.link.save(function (err, link) {
if (err) {
return res.send(err)
}
res.send(link)
})
}
exports.patch = exports.update
exports.destroy = function (req, res) {
req.link.remove(function (err) {
if (err) {
return res.send(err)
}
res.send()
})
}
Finally, I use the express-resourcemodule to map these controllers to the necessary CRUD routes on top of the Express app.
最后,我使用该express-resource模块将这些控制器映射到 Express 应用程序顶部的必要 CRUD 路由。
app.resource('api/links', require('../resources/links'))
回答by Bentheitroad
You should look into restify
你应该看看restify
If you want to use express, you can also check out this project that I made -- called node-restful.
如果你想使用 express,你也可以查看我制作的这个项目——叫做node-restful。
This library seems to be much more mature and have more features though: https://github.com/jspears/mers
这个库似乎更加成熟并且具有更多功能:https: //github.com/jspears/mers
回答by Sean McClory
Strongloop Loopbackseeems to be another good alternative for generating Node/MongoDB APIs. It can also generate mocha teststoo.
Strongloop Loopback似乎是生成 Node/MongoDB API 的另一个不错的选择。它还可以生成mocha 测试。
回答by ramon22
Take a look at Hapiits a configuration-centric framework for building web applications and APIs its used as restful service.
看看Hapi,它是一个以配置为中心的框架,用于构建用作 Restful 服务的 Web 应用程序和 API。
Other options are sails.jsand actionhero
其他选项是sails.js和actionhero
回答by joeytwiddle
Strapiis a new (2015) framework.
Strapi是一个新的(2015)框架。
The admin interface on their website allows you to create an API and specify relationships between models. (As can be seen in their introduction video.)
他们网站上的管理界面允许您创建 API 并指定模型之间的关系。(从他们的介绍视频中可以看出。)
However it is designed to run on the Koa server, not on Express.
然而,它被设计为在 Koa 服务器上运行,而不是在 Express 上运行。
回答by wprl
I recommend Baucis + Express. Thousands of users, model-driven design based on Mongoose, very flexible, spec-compliant, HATEOAS/Level 3 ready. Fits all my needs perfectly. But then, I'm the author :) https://github.com/wprl/baucis
我推荐 Baucis + Express。数以千计的用户,基于 Mongoose 的模型驱动设计,非常灵活,符合规范,HATEOAS/Level 3 就绪。完美满足我的所有需求。但是,我是作者:) https://github.com/wprl/baucis
回答by yokodev
回答by elawcn
Here is the issues about the frameworks nowadays.
这是当今有关框架的问题。
When you come here from google searching "best", "fastest" framework blah, blah, people will drop a line says "Hey, you should try this sails.js, feathers, Derby etc..."
当你从谷歌搜索“最好的”、“最快的”框架等等来这里时,人们会放下一行说“嘿,你应该试试这个sails.js、feather、Derby等等……”
Ok The question is: - Are you just for fun with those frameworks - if yes, you can easily get a list of frameworks and then start to benchmark them whatsoever.
好的问题是: - 你只是为了好玩这些框架 - 如果是,你可以轻松获得框架列表,然后开始对它们进行任何基准测试。
- I am assuming most of people are "I want to build a product, build a site can make money in the future, or at least it will become popular";
- 我假设大部分人是“我要建一个产品,建个网站将来能赚钱,或者至少会流行起来”;
Ok, all you search keywords and attentions here is wrong, try to search "production ready", "enterprise ready", "case study" those keywords then, or maybe go to indeed.com and search node.js, further dig out what node.js framework most companies using, the answer maybe just simply say "express".
好吧,你在这里搜索的关键词和attention都是错误的,尝试搜索“生产就绪”、“企业就绪”、“案例研究”这些关键词,或者去indeed.com搜索node.js,进一步挖掘什么大多数公司使用的 node.js 框架,答案可能只是简单地说“表达”。
if so, From node.js stack, The frameworks will pretty much be narrowed down a few of them: Hapi, Strongloop, or even not popular one Mojito from Yahoo
如果是这样,从 node.js 堆栈中,框架将几乎缩小其中的一些:Hapi、Strongloop,甚至不流行的一种来自 Yahoo 的 Mojito
For Those frameworks at least you can tell - "They are really production or enterprise ready" - cos' they have been using form Walmart, from Yahoo, from other big giants from some time, some even for couple of years.
对于那些框架,至少你可以说 - “它们真的是生产或企业就绪” - 因为他们一直在使用沃尔玛,雅虎,其他大巨头一段时间,有些甚至几年。
Can this explain why Ruby on rails and Django still dominate the full stack framework markets? even you see lots of "cool" frameworks keeping on coming to the market, Meteor, Sails.js, Go's Revel, Java's Play Spark whatever you can name - It doesn't mean these frameworks worse than the two, just mean they need time to win the market.
这能解释为什么 Ruby on rails 和 Django 仍然主导着全栈框架市场吗?即使你看到很多“很酷”的框架不断涌入市场,Meteor、Sails.js、Go 的 Revel、Java 的 Play Spark,无论你能说出什么名字——这并不意味着这些框架比这两个框架更糟糕,只是意味着它们需要时间赢得市场。
Another problems lots of the current frameworks are a kind of all-in-one, clone of "Ror"; From the end user's prospect, They just need a thing to help them get things done, need productive, need something to work from the begin to the end, like Ruby on Rails, like MacOS, like windows, like anything itself which has been tested by the time, has been daily used by people.
许多当前框架的另一个问题是一种多合一的“Ror”的克隆;从最终用户的前景来看,他们只需要一个东西来帮助他们完成任务,需要生产力,需要一些东西从头到尾都可以工作,比如 Ruby on Rails,比如 MacOS,比如 Windows,比如任何经过测试的东西本身到了那个时候,已经被人们日常使用了。
回答by Ashane.E
This is a sample to perform CRUD operations in a library system
这是在图书馆系统中执行 CRUD 操作的示例
var schema=require('../dbSchema');
var bookmodel=schema.model('book');
exports.getBooks = function (req,res) {
bookmodel.find().exec().then((data)=>{
res.send(data)
}).catch((err)=>{
console.log(err);
});
};
exports.getBook = function (req,res) {
var bkName=req.params.Author;
bookmodel.find({Name:bkName}).exec().then((data)=>{
res.send(data)
}).catch((err)=>{
console.log(err);
});
};
exports.getAutBooks = function (req,res) {
bookmodel.find({},'Author').then((data)=>{
res.send(data);
}).catch((err)=>{
console.log(err);
});
};
exports.deleteBooks=function(req,res){
var bkName=req.params.name;
bookmodel.remove({Name:bkName}).exec().then((data)=>{
res.status(200);
console.log(bkName);
}).catch((err)=>{
console.log(err);
});
};
exports.addBooks=function(req,res){
var newBook=new bookmodel({
Name:req.body.Name,
ISBN:req.body.ISBN,
Author:req.body.Author,
Price:req.body.Price,
Year:req.body.Year,
Publisher:req.body.Publisher
});
newBook.save().then(()=>{
res.status(201);
}).catch((err)=>{
console.log(err);
});
};
回答by Thilina Imalka
var mongoose = require('../DBSchema/SchemaMapper');
var UserSchema = mongoose.model('User');
var UserController = function(){
this.insert = (data) => {
return new Promise((resolve, reject) => {
var user = new UserSchema({
userName: data.userName,
password: data.password
});
user.save().then(() => {
resolve({status: 200, message: "Added new user"});
}).catch(err => {
reject({status: 500, message: "Error:- "+err});
})
})
}
this.update = (id, data) => {
return new Promise((resolve, reject) => {
UserSchema.update({_id: id}, data).then(() => {
resolve({status: 200, message: "update user"});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.searchAll = () => {
return new Promise((resolve, reject) => {
UserSchema.find().exec().then((data) => {
resolve({status: 200, data: data});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.search = (id) => {
return new Promise((resolve, reject) => {
UserSchema.find({_id:id}).exec().then(user => {
resolve({status: 200, data: user});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.delete = (id) => {
return new Promise((resolve, reject) => {
UserSchema.remove({_id:id}).then(() => {
resolve({status: 200, message: "remove user"});
}).catch(err => {
reject({status: 500, message:"Error:- " + err});
})
})
}
}
module.exports = new UserController();
///Route
var express = require('express');
var router = express.Router();
var Controller = require('./User.Controller');
router.post('/', (req, res) => {
Controller.insert(req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.put('/:id', (req, res) => {
Controller.update(req.params.id, req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.get('/', (req, res) => {
Controller.searchAll().then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.get('/:id', (req, res) => {
Controller.search(req.params.id).then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.delete('/:id', (req, res) => {
Controller.delete(req.params.id).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
})
module.exports = router;
//db`enter code here`schema
var mongoose = require('mongoose');
const Schema = mongoose.Schema;
var Supplier =new Schema({
itemId:{
type:String,
required:true
},
brand:{
type:String,
required:true
},
pno:{
type:String,
required:true
},
email:{
type:String,
required:true
}
});
mongoose.model('Inventory',Inventory);
mongoose.model('Supplier',Supplier);
mongoose.connect('mongodb://127.0.0.1:27017/LAB', function (err) {
if (err) {
console.log(err);
process.exit(-1);
}
console.log("Connected to the db");
});
module.exports = mongoose;
回答by user3205479
I am a big fan of express and I've been using it to build RESTful APIs on Node.js which are easier to build. However, when our application started growing, we ended in a situation where express structure did not scale well and with more code splitting around, it was harder for us to maintain.
我是 express 的忠实粉丝,我一直在使用它在 Node.js 上构建更容易构建的 RESTful API。然而,当我们的应用程序开始增长时,我们最终遇到了一种情况,即 express 结构不能很好地扩展,并且随着更多的代码拆分,我们更难维护。
I am from C#/Java background where SOLID principles are heavily used. Frameworks like Java Spring / C# WebAPIare proven to create enterprise level applications.
I wanted to have a framework where I can reuse my existing C#/Java skills (reuse I mean MVC architecture, OOPS, SOLID, DI, Mocks ... yeah, strong typing). Unfortunately, I did not find a framework which meets my requirements (It should have less learning curve, minimalist codebase size, completely express compatible).
我来自 C#/Java 背景,其中大量使用了 SOLID 原则。类似Java Spring / C# WebAPI的框架已被证明可以创建企业级应用程序。我想要一个框架,我可以在其中重用我现有的 C#/Java 技能 ( reuse I mean MVC architecture, OOPS, SOLID, DI, Mocks ... yeah, strong typing)。不幸的是,我没有找到符合我要求的框架 ( It should have less learning curve, minimalist codebase size, completely express compatible)。
What do I mean by completely express compatible?Whatever express does, I must be able to do it even If I use a framework on top of it, when I have looked into Strongloop Loopbackit was pretty good to use but It had a lot of documentation to go through and the frameworks are coupled, not really what I was looking for.
我所说的完全兼容是什么意思?无论 express 做什么,即使我在它上面使用框架,我也必须能够做到,当我查看Strongloop Loopback 时,它使用起来非常好,但是它有很多文档需要阅读,并且框架是耦合的,并不是我真正想要的。
So I have created Dinolooppowered by Typescript (has interfaces, classes, abstract classes and strong oops). The package is pretty stable now.
所以我创建Dinoloop搭载打字稿(has interfaces, classes, abstract classes and strong oops)。这个包现在很稳定。
With Dinoloop you can build enterprise level applications in a scalable architecture.
It uses Dependency Injection framework but you can configure any DI frameworks available in typescript. Dinoloop enables typescript to use as a Nodejs REST framework that helped me to maintain common typescript codebase for both angularand nodeprojects.
使用 Dinoloop,您可以在可扩展的架构中构建企业级应用程序。它使用依赖注入框架,但您可以配置打字稿中可用的任何 DI 框架。Dinoloop 使 typescript 能够用作 Nodejs REST 框架,帮助我为项目angular和node项目维护通用的 typescript 代码库。
So, Dinoloop is a perfect fit for typescript lovers and angular developers.
因此,Dinoloop 非常适合打字稿爱好者和 Angular 开发人员。


