fix(i18n): update Chinese translation of basic node and express (#38889)

This commit is contained in:
ZhichengChen
2020-09-07 13:40:31 +08:00
committed by GitHub
parent c23c4ef8e4
commit 5a72d44482
12 changed files with 229 additions and 100 deletions

View File

@ -1,18 +1,32 @@
---
id: 587d7fb1367417b2b2512bf4
title: Chain Middleware to Create a Time Server
localeTitle: 链中间件创建时间服务器
challengeType: 2
forumTopicId: 301510
localeTitle: 使用链中间件来创建时间服务器
---
## Description
<section id='description'>使用<code>app.METHOD(path, middlewareFunction)</code>可以在特定路径上安装<code>app.METHOD(path, middlewareFunction)</code> 。中间件也可以在路由定义中链接。查看以下示例:
<blockquote>app.get('/user', function(req, res, next) {<br> req.user = getTheUserSync(); // Hypothetical synchronous operation<br> next();<br>}, function(req, res) {<br> res.send(req.user);<br>})</blockquote>此方法可用于将服务器操作拆分为较小的单元。这导致了更好的应用程序结构以及在不同位置重用代码的可能性。此方法还可用于对数据执行某些验证。在中间件堆栈的每个点您可以阻止当前链的执行并将控制权传递给专门用于处理错误的函数。或者您可以将控制权传递给下一个匹配的路径以处理特殊情况。我们将在高级Express部分中看到如何。在路径<code>app.get('/now', ...)</code>链中间件函数和最终处理程序。在中间件功能中,您应该在<code>req.time</code>键中将当前时间添加到请求对象。您可以使用<code>new Date().toString()</code> 。在处理程序中使用JSON对象进行响应采用结构<code>{time: req.time}</code> 。提示:如果不链接中间件,测试将无法通过。如果将函数挂载到其他位置,即使输出结果正确,测试也会失败。
<section id='description'>
使用<code>app.METHOD(path, middlewareFunction)</code>可以将中间件挂载到指定的路由。中间件也可以在路由定义中链接。
请看以下示例:
```js
app.get('/user', function(req, res, next) {
req.user = getTheUserSync(); // Hypothetical synchronous operation
next();
}, function(req, res) {
res.send(req.user);
});
```
此方法可用于将服务操作拆分为较小的单元。这样可以让应用拥有更好的结构,以便于在不同的位置上复用代码。此方法还可用于对数据执行某些验证。在每一个中间件堆栈中,你都可以阻止当前链的执行,并将控制权传递给专门设计用于处理错误的函数。或者你可以将控制权传递给下一个匹配的路径,以处理特殊情况。我们将在高级 Express 章节中看到。
</section>
## Instructions
<section id='instructions'>
在路由<code>app.get('/now', ...)</code>链中,在中间件函数中,你应该在<code>req.time</code>里将当前时间添加到请求对象中。你可以使用<code>new Date().toString()</code>。在处理函数中,使用<code>{time: req.time}</code>结构的 JSON 对象来响应。
提示: 如果不链接中间件,测试将不能通过。如果将中间件函数挂载在其他地方,即使输出结果正确,测试也会失败。
</section>
## Tests
@ -20,9 +34,9 @@ challengeType: 2
```yml
tests:
- text: / now端点应该已经安装了中间件
- text: 路由 /now 应该已经挂载了中间件
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/chain-middleware-time'').then(data => { assert.equal(data.stackLength, 2, ''"/now" route has no mounted middleware''); }, xhr => { throw new Error(xhr.responseText); })'
- text: / now端点应返回从现在起+/- 20秒的时间
- text: 路由 /now 应该返回一个从现在开始 +/-20 秒的时间
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/chain-middleware-time'').then(data => { var now = new Date(); assert.isAtMost(Math.abs(new Date(data.time) - now), 20000, ''the returned time is not between +- 20 secs from now''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -38,7 +52,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,17 +1,22 @@
---
id: 587d7fb2367417b2b2512bf8
title: Get Data from POST Requests
localeTitle: 从POST请求中获取数据
challengeType: 2
forumTopicId: 301511
localeTitle: 从 POST 请求中获取数据
---
## Description
<section id='description'> 在路径<code>/name</code>处安装POST处理程序。它和以前一样。我们在html首页中准备了一个表单。它将提交练习10查询字符串的相同数据。如果正确配置了body-parser您应该在对象<code>req.body</code>找到参数。看看通常的库示例:
<blockquote>route: POST '/library'<br>urlencoded_body: userId=546&bookId=6754 <br>req.body: {userId: '546', bookId: '6754'}</blockquote> 使用与以前相同的JSON对象进行响应 <code>{name: 'firstname lastname'}</code> 。使用我们在应用程序首页中提供的html表单测试您的端点是否正常工作。 提示除了GET和POST之外还有其他几种http方法。按照惯例http动词与您要在服务器上执行的操作之间存在对应关系。传统的映射是
POST有时是PUT - 使用随请求发送的信息创建新资源,
GET - 读取现有资源而不修改它,
PUT或PATCH有时是POST - 使用数据更新资源已发送,
DELETE =&gt;删除资源。 还有一些其他方法用于协商与服务器的连接。除了GET之外上面列出的所有其他方法都可以有一个有效载荷即数据进入请求体。身体解析器中间件也适用于这些方法。
<section id='description'>
在路径<code>/name</code>处挂载一个 POST 处理方法。和前面一样。我们已经在 html 首页准备了一份表格。它将提交与练习 10 相同的数据(查询字符串)。如果 body-parser 正确配置好了,你就可以在<code>req.body</code>对象中找到请求的参数。来看看一个常规的请求 /library 例子:
<blockquote>route: POST '/library'<br>urlencoded_body: userId=546&bookId=6754 <br>req.body: {userId: '546', bookId: '6754'}</blockquote>
和前面一样响应一个 JSON 对象<code>{name: 'firstname lastname'}</code>。你可以使用首页应用提供的 html 表单,来测试你的 API 是否正常工作。
提示: 除了 GET 和 POST还有其他几种 http 方法。按照惯例http 动词之间有对应关系,它们分别对应你在服务端执行的某种操作,传统的对应关系:
POST (有时候是 PUT) - 使用请求发送信息,以创建新资源,
GET - 读取已存在的资源,不用修改它,
PUT 或者 PATCH (有时候是 POST) - 发送数据,以更新资源,
DELETE => 删除一个资源。
还有一些其他方法,常用于与服务进行交互。除了 GET 之外,上面列出的所有方法都可以负载数据(换言之,数据都能在请求体中找到)。也可以使用 body-parser 来正常工作。
</section>
## Instructions
@ -24,9 +29,9 @@ DELETE =&gt;删除资源。 还有一些其他方法用于协商与服务器的
```yml
tests:
- text: '测试1您的API端点应使用正确的名称进行响应'
- text: 测试 1你的 API 应该使用正确的名称响应
testString: 'getUserInput => $.post(getUserInput(''url'') + ''/name'', {first: ''Mick'', last: ''Jagger''}).then(data => { assert.equal(data.name, ''Mick Jagger'', ''Test 1: "POST /name" route does not behave as expected'') }, xhr => { throw new Error(xhr.responseText); })'
- text: '测试2您的API端点应使用正确的名称进行响应'
- text: 测试 2你的 API 应该使用正确的名称响应
testString: 'getUserInput => $.post(getUserInput(''url'') + ''/name'', {first: ''Keith'', last: ''Richards''}).then(data => { assert.equal(data.name, ''Keith Richards'', ''Test 2: "POST /name" route does not behave as expected'') }, xhr => { throw new Error(xhr.responseText); })'
```
@ -42,7 +47,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,21 @@
---
id: 587d7fb2367417b2b2512bf6
title: Get Query Parameter Input from the Client
localeTitle: 从客户端获取查询参数输入
challengeType: 2
forumTopicId: 301512
localeTitle: 从客户端获取查询参数输入
---
## Description
<section id='description'> 从客户端获取输入的另一种常用方法是使用查询字符串对路径路径后的数据进行编码。查询字符串由问号分隔并包括field = value couple。每对夫妇用和号隔开。 Express可以解析查询字符串中的数据并填充对象<code>req.query</code> 。某些字符不能在URL中它们必须以<a href='https://en.wikipedia.org/wiki/Percent-encoding' target='_blank'>不同的格式</a>编码才能发送它们。如果您使用JavaScript中的API则可以使用特定方法对这些字符进行编码/解码。
<section id='description'>
从客户端获取输入的另一种常见方式是使用查询字符串对路由路径中的数据进行编码。查询字符串使用标记 (?) 分隔,并且包含一对<code>field=value</code>。每一对键值使用符号 (&) 分隔。Express 能够从查询字符串中分析这些数据,并且把它放到<code>req.query</code>对象中。有些字符不能在出现在 URL 中,它们在发送前必须以<a href='https://en.wikipedia.org/wiki/Percent-encoding' target='_blank'>不同的格式</a>进行编码。如果你使用来自 JavaScript 的 API你可以使用特定的方法来编码/解码这些字符。
<blockquote>route_path: '/library'<br>actual_request_URL: '/library?userId=546&bookId=6754' <br>req.query: {userId: '546', bookId: '6754'}</blockquote>
</section>
## Instructions
<section id='instructions'>
构建一个<code>GET /name</code>挂载的API端点。使用结构<code>{ name: 'firstname lastname'}</code>回复JSON文档。名字和姓氏参数应该在查询字符串中编码,例如<code>?first=firstname&amp;last=lastname</code> 。 提示:在下面的练习中,我们将在相同<code>/name</code>路径路径的POST请求中接收数据。如果需要可以使用方法<code>app.route(path).get(handler).post(handler)</code> 。此语法允许您在同一路径路径上链接不同的动词处理程序。您可以节省一些打字,并拥有更清晰的代码。
构建一个 API ,使用路由挂载<code>GET /name</code>。使用一个 JSON 文件来响应,它的结构是这样的:<code>{ name: 'firstname lastname'}</code>。名字和姓氏参数应该编码在查询参数中,举个例子:<code>?first=firstname&last=lastname</code>.
提示: 在下面的练习中,我们将从相同的<code>/name</code>路由路径中 POST 请求接收数据。如果你愿意,你可以使用<code>app.route(path).get(handler).post(handler)</code>这中写法,此语法允许你在同一路径路由上链接不同的 HTTP 动词处理函数。可以节省一点打字时间,并且可以让代码看起来更清晰。
</section>
## Tests
@ -20,9 +23,9 @@ challengeType: 2
```yml
tests:
- text: '测试1您的API端点应使用正确的名称进行响应'
- text: 测试 1你的 API 应该使用正确的名称响应
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/name?first=Mick&last=Jagger'').then(data => { assert.equal(data.name, ''Mick Jagger'', ''Test 1: "GET /name" route does not behave as expected'') }, xhr => { throw new Error(xhr.responseText); })'
- text: '测试2您的API端点应以正确的名称响应'
- text: 测试 2你的 API 应该使用正确的名称响应
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/name?last=Richards&first=Keith'').then(data => { assert.equal(data.name, ''Keith Richards'', ''Test 2: "GET /name" route does not behave as expected'') }, xhr => { throw new Error(xhr.responseText); })'
```
@ -38,7 +41,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,20 @@
---
id: 587d7fb2367417b2b2512bf5
title: Get Route Parameter Input from the Client
localeTitle: 从客户端获取路由参数输入
challengeType: 2
forumTopicId: 301513
localeTitle: 从客户端获取路由参数输入
---
## Description
<section id='description'> 构建API时我们必须允许用户与我们沟通他们希望从我们的服务中获得什么。例如如果客户端请求有关存储在数据库中的用户的信息他们需要一种方法让我们知道他们感兴趣的用户。实现此结果的一种可能方法是使用路由参数。路由参数是URL的命名段由斜杠/分隔。每个段捕获URL的与其位置匹配的部分的值。捕获的值可以在<code>req.params</code>对象中找到。
<section id='description'>
在构建 API 时,我们要让用户告诉我们他们想从服务中获取什么。举个例子,如果客户请求数据库中存储的用户信息,他们需要一种方法让我们知道他们对哪个用户感兴趣。实现这个需求的的方式就是使用路由参数。路由参数是由斜杠 (/) 分隔的 URL 命名段。每一小段能捕获与其位置匹配的 URL 部分的值。捕获的值能够在<code>req.params</code>对象中找到。
<blockquote>route_path: '/user/:userId/book/:bookId'<br>actual_request_URL: '/user/546/book/6754' <br>req.params: {userId: '546', bookId: '6754'}</blockquote>
</section>
## Instructions
<section id='instructions'>
构建一个安装在路径<code>GET /:word/echo</code>的回显服务器。使用结构<code>{echo: word}</code>响应JSON对象。可以在<code>req.params.word</code>找到要重复的<code>req.params.word</code> 。您可以浏览器的地址栏测试的路线,访问一些匹配的路线,例如 your-app-rootpath/freecodecamp/echo
在路由中<code>GET /:word/echo</code>构建一个 echo 服务,响应一个采用<code>{echo: word}</code>结构的 JSON 对象。可以在<code>req.params.word</code>找到要重复的单词。你可以浏览器的地址栏测试的路,访问一些匹配的路由,比如:your-app-rootpath/freecodecamp/echo
</section>
## Tests
@ -20,9 +22,9 @@ challengeType: 2
```yml
tests:
- text: '测试1您的echo服务应该正确重复单词'
- text: 测试 1你的 echo 服务应该正确重复单词
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/eChOtEsT/echo'').then(data => { assert.equal(data.echo, ''eChOtEsT'', ''Test 1: the echo server is not working as expected'') }, xhr => { throw new Error(xhr.responseText); })'
- text: '测试2您的echo服务应该正确重复单词'
- text: 测试 2你的 echo 服务应该正确重复单词
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/ech0-t3st/echo'').then(data => { assert.equal(data.echo, ''ech0-t3st'', ''Test 2: the echo server is not working as expected'') }, xhr => { throw new Error(xhr.responseText); })'
```
@ -38,7 +40,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,31 @@
---
id: 587d7fb1367417b2b2512bf3
title: Implement a Root-Level Request Logger Middleware
localeTitle: 实现根级请求记录器中间件
challengeType: 2
forumTopicId: 301514
localeTitle: 实现一个根层的请求记录器中间件
---
## Description
<section id='description'> 在我们介绍<code>express.static()</code>中间件函数之前。现在是时候更详细地看看中间件是什么了。中间件函数是带有3个参数的函数请求对象响应对象和应用程序请求 - 响应周期中的下一个函数。这些函数执行一些可能对应用程序产生副作用的代码,并且通常会向请求或响应对象添加信息。当满足某些条件时,它们还可以结束发送响应的循环。如果他们没有发送响应,当他们完成时,他们开始执行堆栈中的下一个函数。触发调用第三个参数<code>next()</code><a href='http://expressjs.com/en/guide/using-middleware.html' target='_blank'>快递文档</a>中的更多信息。 查看以下示例:
<blockquote>function(req, res, next) {<br> console.log("I'm a middleware...");<br> next();<br>}</blockquote> 假设我们在路线上安装了此功能。当请求与路由匹配时,它会显示字符串“我是中间件......”。然后它执行堆栈中的下一个函数。 在本练习中我们将构建一个根级中间件。正如我们在挑战4中所见要在根级别安装中间件功能我们可以使用方法<code>app.use(&lt;mware-function&gt;)</code> 。在这种情况下将对所有请求执行该功能但您也可以设置更具体的条件。例如如果您希望仅为POST请求执行某个函数则可以使用<code>app.post(&lt;mware-function&gt;)</code> 。所有http动词都有类似的方法GETDELETEPUT...
<section id='description'>
前面我们介绍了<code>express.static()</code>中间件函数。现在是时候更详细地了解什么是中间件了。中间件是一个接收 3 个参数的函数:请求对象、响应对象和在应用请求响应循环中的下一个函数。这些函数执行一些可能对应用程序产生副作用的代码,通常还会在请求对象或者响应对象里添加一些信息。当满足某些条件时,它们也可以结束发送响应的循环。如果它们没有发送响应,那么当它们完成时就会开始执行堆栈中的下一个函数。这将触发调用第 3 个参数<code>next()</code>。更多信息请查看 <a href='http://expressjs.com/en/guide/using-middleware.html' target='_blank'>express 文档</a>
看看下面的例子:
```js
function(req, res, next) {
console.log("I'm a middleware...");
next();
}
```
假设我们在某个路由上安装了这个中间件函数。当一个请求与路由匹配时,它会显示字符串"我是中间件..."。然后它执行堆栈中的下一个函数。
在这个练习中,我们将构建根级中间件。正如我们在挑战 4 中看到的,要在根层级安装中间件函数,我们可以使用<code>app.use(&lt;mware-function&gt;)</code>方法。在这种情况下,该函数将对所有请求执行,但是你还是可以设置成更具体的条件来执行。举个例子,如果你希望某个函数只针对 POST 请求执行,可以使用<code>app.post(&lt;mware-function&gt;)</code>方法。所有 http 动作都有类似的方法,比如 GET、DELETE、PUT 等等。
</section>
## Instructions
<section id='instructions'>
构建一个简单的记录器。对于每个请求,它应该在控制台中录一个字符串,采用以下格式: <code>method path - ip</code> 。示例如下: <code>GET /json - ::ffff:127.0.0.1</code> 。请注意, <code>method</code><code>path</code>之间有一个空格,并且破折号分隔<code>path</code><code>ip</code>被两侧的空格包围。您可以使用<code>req.method</code> <code>req.path</code><code>req.ip</code>从请求对象获取请求方法http谓词相对路由路径和调用者的ip。记得在完成后调用<code>next()</code> ,否则你的服务器将永远停留。确保打开“日志”,并查看某些请求到达时会发生什么... 提示Express按照它们在代码中出现的顺序评估函数。中间件也是如此。如果您希望它适用于所有路由则应在它们之前安装它。
构建一个简单的日志记录器。对于每个请求,它应该在控制台中录一个采用以下格式的字符串<code>method path - ip</code>。一个简单的日志看起来就像这样:<code>GET /json - ::ffff:127.0.0.1</code>。注意<code>method</code><code>path</code>有一个空格,并且<code>path</code><code>ip</code>中间的破折号两边都有空格。在请求对象中,可以使用<code>req.method</code><code>req.path</code><code>req.ip</code>获取请求方法http 动词)、路由相对路径和请求者的 IP 信息。记住,当你完成时,要调用<code>next()</code>方法,否则你的服务器将一直处于挂起状态。请确保 "Logs" 是打开的,观察一下当一些请求被响应时会发生什么……
提示: Express 按照函数在代码中出现的顺序来评估函数。中间件也是如此。如果你想让中间件函数适用于所有路由,那么应该在路由之前配置好中间件。
</section>
## Tests
@ -20,7 +33,7 @@ challengeType: 2
```yml
tests:
- text: 根级记录器中间件应该是活动的
- text: 根级记录器中间件应该被激活
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/root-middleware-logger'').then(data => { assert.isTrue(data.passed, ''root-level logger is not working as expected''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -36,7 +49,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,16 +1,24 @@
---
id: 587d7fb0367417b2b2512bed
title: Meet the Node console
localeTitle: 认识节点控制台
challengeType: 2
forumTopicId: 301515
localeTitle: 认识 Node 的控制台
---
## Description
<section id='description'> 在开发过程中,能够检查代码中发生的情况非常重要。 Node只是一个JavaScript环境。与客户端JavaScript一样您可以使用控制台显示有用的调试信息。在本地计算机上您将在终端中看到控制台输出。在Glitch上您可以打开屏幕下方的日志。您可以使用“日志”按钮切换日志面板左上角在应用名称下。 要开始使用只需在控制台中打印经典的“Hello World”即可。我们建议在应对这些挑战时保持日志面板处于打开状态。阅读日志您可以了解可能发生的错误的性质。
<section id='description'>
在开发过程中能够随时看到代码的运行结果是非常重要的。Node 只是一个 JavaScript 环境。与客户端 JavaScript 一样,你可以使用控制台输出有用的调试信息。在本地计算机上,你可以在终端中输出调试信息。在 Glitch 上,你可以打开屏幕下方的日志。使用 "Logs" 按钮切换日志面板(在左上角,应用名称的下面)。
我们建议在做这些挑战题时,保持日志面板处于打开状态。通过这些错误日志,你可能会发现这些错误的本质原因。
</section>
## Instructions
<section id='instructions'> 修改<code>myApp.js</code>文件以将“Hello World”记录到控制台。
<section id='instructions'>
如果还没准备好,请阅读[介绍](/learn/apis-and-microservices/basic-node-and-express/)里面的指引,在 Glitch 里通过这个[链接](https://glitch.com/edit/#!/remix/clone-from-repo?REPO_URL=https://github.com/freeCodeCamp/boilerplate-express/)创建一个新项目。
修改 <code>myApp.js</code> 文件,在控制台打印出经典的 "Hello World" 即可。
</section>
## Tests
@ -18,7 +26,7 @@ challengeType: 2
```yml
tests:
- text: <code>"Hello World"</code>应该在控制台中
- text: "控制台应该输出:<code>'Hello World'</code>"
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/hello-console'').then(data => { assert.isTrue(data.passed, ''"Hello World" is not in the server console''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -34,7 +42,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,12 +1,14 @@
---
id: 587d7fb0367417b2b2512bef
title: Serve an HTML File
localeTitle: 提供HTML文件
challengeType: 2
forumTopicId: 301516
localeTitle: 服务 HTML 文件
---
## Description
<section id='description'> 我们可以使用<code>res.sendFile(path)</code>方法响应文件。 您可以将它放在<code>app.get('/', ...)</code>路由处理程序中。在幕后此方法将根据其类型设置适当的标头以指示您的浏览器如何处理您要发送的文件。然后它将读取并发送文件。此方法需要绝对文件路径。我们建议您使用Node全局变量<code>__dirname</code>来计算路径。 例如:
<section id='description'>
我们可以使用<code>res.sendFile(path)</code>方法来响应一个文件。你可以把响应一个文件的方法放到路由处理程序中:<code>app.get('/', ...)</code>。在后台,这个方法会根据你想发送的文件的类型,设置适当的 headers 头信息来告诉浏览器如何处理它。然后它会读取并发送文件。此方法需要文件的绝对路径。我们建议你使用 Node.js 的全局变量<code>__dirname</code>来计算出这个文件的绝对路径。
```js
absolutePath = __dirname + relativePath/file.ext
@ -16,9 +18,9 @@ absolutePath = __dirname + relativePath/file.ext
## Instructions
<section id='instructions'>
要发送的文件是<code>/views/index.html</code> 。尝试“显示”你的应用程序,你应该看到一个大的HTML标题以及我们稍后将使用的表单......),没有应用任何样式。
要发送的文件是<code>/views/index.html</code>。在 app 中点击 "Show Live" 按钮,你会看到一个大的 HTML 标题(以及我们稍后将使用的表单…),目前它们还没有任何样式。
<strong>注意</strong>可以编辑上一个挑战的解决方案,也可以创建一个新挑战。如果您创建新解决方案,请记住Express会从上到下评估路由。它执行第一个匹配的处理程序。您必须注释掉前面的解决方案,否则服务器将继续使用字符串进行响应
<strong>注意: </strong>可以编辑上一个挑战的解题代码,或者创建一个新挑战。如果你重写了之前的代码,请注意 Express 会从上到下重新解析对应的路由方法。它执行第一个匹配的路由处理方法。你必须注释掉前面的代码,否则服务器还是响应之前的字符串
</section>
## Tests
@ -26,7 +28,7 @@ absolutePath = __dirname + relativePath/file.ext
```yml
tests:
- text: 您的应用应该提供文件views / index.html
- text: app 应该响应 views/index.html 文件
testString: 'getUserInput => $.get(getUserInput(''url'')).then(data => { assert.match(data, /<h1>.*<\/h1>/, ''Your app does not serve the expected HTML''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -42,7 +44,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,17 +1,20 @@
---
id: 587d7fb1367417b2b2512bf1
title: Serve JSON on a Specific Route
localeTitle: 在特定路线上提供JSON
challengeType: 2
forumTopicId: 301517
localeTitle: 服务指定路由上的 JSON
---
## Description
<section id='description'> 虽然HTML服务器提供您猜对了HTML但API提供数据。 <dfn>REST</dfn> REpresentational State TransferAPI允许以简单的方式进行数据交换而无需客户端知道有关服务器的任何细节。客户端只需要知道资源的位置URL以及它想要对其执行的操作动词。当您获取某些信息而不修改任何信息时将使用GET动词。目前用于在Web上移动信息的首选数据格式是JSON。简单地说JSON是一种将JavaScript对象表示为字符串的便捷方式因此可以轻松传输。 让我们通过在路径<code>/json</code>处创建一个以JSON响应的路由来创建一个简单的API。您可以像往常一样使用<code>app.get()</code>方法执行此操作。在路由处理程序内部使用方法<code>res.json()</code> ,将对象作为参数传入。此方法关闭请求 - 响应循环返回数据。在幕后它将有效的JavaScript对象转换为字符串然后设置相应的标题以告诉您的浏览器您正在提供JSON并将数据发回。有效对象具有通常的结构<code>{key: data}</code> 。数据可以是数字,字符串,嵌套对象或数组。数据也可以是变量或函数调用的结果,在这种情况下,它将在转换为字符串之前进行评估。
<section id='description'>
HTML 服务器提供 HTMLAPI 服务器提供数据。<dfn>REST</dfn>表现层状态转换API 允许使用更简易的方式交换数据,从而不需要客户端知道服务器的实现细节。客户端只要知道需请求资源对应的 URL 是什么,以及需要对这个 URL 进行何种操作就够了。比如 GET 这个动作,就是从服务器上获取某些信息,它不会修改任何数据。如今,在 web 上传输数据的首选数据格式是 JSON。简言之JSON 是一种将 JavaScript 对象表示为字符串的简易方式,因此可以很容易地传输这些数据。
我们来创建一个简单的 API一个路径为<code>/json</code>且返回数据是 JSON 格式的路由,你可以像之前那样通过<code>app.get()</code>方法来做,然后在路由处理部分使用<code>res.json()</code>方法返回 JSON 格式的数据这个方法可以接收一个配置对象。这个方法会结束请求响应循环request-response loop然后返回数据。<code>res.json()</code>将一个有效的 JavaScript 对象转化为字符串然后会设置适当的头信息headers来告诉浏览器这是一个 JSON 数据,最后返回给客户端进行处理。一个有效的对象通常是这种结构:<code>{key: data}</code>。数据可以是数字、字符串、嵌套对象或数组。也可以是变量或者函数返回值,在这种情况下,会以它们的执行结果为基准,再转成字符串。
</section>
## Instructions
<section id='instructions'>
将对象<code>{"message": "Hello json"}</code>作为JSON格式的响应提供给对路由<code>/json</code>的GET请求。然后浏览器指向 <code>your-app-url/json</code>您应该在屏幕上看到消息。
当 GET 请求路由<code>/json</code>时,将对象<code>{"message": "Hello json"}</code>作为 JSON 格式返回给客户端。然后浏览器里输入完整的 URL比如<code>your-app-url/json</code>就可以在屏幕上看到这个消息
</section>
## Tests
@ -19,7 +22,7 @@ challengeType: 2
```yml
tests:
- text: 'endpoint <code>/json</code>应该服务于json对象<code>{"message": "Hello json"}</code> '
- text: '服务端<code>/json</code>应该返回一个 JSON 对象<code>{"message": "Hello json"}</code>'
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/json'').then(data => { assert.equal(data.message, ''Hello json'', ''The \''/json\'' endpoint does not serve the right data''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -35,7 +38,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,20 @@
---
id: 587d7fb0367417b2b2512bf0
title: Serve Static Assets
localeTitle: 服务静态资产
challengeType: 2
forumTopicId: 301518
localeTitle: 服务静态资源
---
## Description
<section id='description'>
HTML服务器通常有一个或多个用户可以访问的目录。可以放置应用程序所需的静态资产(样式表脚本,图像)。在Express中,您可以使用中间件<code>express.static(path)</code>实现此功能,其中参数是包含资产的文件的绝对路径。如果不知道中间件是什么,请不要担心。我们稍后详细讨论它。基本上,中间件是拦截路由处理程序,添加某种信息的函数。需要使用<code>app.use(path, middlewareFunction)</code>方法<code>app.use(path, middlewareFunction)</code>第一个路径参数是可选的如果您没有通过它,将为所有请求执行中间件。
HTML 服务器通常有一个或多个用户可以访问的目录。可以应用程序所需的静态资源 (样式表脚本、图片) 放在那里。在 Express 中你可以使用中间件<code>express.static(path)</code>设置此功能,它的参数就是静态资源文件的绝对路径。如果不知道什么是中间件,也不用担心。我们稍后详细讨论此事。一个最基本的中间件可以看做是一个函数,它拦截路由处理方法,并在里面添加了一点别的信息。使用<code>app.use(path, middlewareFunction)</code>方法来加载一个中间件。它的第一个参数是可选的如果没设置第一个参数,那么应用的所有请求都会经过这个中间件处理。
</section>
## Instructions
<section id='instructions'>
使用<code>app.use()</code>为所有请求安装<code>express.static()</code>中间件。 assets文件夹的绝对路径是<code>__dirname + /public</code> 。 现在您的应用应该能够提供CSS样式表。从公共文件夹外部将显示挂载到根目录。你的头版现在应该看起来好一点!
使用<code>app.use()</code>来加载<code>express.static()</code>中间件,让所有的请求都能访问我们的静态资源目录。静态资源的绝对路径是<code>__dirname + /public</code>
现在 app 就能正常返回一个样式文件了,访问 app 根路径时,静态资源目录的文件就会被加载进来,现在你的首页看起来应该好些了!
</section>
## Tests
@ -20,7 +22,7 @@ HTML服务器通常有一个或多个用户可以访问的目录。您可以放
```yml
tests:
- text: 您的应用应该从<code>/public</code>目录提供资产文件
- text: 应用的静态资源文件应该来自<code>/public</code>目录
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/style.css'').then(data => { assert.match(data, /body\s*\{[^\}]*\}/, ''Your app does not serve static assets''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -36,7 +38,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,30 @@
---
id: 587d7fb0367417b2b2512bee
title: Start a Working Express Server
localeTitle: 启动Working Express服务器
challengeType: 2
forumTopicId: 301519
localeTitle: 启动一个 Express 服务器
---
## Description
<section id='description'> 在myApp.js文件的前两行中您可以看到如何轻松创建Express应用程序对象。这个对象有几种方法我们将在这些挑战中学到很多方法。一个基本方法是<code>app.listen(port)</code> 。它告诉您的服务器侦听给定端口,使其处于运行状态。您可以在文件底部看到它。这是内部评论,因为出于测试原因,我们需要应用程序在后台运行。您可能想要添加的所有代码都介于这两个基本部分之间。 Glitch将端口号存储在环境变量<code>process.env.PORT</code> 。它的价值是<code>3000</code> 。 让我们的第一个字符串在Express中路由采用以下结构 <code>app.METHOD(PATH, HANDLER)</code> 。 METHOD是小写的http方法。 PATH是服务器上的相对路径它可以是字符串甚至是正则表达式。 HANDLER是Express匹配路由时调用的功能。 处理程序采用表单<code>function(req, res) {...}</code> 其中req是请求对象res是响应对象。例如处理程序
<blockquote>function(req, res) {<br> res.send('Response String');<br>}</blockquote> 将提供字符串'Response String'。
<section id='description'>
在 myApp.js 文件的前两行中,你可以看到创建一个 Express 应用对象是很简单的。这个 Express 对象有几个方法,在这些挑战中,我们将会学习它们更多的方法。一个基础的方法是<code>app.listen(port)</code>。它告诉服务器监听指定的端口并且让这个服务处于运行状态。你可以在文件的底部看到它们。它在注释里面因为出于测试原因我们需要知道这个应用正在后台运行。你想要添加的所有代码都放在这两部分之间。Glitch 将端口号存储在环境变量<code>process.env.PORT</code>中。它的值是<code>3000</code>
让我们在服务端输出第一个字符串!在 Express 中,路由采用这种结构:<code>app.METHOD(PATH, HANDLER)</code><code>METHOD</code>是小写的 http 方法。<code>PATH</code>是服务器上的相对路径(它是一个字符串,甚至是正则表达式)<code>HANDLER</code>是 Express 匹配路由时调用的处理函数。
处理函数采用这种形式:<code>function(req, res) {...}</code>,在这个处理函数的参数中<code>req</code>是请求对象。<code>res</code>是响应对象。举个例子,处理函数:
```js
function(req, res) {
res.send('Response String');
}
```
将会响应一个字符串 'Response String'。
</section>
## Instructions
<section id='instructions'>
使用<code>app.get()</code>方法为字符串Hello Express提供服务,以匹配/ root路径的GET请求。通过查看日志确保您的代码正常工作然后在浏览器中查看结果单击Glitch UI中的“Show Live”按钮。
当 GET 请求根路由( "/" )时,使用<code>app.get()</code>方法端响应一个 "Hello Express" 字符串。
<strong>注意:</strong> 在 Glitch 中点击 "Show Live" 按钮,通过查看日志确保你的代码正常运行,然后在浏览器中查看结果。
</section>
## Tests
@ -20,7 +32,7 @@ challengeType: 2
```yml
tests:
- text: 您的应用应该提供字符串'Hello Express'
- text: 'app 应该输出 "Hello Express" 字符串'
testString: 'getUserInput => $.get(getUserInput(''url'')).then(data => { assert.equal(data, ''Hello Express'', ''Your app does not serve the text "Hello Express"''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -36,7 +48,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,19 +1,33 @@
---
id: 587d7fb2367417b2b2512bf7
title: Use body-parser to Parse POST Requests
localeTitle: 使用body-parser来解析POST请求
challengeType: 2
forumTopicId: 301520
localeTitle: 使用 body-parser 来解析POST请求
---
## Description
<section id='description'> 除了GET之外还有另一个常见的http动词它是POST。 POST是用于使用HTML表单发送客户端数据的默认方法。在REST约定中POST用于发送数据以在数据库中创建新项目新用户或新博客文章。我们在这个项目中没有数据库但我们将学习如何处理POST请求。 在这些请求中数据不会出现在URL中它隐藏在请求正文中。这是HTML请求的一部分也称为有效负载。由于HTML是基于文本的即使您没有看到数据也不意味着它们是秘密的。 HTTP POST请求的原始内容如下所示
<blockquote>POST /path/subpath HTTP/1.0<br>From: john@example.com<br>User-Agent: someBrowser/1.0<br>Content-Type: application/x-www-form-urlencoded<br>Content-Length: 20<br>name=John+Doe&age=25</blockquote> 正如您所见,正文被编码为查询字符串。这是HTML表单使用的默认格式。使用Ajax我们还可以使用JSON来处理具有更复杂结构的数据。还有另一种编码类型multipart / form-data。这个用于上传二进制文件。 在本练习中我们将使用urlencoded主体。 要解析来自POST请求的数据您必须安装一个包body-parser。该软件包允许您使用一系列中间件这些中间件可以解码不同格式的数据。请参阅<a href="https://github.com/expressjs/body-parser" target="_blank" >此处</a>的文档。
<section id='description'>
除了 GET 还有另一个常见的 http 动词,它是 POST。POST 是使用 HTML 表单发送客户端数据的默认方法。在 REST 规范中POST 常用于发送数据,以便在数据库中创建新项目(新用户或新博客文章)。我们在这个项目中没有使用数据库,我们将学习如何处理 POST 请求
在这些类型的请求中,数据不会出现在 URL 中,而是隐藏在请求正文中。这也是 HTML 请求的一部分,被称为负载。因为 HTML 是基于文本的你看不到数据这并不意味着它们是加密的。HTTP POST 请求的原始内容如下所示:
```http
POST /path/subpath HTTP/1.0
From: john@example.com
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。它用来上传二进制文件。
在本练习中,我们将使用网址编码 body。要解析来自 POST 请求的数据你必须安装一个包body-parser。这个包允许你使用一套可以解码不同格式数据的中间件<a href="https://github.com/expressjs/body-parser" target="_blank" >这里</a>查看文档。
</section>
## Instructions
<section id='instructions'>
在package.json中安装body-parser模块然后在文件顶部需要它。将其存储在名为bodyParser的变量中。
<code>bodyParser.urlencoded({extended: false})</code>返回处理url编码数据的中间件。<strong>注意:</strong><code>extended=false</code>是一个配置选项,告诉解析器使用经典编码。使用它时,值可以只是字符串或数组。扩展版本允许更多的数据灵活性但它被JSON击败。将<code>app.use()</code>传递给前一个方法调用返回的函数。像往常一样,必须在需要它的所有路由之前安装中间件
package.json 中安装 body-parser 模块然后在文件顶部 require 进来,用变量 bodyParser 保存它。
处理 URL 编码数据通过中间件的<code>bodyParser.urlencoded({extended: false})</code>方法。<code>extended=false</code>是一个配置选项,告诉解析器使用经典编码。当你使用它时,值只是字符串或数组。继承版使用起来数据更加灵活,它比 JSON 更好。传递给<code>app.use()</code>上一次方法调用返回的函数。通常中间件必须挂载在所有需要它的路由之前。
</section>
## Tests
@ -21,7 +35,7 @@ challengeType: 2
```yml
tests:
- text: 应该安装'body-parser'中间件
- text: '"body-parser" 中间件应该被挂载'
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/add-body-parser'').then(data => { assert.isAbove(data.mountedAt, 0, ''"body-parser" is not mounted correctly'') }, xhr => { throw new Error(xhr.responseText); })'
```
@ -37,7 +51,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>

View File

@ -1,18 +1,21 @@
---
id: 587d7fb1367417b2b2512bf2
title: Use the .env File
localeTitle: 使用.env文件
challengeType: 2
forumTopicId: 301521
localeTitle: 使用 .env 文件
---
## Description
<section id='description'>
<code>.env</code>文件是一个隐藏文件,用于将环境变量传给应用程序。这个文件是秘密的,没有人可以访问它,它可以用来存储你想保密或隐藏的数据。例如,您可以存储来自外部服务或数据库URI的API密钥。您还可以使用它来存储配置选项。通过设置配置选项,可以改应用程序的行为,而无需重写些代码。 可以从应用程序访问环境变量<code>process.env.VAR_NAME</code><code>process.env</code>对象是一个全局Node对象变量作为字符串传递。按照惯例变量名都是大写的单词用下划线分隔。 <code>.env</code>是一个shell文件因此您不需要在引号中包装名称或值。同样重要的是要注意当您为变量赋值时等号周围不能有空格例如<code>VAR_NAME=value</code> 。通常,您将每个变量定义放在单独的行上。
<code>.env</code>文件是一个隐藏文件,用于将环境变量传给应用程序。这是一个私密文件,除了你之外没人可以访问它,它可以用来存储你想保持私有或者隐藏的数据。举个例子,可以存储第三方服务 API 密钥或者数据库 URI。你也可以使用它来存储配置选项。通过设置配置选项,可以改应用程序的行为,而无需重写些代码。
在应用程序中可以通过<code>process.env.VAR_NAME</code>访问到环境变量。<code>process.env</code>是 Node 程序中的一个全局对象,可以给这个变量传字符串。按照惯例,变量名都是大写的,单词之间用下划线隔开。<code>.env</code>是一个 shell 文件,因此不需要用给变量名和值加引号。还有一点需要注意,当你给变量赋值时,等号周围不能有空格,举个例子:<code>VAR_NAME=value</code>。通常来讲,每一个变量会单独定义在新的一行。
</section>
## Instructions
<section id='instructions'>
让我们添加一个环境变量作为配置选项。将变量<code>MESSAGE_STYLE=uppercase</code>存储在<code>.env</code>文件中。然后告诉您在上一次质询中创建的GET <code>/json</code>路由处理程序,如果<code>process.env.MESSAGE_STYLE</code>等于<code>uppercase</code>则将响应对象的消息转换为<code>uppercase</code> 。响应对象应该成为<code>{"message": "HELLO JSON"}</code>
让我们添加一个环境变量作为配置选项。
<code>.env</code>文件中保存变量<code>MESSAGE_STYLE=uppercase</code>。它的作用是,告诉上一次挑战中的路由处理程序,当我们 GET 方法请求 /JSON 时,如果<code>process.env.MESSAGE_STYLE</code>的值为<code>uppercase</code>,那么返回的对象则应该是<code>{"message": "HELLO JSON"}</code>.
</section>
## Tests
@ -20,7 +23,7 @@ challengeType: 2
```yml
tests:
- text: 端点<code>/json</code>的响应应根据环境变量<code>MESSAGE_STYLE</code>
- text: 客户端响应<code>/json</code>的值,应该随着环境变量<code>MESSAGE_STYLE</code>的变化而改变
testString: 'getUserInput => $.get(getUserInput(''url'') + ''/_api/use-env-vars'').then(data => { assert.isTrue(data.passed, ''The response of "/json" does not change according to MESSAGE_STYLE''); }, xhr => { throw new Error(xhr.responseText); })'
```
@ -36,7 +39,11 @@ tests:
<section id='solution'>
```js
// solution required
/**
Backend challenges don't need solutions,
because they would need to be tested against a full working project.
Please check our contributing guidelines to learn more.
*/
```
/section>
</section>