共计 6256 个字符,预计需要花费 16 分钟才能阅读完成。
Express
在 myApp.js
文件的前两行中,创立一个 Express 利用对象很简略。这个对象有几种办法,一个根底的办法是 app.listen(port)
。它处于运行状态时通知服务器监听指定的端口。出于测试的起因,须要利用在后盾运行,所以在 server.js
中曾经增加了这个办法。
在 Express 中,路由采纳这种构造:app.METHOD(PATH, HANDLER)
,METHOD 是 http 申请办法的小写模式,PATH 是服务器上的相对路径(它能够是一个字符串,甚至能够是正则表达式),HANDLER 是匹配路由时 Express 调用的函数,处理函数采纳这种模式:function(req, res) {...}
,其中 req 是申请对象,res 是响应对象,例如:
function(req, res) {res.send('Response String');
} //“Response String”
app.get("/", function(req, res) {res.send("Hello Express");
})
提供 HTML 文件
通过 res.sendFile(path)
办法给申请响应一个文件,能够把它放到路由解决 app.get('/', ...)
中。在后盾,这个办法会依据想发送的文件的类型,设置适当的音讯头信息来通知浏览器如何解决它,而后读取并发送文件,此办法须要文件的绝对路径。倡议应用 Node. js 的全局变量 __dirname
来计算出这个文件的绝对路径:
absolutePath = __dirname + relativePath/file.ext
var express = require('express');
var app = express();
let absolutePath = __dirname + "/views/index.html";
app.get("/", function(req, res) {res.sendFile(absolutePath);
});
module.exports = app;
提供动态资源
HTML 服务器通常有一个或多个用户能够拜访的目录。能够将应用程序所需的动态资源 (样式表、脚本、图片) 放在那里。在 Express 中能够应用中间件 express.static(path)
来设置此性能,它的参数 path
就是蕴含动态资源文件的绝对路径。
其实,中间件就是一个拦挡路由解决办法并在外面增加一些信息的函数。应用 app.use(path, middlewareFunction)
办法来加载一个中间件,它的第一个参数 path
是可选的,如果没设置第一个参数,那么所有的申请都会通过这个中间件解决。
app.use("/public", express.static(__dirname + "/public"));
在指定路由上提供 JSON
HTML 服务器提供 HTML 服务,而 API 提供数据服务。REST(REpresentational State Transfer)API 容许以简略的形式进行数据交换,对于客户端不必要晓得服务器的细节。客户只须要晓得资源在哪里(URL),以及想执行的动作(动词)。GET 动词常被用来获取无需批改的信息。现在,网络上的挪动数据首选格局是 JSON,简而言之,JSON 是一种能够不便地用字符串示意 JavaScript 对象的形式,因而它很容易传输。
来创立一个简略的 API,创立一个门路为 /json
且返回数据是 JSON 格局的路由,能够像之前那样用 app.get()
办法来做。而后在路由解决局部应用 res.json()
办法,并传入一个对象作为参数,这个办法会完结申请响应循环(request-response loop),而后返回数据。在后盾,它把一个无效的 JavaScript 对象转化为字符串,而后会设置适当的音讯头来通知浏览器:“这是一个 JSON 数据”,最初将数据返回给客户端。一个无效的对象通常是这种构造:{key: data}
,data
能够是数字、字符串、嵌套对象或数组,data
也能够是变量或者函数返回值,在这种状况下,它们先求值再转成字符串。
app.get("/json", function(req, res) {
res.json({"message": "Hello json"});
})
当向路由 /json
发送 GET 申请,将对象 {"message": "Hello json"}
以 JSON 格局返回给客户端,浏览器拜访 your-app-url/json
时,应该在屏幕上看到这个音讯。
应用 .env 文件
.env
文件是一个用于将环境变量传给应用程序的暗藏文件,这是一个除了开发者之外没人能够拜访的私密文件,它能够用来存储窃密或者暗藏的数据,例如,它能够存储第三方服务的 API 密钥或者数据库 URI,也能够应用它来存储配置选项,通过设置配置选项,扭转应用程序的行为,而无需重写一些代码。
在应用程序中通过 process.env.VAR_NAME
拜访到环境变量。process.env
对象是 Node 程序中的一个全局对象,能够给这个变量传字符串。习惯上,变量名全副大写,单词之间用下划线分隔。.env
是一个 shell 文件,因而不须要用给变量名和值加引号。还有一点须要留神,当你给变量赋值时等号两侧不能有空格,例如:VAR_NAME=value
。通常来讲,每一个变量定义会独占一行。
app.get('/json', (function(req,res) {const mySecret = process.env['MESSAGE_STYLE'];
if(mySecret === "uppercase"){res.json({"message" : "Hello json".toUpperCase() });
} else {res.json({"message" : "Hello json"});
}
}))
增加一个环境变量作为配置选项。
在我的项目根目录创立一个 .env
文件,并存储变量 MESSAGE_STYLE=uppercase
。
当向 /json
发 GET 申请时,如果 process.env.MESSAGE_STYLE
的值为 uppercase
,那么上一次挑战中的路由处理程序返回的对象的音讯则应该大写。响应对象应该是 {"message": "Hello json"}
or {"message": "HELLO JSON"}
,取决于 MESSAGE_STYLE
的值。
留神: 在本地工作,须要 dotenv
包。它将环境变量从的 .env
文件加载到 process.env
中。应用 npm install dotenv
装置它。而后,在 myApp.js
文件的顶部,应用 require('dotenv').config()
导入和加载变量。
实现一个根级的申请记录中间件 Root-Level Request Logger Middleware
中间件函数是一个接管 3 个参数的函数,这 3 个参数别离是:申请对象、响应对象和在利用的申请 - 响应循环中的下一个函数。中间件函数执行一些可能对应用程序产生一些成果的代码,通常还会在申请对象或者响应对象里增加一些信息,它们也能够在满足某些条件时通过发送响应来完结循环,如果在它们实现时没有发送响应,那么就会开始执行堆栈中的下一个函数,next()
将触发调用第 3 个参数。
请看以下示例:
function(req, res, next) {console.log("I'm a middleware...");
next();}
假如在某个路由上装置了这个中间件函数,当一个申请与路由匹配时,它会显示字符串“I’m a middleware…”,而后它执行堆栈中的下一个函数。能够应用 app.use(<mware-function>)
办法。在这种状况下,该函数将对所有申请执行,但也能够设置更具体的条件来执行,例如,如果你心愿某个函数只针对 POST 申请执行,能够应用 app.post(<mware-function>)
办法。所有的 HTTP 动词(GET、DELETE、PUT……)都存在相似的办法。
app.use(function(req, res, next) {console.log(req.method + "" + req.path +" - " + req.ip);
next();})
留神: Express 依照函数在代码中呈现的程序来执行,中间件也是如此。如果想让中间件函数实用于所有路由,那么应该在路由之前配置好中间件。
通过链式调用中间件来创立工夫服务 Chain Middleware
应用 app.METHOD(path, middlewareFunction)
能够在指定的路由挂载中间件,也能够在路由定义中链式调用中间件。
请看以下示例:
app.get('/user', function(req, res, next) {req.user = getTheUserSync();
next();}, function(req, res) {res.send(req.user);
});
此办法可用于将服务操作拆分为较小的单元,这能够让利用领有更好的构造,也便于在不同的地位上复用代码;此办法还可用于对数据执行某些验证。能够在每一个中间件堆栈中,阻止以后链的执行,并将控制权传递给专门设计用于处理错误的函数;或者能够将控制权传递给下一个匹配的路由,以解决非凡状况。
从客户端获取路由参数 Route Parameter
在构建 API 时,要让用户阐明他们想从服务中获取什么。举个例子,如果客户申请数据库中存储的用户信息,须要一种办法让开发者晓得用户对哪个数据库用户项感兴趣,应用路由参数能够实现这个需要。路由参数是由斜杠(/)分隔的 URL 命名段,每一小段能捕捉与其地位匹配的 URL 局部的值,捕捉的值可能在 req.params
对象中找到。
路由地址:’/user/:userId/book/:bookId’
理论申请 URL:’/user/546/book/6754′
req.params:{userId: ‘546’, bookId: ‘6754’}
app.get("/:word/echo", (req, res) => {const { word} = req.params;
res.json({echo: word});
});
从客户端获取输出的查问数据 Query Parameter
从客户端获取输出的另一种常见形式是应用查问字符串对路由门路中的数据进行编码,查问字符串应用标记(?)分隔,并且蕴含键值对 field=value,每对键值应用连字号(&)分隔。Express 可能从查问字符串中解析这些数据,并且把它放到 req.query
对象中。有些字符(如百分号(%))不能在呈现在 URL 中,它们在发送前必须以不同的格局进行编码。如果应用 JavaScript 的 API,能够用特定的办法来编码 / 解码这些字符。
路由地址:’/library’
理论申请 URL:’/library?userId=546&bookId=6754′
req.query:{userId: ‘546’, bookId: ‘6754’}
留神: 在前面的练习中,咱们将向雷同的路由门路 /name
发送 POST 申请来接收数据。如果违心,能够应用 app.route(path).get(handler).post(handler)
这中写法,这种语法容许在同一门路路由上链式调用不同的申请办法,能够节俭一点打字工夫,也能够让代码看起来更清晰。
app.get("/name", function(req, res) {
res.json({name: `${req.query.first} ${req.query.last}`
});
})
body-parser
除了 GET 还有另一个常见的 HTTP 动词,即 POST。POST 是应用 HTML 表单发送客户端数据的默认办法。在 REST 标准中,POST 罕用于发送数据以在数据库中创立新我的项目(新用户或新博客文章)。在这个我的项目中没有应用数据库,但上面将学习如何解决 POST 申请。
在这种类型的申请中,数据不会呈现在 URL 中,而是暗藏在申请注释中。申请注释也是 HTML 申请的一部分,被称为负载。即便数据在 URL 中是不可见的,也不意味着它是公有的。要理解起因,请察看 HTTP POST 申请的原始内容:
POST /path/subpath HTTP/1.0
From: [email protected]
User-Agent: someBrowser/1.0
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
name=John+Doe&age=25
正如你所看到的,注释被编码成相似查问字符串的模式,这是 HTML 表单应用的默认格局。能够通过 Ajax 应用 JSON 来解决具备更简单构造的数据。还有另一种类型的编码:multipart/form-data,它被用来上传二进制文件。应用 URL 编码申请注释。要解析来自 POST 申请的数据,必须装置 body-parser
包,这个包蕴含一套能够解码不同格局数据的中间件。
var express = require('express');
var bodyParser = require("body-parser");
var app = express();
app.use(bodyParser.urlencoded({ extended: false}));
app.use(bodyParser.json());
从 POST 申请中获取数据
在门路 /name
挂载一个 POST 解决办法,和后面一样,咱们曾经在 html 首页筹备了一份表单,它将提交与练习 10 雷同的数据(查问字符串),如果 body-parser 正确配置好了,那么就能够在 req.body
对象中找到申请的参数。来看看一个惯例的例子:
路由:POST ‘/library’
URL 编码的申请注释:userId=546&bookId=6754
req.body:{userId: ‘546’, bookId: ‘6754’}
响应和后面一样的 JSON 对象 {name: 'firstname lastname'}
。能够应用首页利用提供的 html 表单,来测试 API 是否失常工作。
提醒:除了 GET 和 POST,还有其余几种 http 办法。依照常规,http 动词和在服务端执行的某种操作之间有对应关系,这种对应关系通常如下:
POST(有时候是 PUT)- 应用申请发送信息,以创立新资源;
GET – 读取不必批改的已存在的资源;
PUT 或者 PATCH(有时候是 POST)- 发送数据,以更新资源;
DELETE => 删除一个资源。
还有其余两种办法罕用于与服务进行交互。除了 GET 之外,下面列出的所有办法都能够负载数据(即数据都能放到音讯注释中),这些办法也能够应用 body-parser 中间件。
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({extended: false}));
const path = require('path')
app.post("/name", function(req, res) {
var string = req.body.first + " " + req.body.last;
res.json({name: string});
});
module.exports = app;