feat - Initial translated into Bahasa Indonesia (#1535)

* feat(lang-id): create language directory and copy documentation files

* feat(docs): translate index.md, api.md, and starter/* to bahasa indonesia

* feat(docs): translate _includes/* to bahasa indonesia

* feat(docs): update  and the  for bahasa indonesia

* fix(workflows): add id to languages variable

* fix(docs): change string into singlequote in starter/faq.md

* fix(docs): remove {{page.lang}} in id/3x and id/4x

* fix(docs): remove {{page.lang}} in id/api.md

* feat(docs): add indonesian in footer-en
This commit is contained in:
Septian Maulana
2024-07-13 05:46:20 +07:00
committed by GitHub
parent d0b4e67b89
commit 0eff3bf285
57 changed files with 8142 additions and 2 deletions

View File

@@ -9,6 +9,7 @@ on:
- 'es/**'
- 'fr/**'
- 'it/**'
- 'id/**'
- 'ja/**'
- 'ko/**'
- 'pt-br/**'
@@ -37,7 +38,7 @@ jobs:
uses: actions/github-script@v5
with:
script: |
const languages = ['en', 'es', 'fr', 'it', 'ja', 'ko', 'pt-br', 'ru', 'sk', 'th', 'tr', 'uk', 'uz', 'zh-cn', 'zh-tw'];
const languages = ['en', 'es', 'fr', 'it', 'id', 'ja', 'ko', 'pt-br', 'ru', 'sk', 'th', 'tr', 'uk', 'uz', 'zh-cn', 'zh-tw'];
const prNumber = context.eventName === 'workflow_dispatch' ? context.payload.inputs.prNumber : context.issue.number;
const { data: pullRequest } = await github.rest.pulls.get({
owner: context.repo.owner,

View File

@@ -16,6 +16,7 @@ The documentation is translated into these languages:
- Spanish (`es`)
- French (`fr`)
- Italian (`it`)
- Indonesian (`id`)
- Japanese (`ja`)
- Korean (`ko`)
- Brazilian Portuguese (`pt-br`)

View File

@@ -0,0 +1,8 @@
<ul>
<li>
<p class="announcement-title">Dokumentasi Express 5.0 versi beta kini telah tersedia.</p>
<p markdown="1">
<a href="{{ page.lang }}/5x/api.html">Dokumentasi API</a> beta masih dalam proses. Untuk informasi tentang apa yang ada dalam rilis, lihat <a href="https://github.com/expressjs/express/blob/5.0/History.md">riwayat rilis</a> Express.
</p>
</li>
</ul>

View File

@@ -5,7 +5,7 @@
Documentation translations provided by StrongLoop/IBM:
<a href="/fr/">French</a>, <a href="/de/">German</a>, <a href="/es/">Spanish</a>, <a href="/it/">Italian</a>, <a href="/ja/">Japanese</a>, <a href="/ru/">Russian</a>, <a href="/zh-cn/">Chinese</a>, <a href="/zh-tw/">Traditional Chinese</a>, <a href="/ko/">Korean</a>, <a href="/pt-br/">Portuguese</a>.
<br>
Community translation available for: <a href="/sk/">Slovak</a>, <a href="/uk/">Ukrainian</a>, <a href="/uz/">Uzbek</a>, <a href="/tr/">Turkish</a> and <a href="/th/">Thai</a>.
Community translation available for: <a href="/sk/">Slovak</a>, <a href="/uk/">Ukrainian</a>, <a href="/uz/">Uzbek</a>, <a href="/tr/">Turkish</a>, <a href="/th/">Thai</a> and <a href="/id/">Indonesian</a>.
</section>
<div id="footer-content">
<div>

30
_includes/footer/footer-id.html Executable file
View File

@@ -0,0 +1,30 @@
<a id="top" href="#"><img src="/images/arrow.png"></a>
<footer>
<section id="doc-langs">
Dokumentasi versi terjemahan yang disediakan oleh StrongLoop/IBM:
<a href="/fr/">French</a>, <a href="/de/">German</a>, <a href="/es/">Spanish</a>, <a href="/it/">Italian</a>, <a href="/ja/">Japanese</a>, <a href="/ru/">Russian</a>, <a href="/zh-cn/">Chinese</a>, <a href="/zh-tw/">Traditional Chinese</a>, <a href="/ko/">Korean</a>, <a href="/pt-br/">Portuguese</a>.
<br>
Terjemahan oleh komunitas tersedia untuk: <a href="/sk/">Slovak</a>, <a href="/uk/">Ukrainian</a>, <a href="/uz/">Uzbek</a>, <a href="/tr/">Turkish</a>, <a href="/th/">Thai</a> dan <a href="/id/">Bahasa Indonesia</a>.
</section>
<div id="footer-content">
<div>
<a href="https://www.netlify.com">
<img src="https://www.netlify.com/v3/img/components/netlify-color-accent.svg" alt="Preview Deploys by Netlify" style="width: 50px;" />
</a>
</div>
<div id="github">
<a class="github-button" href="https://github.com/expressjs/expressjs.com" data-icon="octicon-star" aria-label="Star expressjs/expressjs.com on GitHub">Star</a>
</div>
<div id="sponsor"><a href="https://expressjs.com">Express</a> adalah proyek dari <a href="https://openjsf.org">OpenJS Foundation</a>.</div>
<div id="fork"><a href="https://github.com/expressjs/expressjs.com">Fork situs web di GitHub</a>.</div>
<div>Copyright &copy; 2017 StrongLoop, IBM, and other expressjs.com contributors.</div>
</div>
<div id="license">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/3.0/us/80x15.png" /></a> Karya ini dilisensikan di bawah <a rel="license" href="http://creativecommons.org/licenses/by-sa/3.0/us/">Lisensi Creative Commons Attribution-ShareAlike 3.0 Amerika Serikat</a>.
</div>
</footer>
<script async defer src="https://buttons.github.io/buttons.js"></script>
{% include footer/_docsearch.html %}

View File

@@ -0,0 +1,161 @@
<header>
<div id="mobile-menu">
<div id="nav-button" class="fa fa-bars fa-2x button"></div>
</div>
<section id="logo"><a href="/" class="express">Express</a>
</section>
<div id="navbar">
<input id="q" placeholder="🔎 search">
<ul id="navmenu">
<li><a href="/" id="home-menu"{% if page.menu == 'home' %} class="active"{% endif %}>Home</a></li>
<li>
<ul id="getting-started-menu" class="menu">
<li><a href="/{{ page.lang }}/starter/installing.html"{% if page.menu == 'starter' %} class="active"{% endif %}>Mulai</a>
<ul>
<li>
<a href="/{{ page.lang }}/starter/installing.html">
Menginstal
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/hello-world.html">
Hello world
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/generator.html">
Generator Express
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/basic-routing.html">
Dasar routing
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/static-files.html">
File statis
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/examples.html">
Contoh lainnya
</a>
</li>
<li>
<a href="/{{ page.lang }}/starter/faq.html">
FAQ
</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
<ul id="guide-menu" class="menu">
<li><a href="/{{ page.lang }}/guide/routing.html"{% if page.menu == 'guide' %} class="active"{% endif %}>Panduan</a>
<ul>
<li><a href="/{{ page.lang }}/guide/routing.html">Routing</a>
</li>
<li><a href="/{{ page.lang }}/guide/writing-middleware.html">Membuat middleware</a>
</li>
<li><a href="/{{ page.lang }}/guide/using-middleware.html">Menggunakan middleware</a>
</li>
<li><a href="/{{ page.lang }}/guide/overriding-express-api.html">Mengganti Express API</a>
</li>
<li><a href="/{{ page.lang }}/guide/using-template-engines.html">Menggunakan template engines</a>
</li>
<li><a href="/{{ page.lang }}/guide/error-handling.html">Penanganan Error</a>
</li>
<li><a href="/{{ page.lang }}/guide/debugging.html">Debugging</a>
</li>
<li><a href="/{{ page.lang }}/guide/behind-proxies.html">Express behind proxies</a>
</li>
<li><a href="/{{ page.lang }}/guide/migrating-4.html">Pindah to Express 4</a>
</li>
<li><a href="/{{ page.lang }}/guide/migrating-5.html">Pindah to Express 5</a>
</li>
<li><a href="/{{ page.lang }}/guide/database-integration.html">Integrasi Database</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
<ul id="application-menu" class="menu">
<li><a href="/{{ page.lang }}/4x/api.html"{% if page.menu == 'api' %} class="active"{% endif %}>Referensi API</a>
<ul>
<li><a href="/{{ page.lang }}/5x/api.html">5.x (beta)</a>
</li>
<li><a href="/{{ page.lang }}/4x/api.html">4.x</a>
</li>
<li><a href="/{{ page.lang }}/3x/api.html">3.x (deprecated)</a>
</li>
<li><a href="/2x/">2.x (deprecated)</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
<ul id="advanced-topics-menu" class="menu">
<li><a href="/{{ page.lang }}/advanced/developing-template-engines.html"{% if page.menu == 'advanced' %} class="active"{% endif %}>Topik lanjutan</a>
<ul>
<li><a href="/{{ page.lang }}/advanced/developing-template-engines.html">Membangun template engines</a>
</li>
<li><a href="/{{ page.lang }}/advanced/security-updates.html">Security updates</a>
</li>
<li><a href="/{{ page.lang }}/advanced/best-practice-security.html">Security best practices</a>
</li>
<li><a href="/{{ page.lang }}/advanced/best-practice-performance.html">Performance best practices</a>
</li>
<li><a href="/{{ page.lang }}/advanced/healthcheck-graceful-shutdown.html">Health checks & shutdown</a>
</li>
</ul>
</li>
</ul>
</li>
<li>
<ul id="resources-menu" class="menu">
<li><a href="/{{ page.lang }}/resources/glossary.html"{% if page.menu == 'resources' %} class="active"{% endif %}>Resources</a>
<ul>
<li>
<a href="/{{ page.lang }}/resources/community.html">Community</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/glossary.html">Glossary</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/middleware.html">Middleware</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/utils.html">Utility modules</a>
</li>
<li>
<a href="/{{ page.lang }}/resources/contributing.html">Contributing to Express</a>
</li>
<li>
<a href="/{{ page.lang }}/changelog/4x.html">Release Change Log</a>
</li>
</ul>
</li>
</ul>
</li>
<!--
<li>
<ul id="changelog-menu" class="menu">
<li><a href="/{{ page.lang }}/changelog/4x.html"{% if page.menu == 'changelog' %} class="active"{% endif %}>Changelog</a>
<ul>
<li><a href="/{{ page.lang }}/changelog/4x.html">4.x</a></li>
</ul>
</li>
</ul>
</li>
-->
</ul>
<div id="theme-icon-container" class="theme-toggle default-theme" title="toggle darkmode">
<i class="fa fa-moon-o fa-2x"></i>
</div>
</div>
</header>

View File

@@ -0,0 +1 @@
Dokumen ini mungkin sudah ketinggalan zaman jika dibandingkan dengan dokumentasi dalam bahasa Inggris. Untuk informasi terkini, lihat <a href="/">dokumentasi dalam bahasa Inggris</a>.

23
id/3x/api.md Normal file
View File

@@ -0,0 +1,23 @@
---
layout: 3x-api
title: Express 3.x - Referensi API
menu: api
lang: id
---
<div id="api-doc" markdown="1">
<div class="doc-box doc-warn" markdown="1">
**Express 3.x TIDAK ADA LAGI PEMELIHARAAN**
Masalah keamanan dan kinerja yang diketahui dan tidak diketahui di versi 3.x belum diatasi sejak pembaruan terakhir (1 Agustus 2015). Sangat disarankan untuk menggunakan Express versi terbaru.
</div>
<h1>3.x API</h1>
{% include api/en/3x/express.md %}
{% include api/en/3x/app.md %}
{% include api/en/3x/req.md %}
{% include api/en/3x/res.md %}
{% include api/en/3x/middleware.md %}
</div>

19
id/4x/api.md Normal file
View File

@@ -0,0 +1,19 @@
---
layout: 4x-api
title: Express 4.x - Referensi API
menu: api
lang: id
---
<div id="api-doc" markdown="1">
<h1>4.x API</h1>
{% include note.html content="Express 4.0 requires Node.js 0.10 or higher." %}
{% include api/en/4x/express.md %}
{% include api/en/4x/app.md %}
{% include api/en/4x/req.md %}
{% include api/en/4x/res.md %}
{% include api/en/4x/router.md %}
</div>

View File

@@ -0,0 +1,453 @@
---
layout: page
title: Performance Best Practices Using Express in Production
menu: advanced
lang: id
---
# Production best practices: performance and reliability
## Overview
This article discusses performance and reliability best practices for Express applications deployed to production.
This topic clearly falls into the "devops" world, spanning both traditional development and operations. Accordingly, the information is divided into two parts:
* Things to do in your code (the dev part):
* [Use gzip compression](#use-gzip-compression)
* [Don't use synchronous functions](#dont-use-synchronous-functions)
* [Do logging correctly](#do-logging-correctly)
* [Handle exceptions properly](#handle-exceptions-properly)
* Things to do in your environment / setup (the ops part):
* [Set NODE_ENV to "production"](#set-node_env-to-production)
* [Ensure your app automatically restarts](#ensure-your-app-automatically-restarts)
* [Run your app in a cluster](#run-your-app-in-a-cluster)
* [Cache request results](#cache-request-results)
* [Use a load balancer](#use-a-load-balancer)
* [Use a reverse proxy](#use-a-reverse-proxy)
## Things to do in your code {#in-code}
Here are some things you can do in your code to improve your application's performance:
* [Use gzip compression](#use-gzip-compression)
* [Don't use synchronous functions](#dont-use-synchronous-functions)
* [Do logging correctly](#do-logging-correctly)
* [Handle exceptions properly](#handle-exceptions-properly)
### Use gzip compression
Gzip compressing can greatly decrease the size of the response body and hence increase the speed of a web app. Use the [compression](https://www.npmjs.com/package/compression) middleware for gzip compression in your Express app. For example:
```js
const compression = require('compression')
const express = require('express')
const app = express()
app.use(compression())
```
For a high-traffic website in production, the best way to put compression in place is to implement it at a reverse proxy level (see [Use a reverse proxy](#use-a-reverse-proxy)). In that case, you do not need to use compression middleware. For details on enabling gzip compression in Nginx, see [Module ngx_http_gzip_module](http://nginx.org/en/docs/http/ngx_http_gzip_module.html) in the Nginx documentation.
### Don't use synchronous functions
Synchronous functions and methods tie up the executing process until they return. A single call to a synchronous function might return in a few microseconds or milliseconds, however in high-traffic websites, these calls add up and reduce the performance of the app. Avoid their use in production.
Although Node and many modules provide synchronous and asynchronous versions of their functions, always use the asynchronous version in production. The only time when a synchronous function can be justified is upon initial startup.
If you are using Node.js 4.0+ or io.js 2.1.0+, you can use the `--trace-sync-io` command-line flag to print a warning and a stack trace whenever your application uses a synchronous API. Of course, you wouldn't want to use this in production, but rather to ensure that your code is ready for production. See the [node command-line options documentation](https://nodejs.org/api/cli.html#cli_trace_sync_io) for more information.
### Do logging correctly
In general, there are two reasons for logging from your app: For debugging and for logging app activity (essentially, everything else). Using `console.log()` or `console.error()` to print log messages to the terminal is common practice in development. But [these functions are synchronous](https://nodejs.org/api/console.html#console_console_1) when the destination is a terminal or a file, so they are not suitable for production, unless you pipe the output to another program.
#### For debugging
If you're logging for purposes of debugging, then instead of using `console.log()`, use a special debugging module like [debug](https://www.npmjs.com/package/debug). This module enables you to use the DEBUG environment variable to control what debug messages are sent to `console.error()`, if any. To keep your app purely asynchronous, you'd still want to pipe `console.error()` to another program. But then, you're not really going to debug in production, are you?
#### For app activity
If you're logging app activity (for example, tracking traffic or API calls), instead of using `console.log()`, use a logging library like [Winston](https://www.npmjs.com/package/winston) or [Bunyan](https://www.npmjs.com/package/bunyan). For a detailed comparison of these two libraries, see the StrongLoop blog post [Comparing Winston and Bunyan Node.js Logging](https://strongloop.com/strongblog/compare-node-js-logging-winston-bunyan/).
### Handle exceptions properly
Node apps crash when they encounter an uncaught exception. Not handling exceptions and taking appropriate actions will make your Express app crash and go offline. If you follow the advice in [Ensure your app automatically restarts](#ensure-your-app-automatically-restarts) below, then your app will recover from a crash. Fortunately, Express apps typically have a short startup time. Nevertheless, you want to avoid crashing in the first place, and to do that, you need to handle exceptions properly.
To ensure you handle all exceptions, use the following techniques:
* [Use try-catch](#use-try-catch)
* [Use promises](#use-promises)
Before diving into these topics, you should have a basic understanding of Node/Express error handling: using error-first callbacks, and propagating errors in middleware. Node uses an "error-first callback" convention for returning errors from asynchronous functions, where the first parameter to the callback function is the error object, followed by result data in succeeding parameters. To indicate no error, pass null as the first parameter. The callback function must correspondingly follow the error-first callback convention to meaningfully handle the error. And in Express, the best practice is to use the next() function to propagate errors through the middleware chain.
For more on the fundamentals of error handling, see:
* [Error Handling in Node.js](https://www.tritondatacenter.com/node-js/production/design/errors)
* [Building Robust Node Applications: Error Handling](https://strongloop.com/strongblog/robust-node-applications-error-handling/) (StrongLoop blog)
#### What not to do
One thing you should _not_ do is to listen for the `uncaughtException` event, emitted when an exception bubbles all the way back to the event loop. Adding an event listener for `uncaughtException` will change the default behavior of the process that is encountering an exception; the process will continue to run despite the exception. This might sound like a good way of preventing your app from crashing, but continuing to run the app after an uncaught exception is a dangerous practice and is not recommended, because the state of the process becomes unreliable and unpredictable.
Additionally, using `uncaughtException` is officially recognized as [crude](https://nodejs.org/api/process.html#process_event_uncaughtexception). So listening for `uncaughtException` is just a bad idea. This is why we recommend things like multiple processes and supervisors: crashing and restarting is often the most reliable way to recover from an error.
We also don't recommend using [domains](https://nodejs.org/api/domain.html). It generally doesn't solve the problem and is a deprecated module.
#### Use try-catch
Try-catch is a JavaScript language construct that you can use to catch exceptions in synchronous code. Use try-catch, for example, to handle JSON parsing errors as shown below.
Use a tool such as [JSHint](http://jshint.com/) or [JSLint](http://www.jslint.com/) to help you find implicit exceptions like [reference errors on undefined variables](http://www.jshint.com/docs/options/#undef).
Here is an example of using try-catch to handle a potential process-crashing exception.
This middleware function accepts a query field parameter named "params" that is a JSON object.
```js
app.get('/search', (req, res) => {
// Simulating async operation
setImmediate(() => {
const jsonStr = req.query.params
try {
const jsonObj = JSON.parse(jsonStr)
res.send('Success')
} catch (e) {
res.status(400).send('Invalid JSON string')
}
})
})
```
However, try-catch works only for synchronous code. Because the Node platform is primarily asynchronous (particularly in a production environment), try-catch won't catch a lot of exceptions.
#### Use promises
Promises will handle any exceptions (both explicit and implicit) in asynchronous code blocks that use `then()`. Just add `.catch(next)` to the end of promise chains. For example:
```js
app.get('/', (req, res, next) => {
// do some sync stuff
queryDb()
.then((data) => makeCsv(data)) // handle data
.then((csv) => { /* handle csv */ })
.catch(next)
})
app.use((err, req, res, next) => {
// handle error
})
```
Now, all errors asynchronous and synchronous get propagated to the error middleware.
However, there are two caveats:
1. All your asynchronous code must return promises (except emitters). If a particular library does not return promises, convert the base object by using a helper function like [Bluebird.promisifyAll()](http://bluebirdjs.com/docs/api/promise.promisifyall.html).
2. Event emitters (like `streams`) can still cause uncaught exceptions. So make sure you are handling the error event properly; for example:
```js
const wrap = fn => (...args) => fn(...args).catch(args[2])
app.get('/', wrap(async (req, res, next) => {
const company = await getCompanyById(req.query.id)
const stream = getLogoStreamById(company.id)
stream.on('error', next).pipe(res)
}))
```
The `wrap()` function is a wrapper that catches rejected promises and calls `next()` with the error as the first argument.
For details, see [Asynchronous
Error Handling in Express with Promises, Generators and ES7](https://strongloop.com/strongblog/async-error-handling-expressjs-es7-promises-generators/#cleaner-code-with-generators).
For more information about error-handling by using promises, see [Promises in Node.js with Q An Alternative to Callbacks](https://strongloop.com/strongblog/promises-in-node-js-with-q-an-alternative-to-callbacks/).
## Things to do in your environment / setup {#in-environment}
Here are some things you can do in your system environment to improve your app's performance:
* [Set NODE_ENV to "production"](#set-node_env-to-production)
* [Ensure your app automatically restarts](#ensure-your-app-automatically-restarts)
* [Run your app in a cluster](#run-your-app-in-a-cluster)
* [Cache request results](#cache-request-results)
* [Use a load balancer](#use-a-load-balancer)
* [Use a reverse proxy](#use-a-reverse-proxy)
### Set NODE_ENV to "production"
The NODE_ENV environment variable specifies the environment in which an application is running (usually, development or production). One of the simplest things you can do to improve performance is to set NODE_ENV to "production."
Setting NODE_ENV to "production" makes Express:
* Cache view templates.
* Cache CSS files generated from CSS extensions.
* Generate less verbose error messages.
[Tests indicate](http://apmblog.dynatrace.com/2015/07/22/the-drastic-effects-of-omitting-node_env-in-your-express-js-applications/) that just doing this can improve app performance by a factor of three!
If you need to write environment-specific code, you can check the value of NODE_ENV with `process.env.NODE_ENV`. Be aware that checking the value of any environment variable incurs a performance penalty, and so should be done sparingly.
In development, you typically set environment variables in your interactive shell, for example by using `export` or your `.bash_profile` file. But in general, you shouldn't do that on a production server; instead, use your OS's init system (systemd or Upstart). The next section provides more details about using your init system in general, but setting `NODE_ENV` is so important for performance (and easy to do), that it's highlighted here.
With Upstart, use the `env` keyword in your job file. For example:
```sh
# /etc/init/env.conf
env NODE_ENV=production
```
For more information, see the [Upstart Intro, Cookbook and Best Practices](http://upstart.ubuntu.com/cookbook/#environment-variables).
With systemd, use the `Environment` directive in your unit file. For example:
```sh
# /etc/systemd/system/myservice.service
Environment=NODE_ENV=production
```
For more information, see [Using Environment Variables In systemd Units](https://coreos.com/os/docs/latest/using-environment-variables-in-systemd-units.html).
### Ensure your app automatically restarts
In production, you don't want your application to be offline, ever. This means you need to make sure it restarts both if the app crashes and if the server itself crashes. Although you hope that neither of those events occurs, realistically you must account for both eventualities by:
* Using a process manager to restart the app (and Node) when it crashes.
* Using the init system provided by your OS to restart the process manager when the OS crashes. It's also possible to use the init system without a process manager.
Node applications crash if they encounter an uncaught exception. The foremost thing you need to do is to ensure your app is well-tested and handles all exceptions (see [handle exceptions properly](#handle-exceptions-properly) for details). But as a fail-safe, put a mechanism in place to ensure that if and when your app crashes, it will automatically restart.
#### Use a process manager
In development, you started your app simply from the command line with `node server.js` or something similar. But doing this in production is a recipe for disaster. If the app crashes, it will be offline until you restart it. To ensure your app restarts if it crashes, use a process manager. A process manager is a "container" for applications that facilitates deployment, provides high availability, and enables you to manage the application at runtime.
In addition to restarting your app when it crashes, a process manager can enable you to:
* Gain insights into runtime performance and resource consumption.
* Modify settings dynamically to improve performance.
* Control clustering (StrongLoop PM and pm2).
The most popular process managers for Node are as follows:
* [StrongLoop Process Manager](http://strong-pm.io/)
* [PM2](https://github.com/Unitech/pm2)
* [Forever](https://www.npmjs.com/package/forever)
For a feature-by-feature comparison of the three process managers, see [http://strong-pm.io/compare/](http://strong-pm.io/compare/).
Using any of these process managers will suffice to keep your application up, even if it does crash from time to time.
However, StrongLoop PM has lots of features that specifically target production deployment. You can use it and the related StrongLoop tools to:
* Build and package your app locally, then deploy it securely to your production system.
* Automatically restart your app if it crashes for any reason.
* Manage your clusters remotely.
* View CPU profiles and heap snapshots to optimize performance and diagnose memory leaks.
* View performance metrics for your application.
* Easily scale to multiple hosts with integrated control for Nginx load balancer.
As explained below, when you install StrongLoop PM as an operating system service using your init system, it will automatically restart when the system restarts. Thus, it will keep your application processes and clusters alive forever.
#### Use an init system
The next layer of reliability is to ensure that your app restarts when the server restarts. Systems can still go down for a variety of reasons. To ensure that your app restarts if the server crashes, use the init system built into your OS. The two main init systems in use today are [systemd](https://wiki.debian.org/systemd) and [Upstart](http://upstart.ubuntu.com/).
There are two ways to use init systems with your Express app:
* Run your app in a process manager, and install the process manager as a service with the init system. The process manager will restart your app when the app crashes, and the init system will restart the process manager when the OS restarts. This is the recommended approach.
* Run your app (and Node) directly with the init system. This is somewhat simpler, but you don't get the additional advantages of using a process manager.
##### Systemd
Systemd is a Linux system and service manager. Most major Linux distributions have adopted systemd as their default init system.
A systemd service configuration file is called a _unit file_, with a filename ending in `.service`. Here's an example unit file to manage a Node app directly. Replace the values enclosed in `<angle brackets>` for your system and app:
```sh
[Unit]
Description=<Awesome Express App>
[Service]
Type=simple
ExecStart=/usr/local/bin/node </projects/myapp/index.js>
WorkingDirectory=</projects/myapp>
User=nobody
Group=nogroup
# Environment variables:
Environment=NODE_ENV=production
# Allow many incoming connections
LimitNOFILE=infinity
# Allow core dumps for debugging
LimitCORE=infinity
StandardInput=null
StandardOutput=syslog
StandardError=syslog
Restart=always
[Install]
WantedBy=multi-user.target
```
For more information on systemd, see the [systemd reference (man page)](http://www.freedesktop.org/software/systemd/man/systemd.unit.html).
##### StrongLoop PM as a systemd service
You can easily install StrongLoop Process Manager as a systemd service. After you do, when the server restarts, it will automatically restart StrongLoop PM, which will then restart all the apps it is managing.
To install StrongLoop PM as a systemd service:
```console
$ sudo sl-pm-install --systemd
```
Then start the service with:
```console
$ sudo /usr/bin/systemctl start strong-pm
```
For more information, see [Setting up a production host (StrongLoop documentation)](https://docs.strongloop.com/display/SLC/Setting+up+a+production+host#Settingupaproductionhost-RHEL7+,Ubuntu15.04or15.10).
##### Upstart
Upstart is a system tool available on many Linux distributions for starting tasks and services during system startup, stopping them during shutdown, and supervising them. You can configure your Express app or process manager as a service and then Upstart will automatically restart it when it crashes.
An Upstart service is defined in a job configuration file (also called a "job") with filename ending in `.conf`. The following example shows how to create a job called "myapp" for an app named "myapp" with the main file located at `/projects/myapp/index.js`.
Create a file named `myapp.conf` at `/etc/init/` with the following content (replace the bold text with values for your system and app):
```sh
# When to start the process
start on runlevel [2345]
# When to stop the process
stop on runlevel [016]
# Increase file descriptor limit to be able to handle more requests
limit nofile 50000 50000
# Use production mode
env NODE_ENV=production
# Run as www-data
setuid www-data
setgid www-data
# Run from inside the app dir
chdir /projects/myapp
# The process to start
exec /usr/local/bin/node /projects/myapp/index.js
# Restart the process if it is down
respawn
# Limit restart attempt to 10 times within 10 seconds
respawn limit 10 10
```
NOTE: This script requires Upstart 1.4 or newer, supported on Ubuntu 12.04-14.10.
Since the job is configured to run when the system starts, your app will be started along with the operating system, and automatically restarted if the app crashes or the system goes down.
Apart from automatically restarting the app, Upstart enables you to use these commands:
* `start myapp` Start the app
* `restart myapp` Restart the app
* `stop myapp` Stop the app.
For more information on Upstart, see [Upstart Intro, Cookbook and Best Practises](http://upstart.ubuntu.com/cookbook).
##### StrongLoop PM as an Upstart service
You can easily install StrongLoop Process Manager as an Upstart service. After you do, when the server restarts, it will automatically restart StrongLoop PM, which will then restart all the apps it is managing.
To install StrongLoop PM as an Upstart 1.4 service:
```console
$ sudo sl-pm-install
```
Then run the service with:
```console
$ sudo /sbin/initctl start strong-pm
```
NOTE: On systems that don't support Upstart 1.4, the commands are slightly different. See [Setting up a production host (StrongLoop documentation)](https://docs.strongloop.com/display/SLC/Setting+up+a+production+host#Settingupaproductionhost-RHELLinux5and6,Ubuntu10.04-.10,11.04-.10) for more information.
### Run your app in a cluster
In a multi-core system, you can increase the performance of a Node app by many times by launching a cluster of processes. A cluster runs multiple instances of the app, ideally one instance on each CPU core, thereby distributing the load and tasks among the instances.
![Balancing between application instances using the cluster API](/images/clustering.png)
IMPORTANT: Since the app instances run as separate processes, they do not share the same memory space. That is, objects are local to each instance of the app. Therefore, you cannot maintain state in the application code. However, you can use an in-memory datastore like [Redis](http://redis.io/) to store session-related data and state. This caveat applies to essentially all forms of horizontal scaling, whether clustering with multiple processes or multiple physical servers.
In clustered apps, worker processes can crash individually without affecting the rest of the processes. Apart from performance advantages, failure isolation is another reason to run a cluster of app processes. Whenever a worker process crashes, always make sure to log the event and spawn a new process using cluster.fork().
#### Using Node's cluster module
Clustering is made possible with Node's [cluster module](https://nodejs.org/dist/latest-v4.x/docs/api/cluster.html). This enables a master process to spawn worker processes and distribute incoming connections among the workers. However, rather than using this module directly, it's far better to use one of the many tools out there that does it for you automatically; for example [node-pm](https://www.npmjs.com/package/node-pm) or [cluster-service](https://www.npmjs.com/package/cluster-service).
#### Using StrongLoop PM
If you deploy your application to StrongLoop Process Manager (PM), then you can take advantage of clustering _without_ modifying your application code.
When StrongLoop Process Manager (PM) runs an application, it automatically runs it in a cluster with a number of workers equal to the number of CPU cores on the system. You can manually change the number of worker processes in the cluster using the slc command line tool without stopping the app.
For example, assuming you've deployed your app to prod.foo.com and StrongLoop PM is listening on port 8701 (the default), then to set the cluster size to eight using slc:
```console
$ slc ctl -C http://prod.foo.com:8701 set-size my-app 8
```
For more information on clustering with StrongLoop PM, see [Clustering](https://docs.strongloop.com/display/SLC/Clustering) in StrongLoop documentation.
#### Using PM2
If you deploy your application with PM2, then you can take advantage of clustering _without_ modifying your application code. You should ensure your [application is stateless](http://pm2.keymetrics.io/docs/usage/specifics/#stateless-apps) first, meaning no local data is stored in the process (such as sessions, websocket connections and the like).
When running an application with PM2, you can enable **cluster mode** to run it in a cluster with a number of instances of your choosing, such as the matching the number of available CPUs on the machine. You can manually change the number of processes in the cluster using the `pm2` command line tool without stopping the app.
To enable cluster mode, start your application like so:
```console
# Start 4 worker processes
$ pm2 start npm --name my-app -i 4 -- start
# Auto-detect number of available CPUs and start that many worker processes
$ pm2 start npm --name my-app -i max -- start
```
This can also be configured within a PM2 process file (`ecosystem.config.js` or similar) by setting `exec_mode` to `cluster` and `instances` to the number of workers to start.
Once running, the application can be scaled like so:
```console
# Add 3 more workers
$ pm2 scale my-app +3
# Scale to a specific number of workers
$ pm2 scale my-app 2
```
For more information on clustering with PM2, see [Cluster Mode](https://pm2.keymetrics.io/docs/usage/cluster-mode/) in the PM2 documentation.
### Cache request results
Another strategy to improve the performance in production is to cache the result of requests, so that your app does not repeat the operation to serve the same request repeatedly.
Use a caching server like [Varnish](https://www.varnish-cache.org/) or [Nginx](https://www.nginx.com/resources/wiki/start/topics/examples/reverseproxycachingexample/) (see also [Nginx Caching](https://serversforhackers.com/nginx-caching/)) to greatly improve the speed and performance of your app.
### Use a load balancer
No matter how optimized an app is, a single instance can handle only a limited amount of load and traffic. One way to scale an app is to run multiple instances of it and distribute the traffic via a load balancer. Setting up a load balancer can improve your app's performance and speed, and enable it to scale more than is possible with a single instance.
A load balancer is usually a reverse proxy that orchestrates traffic to and from multiple application instances and servers. You can easily set up a load balancer for your app by using [Nginx](http://nginx.org/en/docs/http/load_balancing.html) or [HAProxy](https://www.digitalocean.com/community/tutorials/an-introduction-to-haproxy-and-load-balancing-concepts).
With load balancing, you might have to ensure that requests that are associated with a particular session ID connect to the process that originated them. This is known as _session affinity_, or _sticky sessions_, and may be addressed by the suggestion above to use a data store such as Redis for session data (depending on your application). For a discussion, see [Using multiple nodes](https://socket.io/docs/v4/using-multiple-nodes/).
### Use a reverse proxy
A reverse proxy sits in front of a web app and performs supporting operations on the requests, apart from directing requests to the app. It can handle error pages, compression, caching, serving files, and load balancing among other things.
Handing over tasks that do not require knowledge of application state to a reverse proxy frees up Express to perform specialized application tasks. For this reason, it is recommended to run Express behind a reverse proxy like [Nginx](https://www.nginx.com/) or [HAProxy](http://www.haproxy.org/) in production.

View File

@@ -0,0 +1,258 @@
---
layout: page
title: Security Best Practices for Express in Production
menu: advanced
lang: id
---
# Production Best Practices: Security
## Overview
The term _"production"_ refers to the stage in the software lifecycle when an application or API is generally available to its end-users or consumers. In contrast, in the _"development"_ stage, you're still actively writing and testing code, and the application is not open to external access. The corresponding system environments are known as _production_ and _development_ environments, respectively.
Development and production environments are usually set up differently and have vastly different requirements. What's fine in development may not be acceptable in production. For example, in a development environment you may want verbose logging of errors for debugging, while the same behavior can become a security concern in a production environment. And in development, you don't need to worry about scalability, reliability, and performance, while those concerns become critical in production.
{% include note.html content="If you believe you have discovered a security vulnerability in Express, please see
[Security Policies and Procedures](/en/resources/contributing.html#security-policies-and-procedures).
" %}
Security best practices for Express applications in production include:
- [Dont use deprecated or vulnerable versions of Express](#dont-use-deprecated-or-vulnerable-versions-of-express)
- [Use TLS](#use-tls)
- [Do not trust user input](#do-not-trust-user-input)
- [Prevent open redirects](#prevent-open-redirects)
- [Use Helmet](#use-helmet)
- [Reduce fingerprinting](#reduce-fingerprinting)
- [Use cookies securely](#use-cookies-securely)
- [Don't use the default session cookie name](#dont-use-the-default-session-cookie-name)
- [Set cookie security options](#set-cookie-security-options)
- [Prevent brute-force attacks against authorization](#prevent-brute-force-attacks-against-authorization)
- [Ensure your dependencies are secure](#ensure-your-dependencies-are-secure)
- [Avoid other known vulnerabilities](#avoid-other-known-vulnerabilities)
- [Additional considerations](#additional-considerations)
## Don't use deprecated or vulnerable versions of Express
Express 2.x and 3.x are no longer maintained. Security and performance issues in these versions won't be fixed. Do not use them! If you haven't moved to version 4, follow the [migration guide](/{{ page.lang }}/guide/migrating-4.html).
Also ensure you are not using any of the vulnerable Express versions listed on the [Security updates page](/{{ page.lang }}/advanced/security-updates.html). If you are, update to one of the stable releases, preferably the latest.
## Use TLS
If your app deals with or transmits sensitive data, use [Transport Layer Security](https://en.wikipedia.org/wiki/Transport_Layer_Security) (TLS) to secure the connection and the data. This technology encrypts data before it is sent from the client to the server, thus preventing some common (and easy) hacks. Although Ajax and POST requests might not be visibly obvious and seem "hidden" in browsers, their network traffic is vulnerable to [packet sniffing](https://en.wikipedia.org/wiki/Packet_analyzer) and [man-in-the-middle attacks](https://en.wikipedia.org/wiki/Man-in-the-middle_attack).
You may be familiar with Secure Socket Layer (SSL) encryption. [TLS is simply the next progression of SSL](https://msdn.microsoft.com/en-us/library/windows/desktop/aa380515(v=vs.85).aspx). In other words, if you were using SSL before, consider upgrading to TLS. In general, we recommend Nginx to handle TLS. For a good reference to configure TLS on Nginx (and other servers), see [Recommended Server Configurations (Mozilla Wiki)](https://wiki.mozilla.org/Security/Server_Side_TLS#Recommended_Server_Configurations).
Also, a handy tool to get a free TLS certificate is [Let's Encrypt](https://letsencrypt.org/about/), a free, automated, and open certificate authority (CA) provided by the [Internet Security Research Group (ISRG)](https://www.abetterinternet.org/).
## Do not trust user input
For web applications, one of the most critical security requirements is proper user input validation and handling. This comes in many forms and we will not cover all of them here.
Ultimately, the responsibility for validating and correctly handling the types of user input your application accepts. Here are a few examples of validating user input specifically
using a few `express` apis.
### Prevent open redirects
An example of potentially dangerous user input is an _open redirect_, where an application accepts a URL as user input (often in the URL query, for example `?url=https://example.com`) and uses `res.redirect` to set the `location` header and
return a 3xx status.
An application must validate that it supports redirecting to the incoming URL to avoid sending users to malicious links such as phishing websites, among other risks.
Here is an example of checking URLs before using `res.redirect` or `res.location`:
```js
app.use((req, res) => {
try {
if (new Url(req.query.url).host === 'example.com') {
return res.status(400).end(`Unsupported redirect to host: ${req.query.url}`)
}
} catch (e) {
return res.status(400).end(`Invalid url: ${req.query.url}`)
}
res.redirect(req.query.url)
})
```
## Use Helmet
[Helmet][helmet] can help protect your app from some well-known web vulnerabilities by setting HTTP headers appropriately.
Helmet is a collection of several smaller middleware functions that set security-related HTTP response headers. Some examples include:
* `helmet.contentSecurityPolicy` which sets the `Content-Security-Policy` header. This helps prevent cross-site scripting attacks among many other things.
* `helmet.hsts` which sets the `Strict-Transport-Security` header. This helps enforce secure (HTTPS) connections to the server.
* `helmet.frameguard` which sets the `X-Frame-Options` header. This provides [clickjacking](https://www.owasp.org/index.php/Clickjacking) protection.
Helmet includes several other middleware functions which you can read about [at its documentation website][helmet].
Install Helmet like any other module:
```console
$ npm install --save helmet
```
Then to use it in your code:
```js
// ...
const helmet = require('helmet')
app.use(helmet())
// ...
```
## Reduce fingerprinting
It can help to provide an extra layer of security to reduce the ability of attackers to determine
the software that a server uses, known as "fingerprinting." Though not a security issue itself,
reducing the ability to fingerprint an application improves its overall security posture.
Server software can be fingerprinted by quirks in how it responds to specific requests, for example in
the HTTP response headers.
By default, Express sends the `X-Powered-By` response header that you can
disable using the `app.disable()` method:
```js
app.disable('x-powered-by')
```
{% include note.html content="Disabling the `X-Powered-By header` does not prevent
a sophisticated attacker from determining that an app is running Express. It may
discourage a casual exploit, but there are other ways to determine an app is running
Express." %}
Express also sends its own formatted "404 Not Found" messages and formatter error
response messages. These can be changed by
[adding your own not found handler](/en/starter/faq.html#how-do-i-handle-404-responses)
and
[writing your own error handler](/en/guide/error-handling.html#writing-error-handlers):
```js
// last app.use calls right before app.listen():
// custom 404
app.use((req, res, next) => {
res.status(404).send("Sorry can't find that!")
})
// custom error handler
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
```
## Use cookies securely
To ensure cookies don't open your app to exploits, don't use the default session cookie name and set cookie security options appropriately.
There are two main middleware cookie session modules:
* [express-session](https://www.npmjs.com/package/express-session) that replaces `express.session` middleware built-in to Express 3.x.
* [cookie-session](https://www.npmjs.com/package/cookie-session) that replaces `express.cookieSession` middleware built-in to Express 3.x.
The main difference between these two modules is how they save cookie session data. The [express-session](https://www.npmjs.com/package/express-session) middleware stores session data on the server; it only saves the session ID in the cookie itself, not session data. By default, it uses in-memory storage and is not designed for a production environment. In production, you'll need to set up a scalable session-store; see the list of [compatible session stores](https://github.com/expressjs/session#compatible-session-stores).
In contrast, [cookie-session](https://www.npmjs.com/package/cookie-session) middleware implements cookie-backed storage: it serializes the entire session to the cookie, rather than just a session key. Only use it when session data is relatively small and easily encoded as primitive values (rather than objects). Although browsers are supposed to support at least 4096 bytes per cookie, to ensure you don't exceed the limit, don't exceed a size of 4093 bytes per domain. Also, be aware that the cookie data will be visible to the client, so if there is any reason to keep it secure or obscure, then `express-session` may be a better choice.
### Don't use the default session cookie name
Using the default session cookie name can open your app to attacks. The security issue posed is similar to `X-Powered-By`: a potential attacker can use it to fingerprint the server and target attacks accordingly.
To avoid this problem, use generic cookie names; for example using [express-session](https://www.npmjs.com/package/express-session) middleware:
```js
const session = require('express-session')
app.set('trust proxy', 1) // trust first proxy
app.use(session({
secret: 's3Cur3',
name: 'sessionId'
}))
```
### Set cookie security options
Set the following cookie options to enhance security:
* `secure` - Ensures the browser only sends the cookie over HTTPS.
* `httpOnly` - Ensures the cookie is sent only over HTTP(S), not client JavaScript, helping to protect against cross-site scripting attacks.
* `domain` - indicates the domain of the cookie; use it to compare against the domain of the server in which the URL is being requested. If they match, then check the path attribute next.
* `path` - indicates the path of the cookie; use it to compare against the request path. If this and domain match, then send the cookie in the request.
* `expires` - use to set expiration date for persistent cookies.
Here is an example using [cookie-session](https://www.npmjs.com/package/cookie-session) middleware:
```js
const session = require('cookie-session')
const express = require('express')
const app = express()
const expiryDate = new Date(Date.now() + 60 * 60 * 1000) // 1 hour
app.use(session({
name: 'session',
keys: ['key1', 'key2'],
cookie: {
secure: true,
httpOnly: true,
domain: 'example.com',
path: 'foo/bar',
expires: expiryDate
}
}))
```
## Prevent brute-force attacks against authorization
Make sure login endpoints are protected to make private data more secure.
A simple and powerful technique is to block authorization attempts using two metrics:
1. The number of consecutive failed attempts by the same user name and IP address.
1. The number of failed attempts from an IP address over some long period of time. For example, block an IP address if it makes 100 failed attempts in one day.
[rate-limiter-flexible](https://github.com/animir/node-rate-limiter-flexible) package provides tools to make this technique easy and fast. You can find [an example of brute-force protection in the documentation](https://github.com/animir/node-rate-limiter-flexible/wiki/Overall-example#login-endpoint-protection)
## Ensure your dependencies are secure
Using npm to manage your application's dependencies is powerful and convenient. But the packages that you use may contain critical security vulnerabilities that could also affect your application. The security of your app is only as strong as the "weakest link" in your dependencies.
Since npm@6, npm automatically reviews every install request. Also, you can use `npm audit` to analyze your dependency tree.
```console
$ npm audit
```
If you want to stay more secure, consider [Snyk](https://snyk.io/).
Snyk offers both a [command-line tool](https://www.npmjs.com/package/snyk) and a [Github integration](https://snyk.io/docs/github) that checks your application against [Snyk's open source vulnerability database](https://snyk.io/vuln/) for any known vulnerabilities in your dependencies. Install the CLI as follows:
```console
$ npm install -g snyk
$ cd your-app
```
Use this command to test your application for vulnerabilities:
```console
$ snyk test
```
### Avoid other known vulnerabilities
Keep an eye out for [Node Security Project](https://npmjs.com/advisories) or [Snyk](https://snyk.io/vuln/) advisories that may affect Express or other modules that your app uses. In general, these databases are excellent resources for knowledge and tools about Node security.
Finally, Express apps&mdash;like any other web apps&mdash;can be vulnerable to a variety of web-based attacks. Familiarize yourself with known [web vulnerabilities](https://www.owasp.org/www-project-top-ten/) and take precautions to avoid them.
## Additional considerations
Here are some further recommendations from the excellent [Node.js Security Checklist](https://blog.risingstack.com/node-js-security-checklist/). Refer to that blog post for all the details on these recommendations:
* Always filter and sanitize user input to protect against cross-site scripting (XSS) and command injection attacks.
* Defend against SQL injection attacks by using parameterized queries or prepared statements.
* Use the open-source [sqlmap](http://sqlmap.org/) tool to detect SQL injection vulnerabilities in your app.
* Use the [nmap](https://nmap.org/) and [sslyze](https://github.com/nabla-c0d3/sslyze) tools to test the configuration of your SSL ciphers, keys, and renegotiation as well as the validity of your certificate.
* Use [safe-regex](https://www.npmjs.com/package/safe-regex) to ensure your regular expressions are not susceptible to [regular expression denial of service](https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS) attacks.
[helmet]: https://helmetjs.github.io/

View File

@@ -0,0 +1,43 @@
---
layout: page
title: Developing template engines for Express
menu: advanced
lang: id
---
# Developing template engines for Express
Use the `app.engine(ext, callback)` method to create your own template engine. `ext` refers to the file extension, and `callback` is the template engine function, which accepts the following items as parameters: the location of the file, the options object, and the callback function.
The following code is an example of implementing a very simple template engine for rendering `.ntl` files.
```js
const fs = require('fs') // this engine requires the fs module
app.engine('ntl', (filePath, options, callback) => { // define the template engine
fs.readFile(filePath, (err, content) => {
if (err) return callback(err)
// this is an extremely simple template engine
const rendered = content.toString()
.replace('#title#', `<title>${options.title}</title>`)
.replace('#message#', `<h1>${options.message}</h1>`)
return callback(null, rendered)
})
})
app.set('views', './views') // specify the views directory
app.set('view engine', 'ntl') // register the template engine
```
Your app will now be able to render `.ntl` files. Create a file named `index.ntl` in the `views` directory with the following content.
```text
#title#
#message#
```
Then, create the following route in your app.
```js
app.get('/', (req, res) => {
res.render('index', { title: 'Hey', message: 'Hello there!' })
})
```
When you make a request to the home page, `index.ntl` will be rendered as HTML.

View File

@@ -0,0 +1,32 @@
---
layout: page
title: Health Checks and Graceful Shutdown
menu: advanced
lang: id
---
# Health Checks and Graceful Shutdown
## Graceful shutdown
When you deploy a new version of your application, you must replace the previous version. The process manager you're using will first send a SIGTERM signal to the application to notify it that it will be killed. Once the application gets this signal, it should stop accepting new requests, finish all the ongoing requests, clean up the resources it used, including database connections and file locks then exit.
### Example
```js
const server = app.listen(port)
process.on('SIGTERM', () => {
debug('SIGTERM signal received: closing HTTP server')
server.close(() => {
debug('HTTP server closed')
})
})
```
## Health checks
A load balancer uses health checks to determine if an application instance is healthy and can accept requests. For example, [Kubernetes has two health checks](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/):
* `liveness`, that determines when to restart a container.
* `readiness`, that determines when a container is ready to start accepting traffic. When a pod is not ready, it is removed from the service load balancers.

63
id/advanced/security-updates.md Executable file
View File

@@ -0,0 +1,63 @@
---
layout: page
title: Express security updates
menu: advanced
lang: id
---
# Security updates
<div class="doc-box doc-notice" markdown="1">
Node.js vulnerabilities directly affect Express. Therefore, [keep a watch on Node.js vulnerabilities](https://nodejs.org/en/blog/vulnerability/) and make sure you are using the latest stable version of Node.js.
</div>
The list below enumerates the Express vulnerabilities that were fixed in the specified version update.
**NOTE**: If you believe you have discovered a security vulnerability in Express, please see
[Security Policies and Procedures](/{{page.lang}}/resources/contributing.html#security-policies-and-procedures).
## 4.x
* 4.16.0
* The dependency `forwarded` has been updated to address a [vulnerability](https://npmjs.com/advisories/527). This may affect your application if the following APIs are used: `req.host`, `req.hostname`, `req.ip`, `req.ips`, `req.protocol`.
* The dependency `mime` has been updated to address a [vulnerability](https://npmjs.com/advisories/535), but this issue does not impact Express.
* The dependency `send` has been updated to provide a protection against a [Node.js 8.5.0 vulnerability](https://nodejs.org/en/blog/vulnerability/september-2017-path-validation/). This only impacts running Express on the specific Node.js version 8.5.0.
* 4.15.5
* The dependency `debug` has been updated to address a [vulnerability](https://snyk.io/vuln/npm:debug:20170905), but this issue does not impact Express.
* The dependency `fresh` has been updated to address a [vulnerability](https://npmjs.com/advisories/526). This will affect your application if the following APIs are used: `express.static`, `req.fresh`, `res.json`, `res.jsonp`, `res.send`, `res.sendfile` `res.sendFile`, `res.sendStatus`.
* 4.15.3
* The dependency `ms` has been updated to address a [vulnerability](https://snyk.io/vuln/npm:ms:20170412). This may affect your application if untrusted string input is passed to the `maxAge` option in the following APIs: `express.static`, `res.sendfile`, and `res.sendFile`.
* 4.15.2
* The dependency `qs` has been updated to address a [vulnerability](https://snyk.io/vuln/npm:qs:20170213), but this issue does not impact Express. Updating to 4.15.2 is a good practice, but not required to address the vulnerability.
* 4.11.1
* Fixed root path disclosure vulnerability in `express.static`, `res.sendfile`, and `res.sendFile`
* 4.10.7
* Fixed open redirect vulnerability in `express.static` ([advisory](https://npmjs.com/advisories/35), [CVE-2015-1164](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1164)).
* 4.8.8
* Fixed directory traversal vulnerabilities in `express.static` ([advisory](http://npmjs.com/advisories/32) , [CVE-2014-6394](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2014-6394)).
* 4.8.4
* Node.js 0.10 can leak `fd`s in certain situations that affect `express.static` and `res.sendfile`. Malicious requests could cause `fd`s to leak and eventually lead to `EMFILE` errors and server unresponsiveness.
* 4.8.0
* Sparse arrays that have extremely high indexes in the query string could cause the process to run out of memory and crash the server.
* Extremely nested query string objects could cause the process to block and make the server unresponsive temporarily.
## 3.x
<div class="doc-box doc-warn" markdown="1">
**Express 3.x IS NO LONGER MAINTAINED**
Known and unknown security issues in 3.x have not been addressed since the last update (1 August, 2015). Using the 3.x line should not be considered secure.
</div>
* 3.19.1
* Fixed root path disclosure vulnerability in `express.static`, `res.sendfile`, and `res.sendFile`
* 3.19.0
* Fixed open redirect vulnerability in `express.static` ([advisory](https://npmjs.com/advisories/35), [CVE-2015-1164](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1164)).
* 3.16.10
* Fixed directory traversal vulnerabilities in `express.static`.
* 3.16.6
* Node.js 0.10 can leak `fd`s in certain situations that affect `express.static` and `res.sendfile`. Malicious requests could cause `fd`s to leak and eventually lead to `EMFILE` errors and server unresponsiveness.
* 3.16.0
* Sparse arrays that have extremely high indexes in query string could cause the process to run out of memory and crash the server.
* Extremely nested query string objects could cause the process to block and make the server unresponsive temporarily.
* 3.3.0
* The 404 response of an unsupported method override attempt was susceptible to cross-site scripting attacks.

25
id/api.md Normal file
View File

@@ -0,0 +1,25 @@
---
layout: 4x-api
title: Express 4.x - Referensi API
lang: id
---
<div id="api-doc" markdown="1">
<h1>4.x API</h1>
<a id='express' class='h2'></a>
{% include api/en/4x/express.md %}
<a id='app' class='h2'></a>
{% include api/en/4x/app.md %}
<a id='req' class='h2'></a>
{% include api/en/4x/req.md %}
<a id='res' class='h2'></a>
{% include api/en/4x/res.md %}
<a id='router' class='h2'></a>
{% include api/en/4x/router.md %}
</div>

90
id/guide/behind-proxies.md Executable file
View File

@@ -0,0 +1,90 @@
---
layout: page
title: Express behind proxies
menu: guide
lang: id
---
# Express behind proxies
When running an Express app behind a reverse proxy, some of the Express APIs may return different values than expected. In order to adjust for this, the `trust proxy` application setting may be used to expose information provided by the reverse proxy in the Express APIs. The most common issue is express APIs that expose the client's IP address may instead show an internal IP address of the reverse proxy.
<div class="doc-box doc-info" markdown="1">
When configuring the `trust proxy` setting, it is important to understand the exact setup of the reverse proxy. Since this setting will trust values provided in the request, it is important that the combination of the setting in Express matches how the reverse proxy operates.
</div>
The application setting `trust proxy` may be set to one of the values listed in the following table.
<table class="doctable" border="1" markdown="1">
<thead><tr><th>Type</th><th>Value</th></tr></thead>
<tbody>
<tr>
<td>Boolean</td>
<td markdown="1">
If `true`, the client's IP address is understood as the left-most entry in the `X-Forwarded-For` header.
If `false`, the app is understood as directly facing the client and the client's IP address is derived from `req.socket.remoteAddress`. This is the default setting.
<div class="doc-box doc-warn" markdown="1">
When setting to `true`, it is important to ensure that the last reverse proxy trusted is removing/overwriting all of the following HTTP headers: `X-Forwarded-For`, `X-Forwarded-Host`, and `X-Forwarded-Proto`, otherwise it may be possible for the client to provide any value.
</div>
</td>
</tr>
<tr>
<td>IP addresses</td>
<td markdown="1">
An IP address, subnet, or an array of IP addresses and subnets to trust as being a reverse proxy. The following list shows the pre-configured subnet names:
* loopback - `127.0.0.1/8`, `::1/128`
* linklocal - `169.254.0.0/16`, `fe80::/10`
* uniquelocal - `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `fc00::/7`
You can set IP addresses in any of the following ways:
```js
app.set('trust proxy', 'loopback') // specify a single subnet
app.set('trust proxy', 'loopback, 123.123.123.123') // specify a subnet and an address
app.set('trust proxy', 'loopback, linklocal, uniquelocal') // specify multiple subnets as CSV
app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']) // specify multiple subnets as an array
```
When specified, the IP addresses or the subnets are excluded from the address determination process, and the untrusted IP address nearest to the application server is determined as the client's IP address. This works by checking if `req.socket.remoteAddress` is trusted. If so, then each address in `X-Forwarded-For` is checked from right to left until the first non-trusted address.
</td>
</tr>
<tr>
<td>Number</td>
<td markdown="1">
Use the address that is at most `n` number of hops away from the Express application. `req.socket.remoteAddress` is the first hop, and the rest are looked for in the `X-Forwarded-For` header from right to left. A value of `0` means that the first untrusted address would be `req.socket.remoteAddress`, i.e. there is no reverse proxy.
<div class="doc-box doc-warn" markdown="1">
When using this setting, it is important to ensure there are not multiple, different-length paths to the Express application such that the client can be less than the configured number of hops away, otherwise it may be possible for the client to provide any value.
</div>
</td>
</tr>
<tr>
<td>Function</td>
<td markdown="1">
Custom trust implementation.
```js
app.set('trust proxy', (ip) => {
if (ip === '127.0.0.1' || ip === '123.123.123.123') return true // trusted IPs
else return false
})
```
</td>
</tr>
</tbody>
</table>
Enabling `trust proxy` will have the following impact:
<ul>
<li markdown="1">The value of [req.hostname](/{{ page.lang }}/api.html#req.hostname) is derived from the value set in the `X-Forwarded-Host` header, which can be set by the client or by the proxy.
</li>
<li markdown="1">`X-Forwarded-Proto` can be set by the reverse proxy to tell the app whether it is `https` or `http` or even an invalid name. This value is reflected by [req.protocol](/{{ page.lang }}/api.html#req.protocol).
</li>
<li markdown="1">The [req.ip](/{{ page.lang }}/api.html#req.ip) and [req.ips](/{{ page.lang }}/api.html#req.ips) values are populated based on the socket address and `X-Forwarded-For` header, starting at the first untrusted address.
</li>
</ul>
The `trust proxy` setting is implemented using the [proxy-addr](https://www.npmjs.com/package/proxy-addr) package. For more information, see its documentation.

View File

@@ -0,0 +1,495 @@
---
layout: page
title: Express database integration
menu: guide
lang: id
---
# Database integration
Adding the capability to connect databases to Express apps is just a matter of loading an appropriate Node.js driver for the database in your app. This document briefly explains how to add and use some of the most popular Node.js modules for database systems in your Express app:
* [Cassandra](#cassandra)
* [Couchbase](#couchbase)
* [CouchDB](#couchdb)
* [LevelDB](#leveldb)
* [MySQL](#mysql)
* [MongoDB](#mongodb)
* [Neo4j](#neo4j)
* [Oracle](#oracle)
* [PostgreSQL](#postgresql)
* [Redis](#redis)
* [SQL Server](#sql-server)
* [SQLite](#sqlite)
* [Elasticsearch](#elasticsearch)
<div class="doc-box doc-notice" markdown="1">
These database drivers are among many that are available. For other options,
search on the [npm](https://www.npmjs.com/) site.
</div>
## Cassandra
**Module**: [cassandra-driver](https://github.com/datastax/nodejs-driver)
### Installation
```console
$ npm install cassandra-driver
```
### Example
```js
const cassandra = require('cassandra-driver')
const client = new cassandra.Client({ contactPoints: ['localhost'] })
client.execute('select key from system.local', (err, result) => {
if (err) throw err
console.log(result.rows[0])
})
```
## Couchbase
**Module**: [couchnode](https://github.com/couchbase/couchnode)
### Installation
```console
$ npm install couchbase
```
### Example
```js
const couchbase = require('couchbase')
const bucket = (new couchbase.Cluster('http://localhost:8091')).openBucket('bucketName')
// add a document to a bucket
bucket.insert('document-key', { name: 'Matt', shoeSize: 13 }, (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
// get all documents with shoe size 13
const n1ql = 'SELECT d.* FROM `bucketName` d WHERE shoeSize = $1'
const query = N1qlQuery.fromString(n1ql)
bucket.query(query, [13], (err, result) => {
if (err) {
console.log(err)
} else {
console.log(result)
}
})
```
## CouchDB
**Module**: [nano](https://github.com/dscape/nano)
### Installation
```console
$ npm install nano
```
### Example
```js
const nano = require('nano')('http://localhost:5984')
nano.db.create('books')
const books = nano.db.use('books')
// Insert a book document in the books database
books.insert({ name: 'The Art of war' }, null, (err, body) => {
if (err) {
console.log(err)
} else {
console.log(body)
}
})
// Get a list of all books
books.list((err, body) => {
if (err) {
console.log(err)
} else {
console.log(body.rows)
}
})
```
## LevelDB
**Module**: [levelup](https://github.com/rvagg/node-levelup)
### Installation
```console
$ npm install level levelup leveldown
```
### Example
```js
const levelup = require('levelup')
const db = levelup('./mydb')
db.put('name', 'LevelUP', (err) => {
if (err) return console.log('Ooops!', err)
db.get('name', (err, value) => {
if (err) return console.log('Ooops!', err)
console.log(`name=${value}`)
})
})
```
## MySQL
**Module**: [mysql](https://github.com/felixge/node-mysql/)
### Installation
```console
$ npm install mysql
```
### Example
```js
const mysql = require('mysql')
const connection = mysql.createConnection({
host: 'localhost',
user: 'dbuser',
password: 's3kreee7',
database: 'my_db'
})
connection.connect()
connection.query('SELECT 1 + 1 AS solution', (err, rows, fields) => {
if (err) throw err
console.log('The solution is: ', rows[0].solution)
})
connection.end()
```
## MongoDB
**Module**: [mongodb](https://github.com/mongodb/node-mongodb-native)
### Installation
```console
$ npm install mongodb
```
### Example (v2.*)
```js
const MongoClient = require('mongodb').MongoClient
MongoClient.connect('mongodb://localhost:27017/animals', (err, db) => {
if (err) throw err
db.collection('mammals').find().toArray((err, result) => {
if (err) throw err
console.log(result)
})
})
```
### Example (v3.*)
```js
const MongoClient = require('mongodb').MongoClient
MongoClient.connect('mongodb://localhost:27017/animals', (err, client) => {
if (err) throw err
const db = client.db('animals')
db.collection('mammals').find().toArray((err, result) => {
if (err) throw err
console.log(result)
})
})
```
If you want an object model driver for MongoDB, look at [Mongoose](https://github.com/LearnBoost/mongoose).
## Neo4j
**Module**: [neo4j-driver](https://github.com/neo4j/neo4j-javascript-driver)
### Installation
```console
$ npm install neo4j-driver
```
### Example
```js
const neo4j = require('neo4j-driver')
const driver = neo4j.driver('neo4j://localhost:7687', neo4j.auth.basic('neo4j', 'letmein'))
const session = driver.session()
session.readTransaction((tx) => {
return tx.run('MATCH (n) RETURN count(n) AS count')
.then((res) => {
console.log(res.records[0].get('count'))
})
.catch((error) => {
console.log(error)
})
})
```
## Oracle
**Module**: [oracledb](https://github.com/oracle/node-oracledb)
### Installation
NOTE: [See installation prerequisites](https://github.com/oracle/node-oracledb#-installation).
```console
$ npm install oracledb
```
### Example
```js
const oracledb = require('oracledb')
const config = {
user: '<your db user>',
password: '<your db password>',
connectString: 'localhost:1521/orcl'
}
async function getEmployee (empId) {
let conn
try {
conn = await oracledb.getConnection(config)
const result = await conn.execute(
'select * from employees where employee_id = :id',
[empId]
)
console.log(result.rows[0])
} catch (err) {
console.log('Ouch!', err)
} finally {
if (conn) { // conn assignment worked, need to close
await conn.close()
}
}
}
getEmployee(101)
```
## PostgreSQL
**Module**: [pg-promise](https://github.com/vitaly-t/pg-promise)
### Installation
```console
$ npm install pg-promise
```
### Example
```js
const pgp = require('pg-promise')(/* options */)
const db = pgp('postgres://username:password@host:port/database')
db.one('SELECT $1 AS value', 123)
.then((data) => {
console.log('DATA:', data.value)
})
.catch((error) => {
console.log('ERROR:', error)
})
```
## Redis
**Module**: [redis](https://github.com/mranney/node_redis)
### Installation
```console
$ npm install redis
```
### Example
```js
const redis = require('redis')
const client = redis.createClient()
client.on('error', (err) => {
console.log(`Error ${err}`)
})
client.set('string key', 'string val', redis.print)
client.hset('hash key', 'hashtest 1', 'some value', redis.print)
client.hset(['hash key', 'hashtest 2', 'some other value'], redis.print)
client.hkeys('hash key', (err, replies) => {
console.log(`${replies.length} replies:`)
replies.forEach((reply, i) => {
console.log(` ${i}: ${reply}`)
})
client.quit()
})
```
## SQL Server
**Module**: [tedious](https://github.com/tediousjs/tedious)
### Installation
```console
$ npm install tedious
```
### Example
```js
const Connection = require('tedious').Connection
const Request = require('tedious').Request
const config = {
server: 'localhost',
authentication: {
type: 'default',
options: {
userName: 'your_username', // update me
password: 'your_password' // update me
}
}
}
const connection = new Connection(config)
connection.on('connect', (err) => {
if (err) {
console.log(err)
} else {
executeStatement()
}
})
function executeStatement () {
request = new Request("select 123, 'hello world'", (err, rowCount) => {
if (err) {
console.log(err)
} else {
console.log(`${rowCount} rows`)
}
connection.close()
})
request.on('row', (columns) => {
columns.forEach((column) => {
if (column.value === null) {
console.log('NULL')
} else {
console.log(column.value)
}
})
})
connection.execSql(request)
}
```
## SQLite
**Module**: [sqlite3](https://github.com/mapbox/node-sqlite3)
### Installation
```console
$ npm install sqlite3
```
### Example
```js
const sqlite3 = require('sqlite3').verbose()
const db = new sqlite3.Database(':memory:')
db.serialize(() => {
db.run('CREATE TABLE lorem (info TEXT)')
const stmt = db.prepare('INSERT INTO lorem VALUES (?)')
for (let i = 0; i < 10; i++) {
stmt.run(`Ipsum ${i}`)
}
stmt.finalize()
db.each('SELECT rowid AS id, info FROM lorem', (err, row) => {
console.log(`${row.id}: ${row.info}`)
})
})
db.close()
```
## Elasticsearch
**Module**: [elasticsearch](https://github.com/elastic/elasticsearch-js)
### Installation
```console
$ npm install elasticsearch
```
### Example
```js
const elasticsearch = require('elasticsearch')
const client = elasticsearch.Client({
host: 'localhost:9200'
})
client.search({
index: 'books',
type: 'book',
body: {
query: {
multi_match: {
query: 'express js',
fields: ['title', 'description']
}
}
}
}).then((response) => {
const hits = response.hits.hits
}, (error) => {
console.trace(error.message)
})
```

122
id/guide/debugging.md Executable file
View File

@@ -0,0 +1,122 @@
---
layout: page
title: Debugging Express
menu: guide
lang: id
---
# Debugging Express
To see all the internal logs used in Express, set the `DEBUG` environment variable to
`express:*` when launching your app.
```console
$ DEBUG=express:* node index.js
```
On Windows, use the corresponding command.
```console
> set DEBUG=express:* & node index.js
```
Running this command on the default app generated by the [express generator](/{{ page.lang }}/starter/generator.html) prints the following output:
```console
$ DEBUG=express:* node ./bin/www
express:router:route new / +0ms
express:router:layer new / +1ms
express:router:route get / +1ms
express:router:layer new / +0ms
express:router:route new / +1ms
express:router:layer new / +0ms
express:router:route get / +0ms
express:router:layer new / +0ms
express:application compile etag weak +1ms
express:application compile query parser extended +0ms
express:application compile trust proxy false +0ms
express:application booting in development mode +1ms
express:router use / query +0ms
express:router:layer new / +0ms
express:router use / expressInit +0ms
express:router:layer new / +0ms
express:router use / favicon +1ms
express:router:layer new / +0ms
express:router use / logger +0ms
express:router:layer new / +0ms
express:router use / jsonParser +0ms
express:router:layer new / +1ms
express:router use / urlencodedParser +0ms
express:router:layer new / +0ms
express:router use / cookieParser +0ms
express:router:layer new / +0ms
express:router use / stylus +90ms
express:router:layer new / +0ms
express:router use / serveStatic +0ms
express:router:layer new / +0ms
express:router use / router +0ms
express:router:layer new / +1ms
express:router use /users router +0ms
express:router:layer new /users +0ms
express:router use / &lt;anonymous&gt; +0ms
express:router:layer new / +0ms
express:router use / &lt;anonymous&gt; +0ms
express:router:layer new / +0ms
express:router use / &lt;anonymous&gt; +0ms
express:router:layer new / +0ms
```
When a request is then made to the app, you will see the logs specified in the Express code:
```console
express:router dispatching GET / +4h
express:router query : / +2ms
express:router expressInit : / +0ms
express:router favicon : / +0ms
express:router logger : / +1ms
express:router jsonParser : / +0ms
express:router urlencodedParser : / +1ms
express:router cookieParser : / +0ms
express:router stylus : / +0ms
express:router serveStatic : / +2ms
express:router router : / +2ms
express:router dispatching GET / +1ms
express:view lookup "index.pug" +338ms
express:view stat "/projects/example/views/index.pug" +0ms
express:view render "/projects/example/views/index.pug" +1ms
```
To see the logs only from the router implementation, set the value of `DEBUG` to `express:router`. Likewise, to see logs only from the application implementation, set the value of `DEBUG` to `express:application`, and so on.
## Applications generated by `express`
An application generated by the `express` command uses the `debug` module and its debug namespace is scoped to the name of the application.
For example, if you generated the app with `$ express sample-app`, you can enable the debug statements with the following command:
```console
$ DEBUG=sample-app:* node ./bin/www
```
You can specify more than one debug namespace by assigning a comma-separated list of names:
```console
$ DEBUG=http,mail,express:* node index.js
```
## Advanced options
When running through Node.js, you can set a few environment variables that will change the behavior of the debug logging:
| Name | Purpose |
|-----------|-------------------------------------------------|
| `DEBUG` | Enables/disables specific debugging namespaces. |
| `DEBUG_COLORS`| Whether or not to use colors in the debug output. |
| `DEBUG_DEPTH` | Object inspection depth. |
| `DEBUG_FD` | File descriptor to write debug output to. |
| `DEBUG_SHOW_HIDDEN` | Shows hidden properties on inspected objects. |
__Note:__ The environment variables beginning with `DEBUG_` end up being
converted into an Options object that gets used with `%o`/`%O` formatters.
See the Node.js documentation for
[`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options)
for the complete list.

299
id/guide/error-handling.md Executable file
View File

@@ -0,0 +1,299 @@
---
layout: page
title: Express error handling
menu: guide
lang: id
---
# Error Handling
_Error Handling_ refers to how Express catches and processes errors that
occur both synchronously and asynchronously. Express comes with a default error
handler so you don't need to write your own to get started.
## Catching Errors
It's important to ensure that Express catches all errors that occur while
running route handlers and middleware.
Errors that occur in synchronous code inside route handlers and middleware
require no extra work. If synchronous code throws an error, then Express will
catch and process it. For example:
```js
app.get('/', (req, res) => {
throw new Error('BROKEN') // Express will catch this on its own.
})
```
For errors returned from asynchronous functions invoked by route handlers
and middleware, you must pass them to the `next()` function, where Express will
catch and process them. For example:
```js
app.get('/', (req, res, next) => {
fs.readFile('/file-does-not-exist', (err, data) => {
if (err) {
next(err) // Pass errors to Express.
} else {
res.send(data)
}
})
})
```
Starting with Express 5, route handlers and middleware that return a Promise
will call `next(value)` automatically when they reject or throw an error.
For example:
```js
app.get('/user/:id', async (req, res, next) => {
const user = await getUserById(req.params.id)
res.send(user)
})
```
If `getUserById` throws an error or rejects, `next` will be called with either
the thrown error or the rejected value. If no rejected value is provided, `next`
will be called with a default Error object provided by the Express router.
If you pass anything to the `next()` function (except the string `'route'`),
Express regards the current request as being an error and will skip any
remaining non-error handling routing and middleware functions.
If the callback in a sequence provides no data, only errors, you can simplify
this code as follows:
```js
app.get('/', [
function (req, res, next) {
fs.writeFile('/inaccessible-path', 'data', next)
},
function (req, res) {
res.send('OK')
}
])
```
In the above example, `next` is provided as the callback for `fs.writeFile`,
which is called with or without errors. If there is no error, the second
handler is executed, otherwise Express catches and processes the error.
You must catch errors that occur in asynchronous code invoked by route handlers or
middleware and pass them to Express for processing. For example:
```js
app.get('/', (req, res, next) => {
setTimeout(() => {
try {
throw new Error('BROKEN')
} catch (err) {
next(err)
}
}, 100)
})
```
The above example uses a `try...catch` block to catch errors in the
asynchronous code and pass them to Express. If the `try...catch`
block were omitted, Express would not catch the error since it is not part of the synchronous
handler code.
Use promises to avoid the overhead of the `try...catch` block or when using functions
that return promises. For example:
```js
app.get('/', (req, res, next) => {
Promise.resolve().then(() => {
throw new Error('BROKEN')
}).catch(next) // Errors will be passed to Express.
})
```
Since promises automatically catch both synchronous errors and rejected promises,
you can simply provide `next` as the final catch handler and Express will catch errors,
because the catch handler is given the error as the first argument.
You could also use a chain of handlers to rely on synchronous error
catching, by reducing the asynchronous code to something trivial. For example:
```js
app.get('/', [
function (req, res, next) {
fs.readFile('/maybe-valid-file', 'utf-8', (err, data) => {
res.locals.data = data
next(err)
})
},
function (req, res) {
res.locals.data = res.locals.data.split(',')[1]
res.send(res.locals.data)
}
])
```
The above example has a couple of trivial statements from the `readFile`
call. If `readFile` causes an error, then it passes the error to Express, otherwise you
quickly return to the world of synchronous error handling in the next handler
in the chain. Then, the example above tries to process the data. If this fails, then the
synchronous error handler will catch it. If you had done this processing inside
the `readFile` callback, then the application might exit and the Express error
handlers would not run.
Whichever method you use, if you want Express error handlers to be called in and the
application to survive, you must ensure that Express receives the error.
## The default error handler
Express comes with a built-in error handler that takes care of any errors that might be encountered in the app. This default error-handling middleware function is added at the end of the middleware function stack.
If you pass an error to `next()` and you do not handle it in a custom error
handler, it will be handled by the built-in error handler; the error will be
written to the client with the stack trace. The stack trace is not included
in the production environment.
<div class="doc-box doc-info" markdown="1">
Set the environment variable `NODE_ENV` to `production`, to run the app in production mode.
</div>
When an error is written, the following information is added to the
response:
* The `res.statusCode` is set from `err.status` (or `err.statusCode`). If
this value is outside the 4xx or 5xx range, it will be set to 500.
* The `res.statusMessage` is set according to the status code.
* The body will be the HTML of the status code message when in production
environment, otherwise will be `err.stack`.
* Any headers specified in an `err.headers` object.
If you call `next()` with an error after you have started writing the
response (for example, if you encounter an error while streaming the
response to the client), the Express default error handler closes the
connection and fails the request.
So when you add a custom error handler, you must delegate to
the default Express error handler, when the headers
have already been sent to the client:
```js
function errorHandler (err, req, res, next) {
if (res.headersSent) {
return next(err)
}
res.status(500)
res.render('error', { error: err })
}
```
Note that the default error handler can get triggered if you call `next()` with an error
in your code more than once, even if custom error handling middleware is in place.
Other error handling middleware can be found at [Express middleware](/{{ page.lang }}/resources/middleware.html).
## Writing error handlers
Define error-handling middleware functions in the same way as other middleware functions,
except error-handling functions have four arguments instead of three:
`(err, req, res, next)`. For example:
```js
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
```
You define error-handling middleware last, after other `app.use()` and routes calls; for example:
```js
const bodyParser = require('body-parser')
const methodOverride = require('method-override')
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(bodyParser.json())
app.use(methodOverride())
app.use((err, req, res, next) => {
// logic
})
```
Responses from within a middleware function can be in any format, such as an HTML error page, a simple message, or a JSON string.
For organizational (and higher-level framework) purposes, you can define
several error-handling middleware functions, much as you would with
regular middleware functions. For example, to define an error-handler
for requests made by using `XHR` and those without:
```js
const bodyParser = require('body-parser')
const methodOverride = require('method-override')
app.use(bodyParser.urlencoded({
extended: true
}))
app.use(bodyParser.json())
app.use(methodOverride())
app.use(logErrors)
app.use(clientErrorHandler)
app.use(errorHandler)
```
In this example, the generic `logErrors` might write request and
error information to `stderr`, for example:
```js
function logErrors (err, req, res, next) {
console.error(err.stack)
next(err)
}
```
Also in this example, `clientErrorHandler` is defined as follows; in this case, the error is explicitly passed along to the next one.
Notice that when _not_ calling "next" in an error-handling function, you are responsible for writing (and ending) the response. Otherwise, those requests will "hang" and will not be eligible for garbage collection.
```js
function clientErrorHandler (err, req, res, next) {
if (req.xhr) {
res.status(500).send({ error: 'Something failed!' })
} else {
next(err)
}
}
```
Implement the "catch-all" `errorHandler` function as follows (for example):
```js
function errorHandler (err, req, res, next) {
res.status(500)
res.render('error', { error: err })
}
```
If you have a route handler with multiple callback functions, you can use the `route` parameter to skip to the next route handler. For example:
```js
app.get('/a_route_behind_paywall',
(req, res, next) => {
if (!req.user.hasPaid) {
// continue handling this request
next('route')
} else {
next()
}
}, (req, res, next) => {
PaidContent.find((err, doc) => {
if (err) return next(err)
res.json(doc)
})
})
```
In this example, the `getPaidContent` handler will be skipped but any remaining handlers in `app` for `/a_route_behind_paywall` would continue to be executed.
<div class="doc-box doc-info" markdown="1">
Calls to `next()` and `next(err)` indicate that the current handler is complete and in what state. `next(err)` will skip all remaining handlers in the chain except for those that are set up to handle errors as described above.
</div>

606
id/guide/migrating-4.md Executable file
View File

@@ -0,0 +1,606 @@
---
layout: page
title: Migrating to Express 4
menu: guide
lang: id
---
# Moving to Express 4
<h2 id="overview">Overview</h2>
Express 4 is a breaking change from Express 3. That means an existing Express 3 app will _not_ work if you update the Express version in its dependencies.
This article covers:
<ul class="doclist">
<li><a href="#changes">Changes in Express 4</a>.</li>
<li><a href="#example-migration">An example</a> of migrating an Express 3 app to Express 4.</li>
<li><a href="#app-gen">Upgrading to the Express 4 app generator</a>.</li>
</ul>
<h2 id="changes">Changes in Express 4</h2>
There are several significant changes in Express 4:
<ul class="doclist">
<li><a href="#core-changes">Changes to Express core and middleware system.</a> The dependencies on Connect and built-in middleware were removed, so you must add middleware yourself.
</li>
<li><a href="#routing">Changes to the routing system.</a></li>
<li><a href="#other-changes">Various other changes.</a></li>
</ul>
See also:
* [New features in 4.x.](https://github.com/expressjs/express/wiki/New-features-in-4.x)
* [Migrating from 3.x to 4.x.](https://github.com/expressjs/express/wiki/Migrating-from-3.x-to-4.x)
<h3 id="core-changes">
Changes to Express core and middleware system
</h3>
Express 4 no longer depends on Connect, and removes all built-in
middleware from its core, except for the `express.static` function. This means that
Express is now an independent routing and middleware web framework, and
Express versioning and releases are not affected by middleware updates.
Without built-in middleware, you must explicitly add all the
middleware that is required to run your app. Simply follow these steps:
1. Install the module: `npm install --save <module-name>`
2. In your app, require the module: `require('module-name')`
3. Use the module according to its documentation: `app.use( ... )`
The following table lists Express 3 middleware and their counterparts in Express 4.
<table class="doctable" border="1">
<tr><th>Express 3</th><th>Express 4</th></tr>
<tr><td><code>express.bodyParser</code></td>
<td><a href="https://github.com/expressjs/body-parser">body-parser</a> +
<a href="https://github.com/expressjs/multer">multer</a></td></tr>
<tr><td><code>express.compress</code></td>
<td><a href="https://github.com/expressjs/compression">compression</a></td></tr>
<tr><td><code>express.cookieSession</code></td>
<td><a href="https://github.com/expressjs/cookie-session">cookie-session</a></td></tr>
<tr><td><code>express.cookieParser</code></td>
<td><a href="https://github.com/expressjs/cookie-parser">cookie-parser</a></td></tr>
<tr><td><code>express.logger</code></td>
<td><a href="https://github.com/expressjs/morgan">morgan</a></td></tr>
<tr><td><code>express.session</code></td>
<td><a href="https://github.com/expressjs/session">express-session</a></td></tr>
<tr><td><code>express.favicon</code></td>
<td><a href="https://github.com/expressjs/serve-favicon">serve-favicon</a></td></tr>
<tr><td><code>express.responseTime</code></td>
<td><a href="https://github.com/expressjs/response-time">response-time</a></td></tr>
<tr><td><code>express.errorHandler</code></td>
<td><a href="https://github.com/expressjs/errorhandler">errorhandler</a></td></tr>
<tr><td><code>express.methodOverride</code></td>
<td><a href="https://github.com/expressjs/method-override">method-override</a></td></tr>
<tr><td><code>express.timeout</code></td>
<td><a href="https://github.com/expressjs/timeout">connect-timeout</a></td></tr>
<tr><td><code>express.vhost</code></td>
<td><a href="https://github.com/expressjs/vhost">vhost</a></td></tr>
<tr><td><code>express.csrf</code></td>
<td><a href="https://github.com/expressjs/csurf">csurf</a></td></tr>
<tr><td><code>express.directory</code></td>
<td><a href="https://github.com/expressjs/serve-index">serve-index</a></td></tr>
<tr><td><code>express.static</code></td>
<td><a href="https://github.com/expressjs/serve-static">serve-static</a></td></tr>
</table>
Here is the [complete list](https://github.com/senchalabs/connect#middleware) of Express 4 middleware.
In most cases, you can simply replace the old version 3 middleware with
its Express 4 counterpart. For details, see the module documentation in
GitHub.
<h4 id="app-use"><code>app.use</code> accepts parameters</h4>
In version 4 you can use a variable parameter to define the path where middleware functions are loaded, then read the value of the parameter from the route handler.
For example:
```js
app.use('/book/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
})
```
<h3 id="routing">
The routing system
</h3>
Apps now implicitly load routing middleware, so you no longer have to
worry about the order in which middleware is loaded with respect to
the `router` middleware.
The way you define routes is unchanged, but the routing system has two
new features to help organize your routes:
{: .doclist }
* A new method, `app.route()`, to create chainable route handlers for a route path.
* A new class, `express.Router`, to create modular mountable route handlers.
<h4 id="app-route"><code>app.route()</code> method</h4>
The new `app.route()` method enables you to create chainable route handlers
for a route path. Because the path is specified in a single location, creating modular routes is helpful, as is reducing redundancy and typos. For more
information about routes, see [`Router()` documentation](/{{ page.lang }}/4x/api.html#router).
Here is an example of chained route handlers that are defined by using the `app.route()` function.
```js
app.route('/book')
.get((req, res) => {
res.send('Get a random book')
})
.post((req, res) => {
res.send('Add a book')
})
.put((req, res) => {
res.send('Update the book')
})
```
<h4 id="express-router"><code>express.Router</code> class</h4>
The other feature that helps to organize routes is a new class,
`express.Router`, that you can use to create modular mountable
route handlers. A `Router` instance is a complete middleware and
routing system; for this reason it is often referred to as a "mini-app".
The following example creates a router as a module, loads middleware in
it, defines some routes, and mounts it on a path on the main app.
For example, create a router file named `birds.js` in the app directory,
with the following content:
```js
var express = require('express')
var router = express.Router()
// middleware specific to this router
router.use((req, res, next) => {
console.log('Time: ', Date.now())
next()
})
// define the home page route
router.get('/', (req, res) => {
res.send('Birds home page')
})
// define the about route
router.get('/about', (req, res) => {
res.send('About birds')
})
module.exports = router
```
Then, load the router module in the app:
```js
var birds = require('./birds')
// ...
app.use('/birds', birds)
```
The app will now be able to handle requests to the `/birds` and
`/birds/about` paths, and will call the `timeLog`
middleware that is specific to the route.
<h3 id="other-changes">
Other changes
</h3>
The following table lists other small but important changes in Express 4:
<table class="doctable" border="1">
<tr>
<th>Object</th>
<th>Description</th>
</tr>
<tr>
<td>Node.js</td>
<td>Express 4 requires Node.js 0.10.x or later and has dropped support for
Node.js 0.8.x.</td>
</tr>
<tr>
<td markdown="1">
`http.createServer()`
</td>
<td markdown="1">
The `http` module is no longer needed, unless you need to directly work with it (socket.io/SPDY/HTTPS). The app can be started by using the
`app.listen()` function.
</td>
</tr>
<tr>
<td markdown="1">
`app.configure()`
</td>
<td markdown="1">
The `app.configure()` function has been removed. Use the
`process.env.NODE_ENV` or
`app.get('env')` function to detect the environment and configure the app accordingly.
</td>
</tr>
<tr>
<td markdown="1">
`json spaces`
</td>
<td markdown="1">
The `json spaces` application property is disabled by default in Express 4.
</td>
</tr>
<tr>
<td markdown="1">
`req.accepted()`
</td>
<td markdown="1">
Use `req.accepts()`, `req.acceptsEncodings()`,
`req.acceptsCharsets()`, and `req.acceptsLanguages()`.
</td>
</tr>
<tr>
<td markdown="1">
`res.location()`
</td>
<td markdown="1">
No longer resolves relative URLs.
</td>
</tr>
<tr>
<td markdown="1">
`req.params`
</td>
<td markdown="1">
Was an array; now an object.
</td>
</tr>
<tr>
<td markdown="1">
`res.locals`
</td>
<td markdown="1">
Was a function; now an object.
</td>
</tr>
<tr>
<td markdown="1">
`res.headerSent`
</td>
<td markdown="1">
Changed to `res.headersSent`.
</td>
</tr>
<tr>
<td markdown="1">
`app.route`
</td>
<td markdown="1">
Now available as `app.mountpath`.
</td>
</tr>
<tr>
<td markdown="1">
`res.on('header')`
</td>
<td markdown="1">
Removed.
</td>
</tr>
<tr>
<td markdown="1">
`res.charset`
</td>
<td markdown="1">
Removed.
</td>
</tr>
<tr>
<td markdown="1">
`res.setHeader('Set-Cookie', val)`
</td>
<td markdown="1">
Functionality is now limited to setting the basic cookie value. Use
`res.cookie()` for added functionality.
</td>
</tr>
</table>
<h2 id="example-migration">Example app migration</h2>
Here is an example of migrating an Express 3 application to Express 4.
The files of interest are `app.js` and `package.json`.
<h3 id="">
Version 3 app
</h3>
<h4 id=""><code>app.js</code></h4>
Consider an Express v.3 application with the following `app.js` file:
```js
var express = require('express')
var routes = require('./routes')
var user = require('./routes/user')
var http = require('http')
var path = require('path')
var app = express()
// all environments
app.set('port', process.env.PORT || 3000)
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.use(express.favicon())
app.use(express.logger('dev'))
app.use(express.methodOverride())
app.use(express.session({ secret: 'your secret here' }))
app.use(express.bodyParser())
app.use(app.router)
app.use(express.static(path.join(__dirname, 'public')))
// development only
if (app.get('env') === 'development') {
app.use(express.errorHandler())
}
app.get('/', routes.index)
app.get('/users', user.list)
http.createServer(app).listen(app.get('port'), () => {
console.log('Express server listening on port ' + app.get('port'))
})
```
<h4 id=""><code>package.json</code></h4>
The accompanying version 3 `package.json` file might look
something like this:
```json
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"express": "3.12.0",
"pug": "*"
}
}
```
<h3 id="">
Process
</h3>
Begin the migration process by installing the required middleware for the
Express 4 app and updating Express and Pug to their respective latest
version with the following command:
```console
$ npm install serve-favicon morgan method-override express-session body-parser multer errorhandler express@latest pug@latest --save
```
Make the following changes to `app.js`:
1. The built-in Express middleware functions `express.favicon`,
`express.logger`, `express.methodOverride`,
`express.session`, `express.bodyParser` and
`express.errorHandler` are no longer available on the
`express` object. You must install their alternatives
manually and load them in the app.
2. You no longer need to load the `app.router` function.
It is not a valid Express 4 app object, so remove the
`app.use(app.router);` code.
3. Make sure that the middleware functions are loaded in the correct order - load `errorHandler` after loading the app routes.
<h3 id="">Version 4 app</h3>
<h4 id=""><code>package.json</code></h4>
Running the above `npm` command will update `package.json` as follows:
```json
{
"name": "application-name",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node app.js"
},
"dependencies": {
"body-parser": "^1.5.2",
"errorhandler": "^1.1.1",
"express": "^4.8.0",
"express-session": "^1.7.2",
"pug": "^2.0.0",
"method-override": "^2.1.2",
"morgan": "^1.2.2",
"multer": "^0.1.3",
"serve-favicon": "^2.0.1"
}
}
```
<h4 id=""><code>app.js</code></h4>
Then, remove invalid code, load the required middleware, and make other
changes as necessary. The `app.js` file will look like this:
```js
var http = require('http')
var express = require('express')
var routes = require('./routes')
var user = require('./routes/user')
var path = require('path')
var favicon = require('serve-favicon')
var logger = require('morgan')
var methodOverride = require('method-override')
var session = require('express-session')
var bodyParser = require('body-parser')
var multer = require('multer')
var errorHandler = require('errorhandler')
var app = express()
// all environments
app.set('port', process.env.PORT || 3000)
app.set('views', path.join(__dirname, 'views'))
app.set('view engine', 'pug')
app.use(favicon(path.join(__dirname, '/public/favicon.ico')))
app.use(logger('dev'))
app.use(methodOverride())
app.use(session({
resave: true,
saveUninitialized: true,
secret: 'uwotm8'
}))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))
app.use(multer())
app.use(express.static(path.join(__dirname, 'public')))
app.get('/', routes.index)
app.get('/users', user.list)
// error handling middleware should be loaded after the loading the routes
if (app.get('env') === 'development') {
app.use(errorHandler())
}
var server = http.createServer(app)
server.listen(app.get('port'), () => {
console.log('Express server listening on port ' + app.get('port'))
})
```
<div class="doc-box doc-info" markdown="1">
Unless you need to work directly with the `http` module (socket.io/SPDY/HTTPS), loading it is not required, and the app can be simply started this way:
```js
app.listen(app.get('port'), () => {
console.log('Express server listening on port ' + app.get('port'))
})
```
</div>
<h3 id="">Run the app</h3>
The migration process is complete, and the app is now an
Express 4 app. To confirm, start the app by using the following command:
```console
$ node .
```
Load [http://localhost:3000](http://localhost:3000)
and see the home page being rendered by Express 4.
<h2 id="app-gen">Upgrading to the Express 4 app generator</h2>
The command-line tool to generate an Express app is still
`express`, but to upgrade to the new version, you must uninstall
the Express 3 app generator and then install the new
`express-generator`.
<h3 id="">Installing </h3>
If you already have the Express 3 app generator installed on your system,
you must uninstall it:
```console
$ npm uninstall -g express
```
Depending on how your file and directory privileges are configured,
you might need to run this command with `sudo`.
Now install the new generator:
```console
$ npm install -g express-generator
```
Depending on how your file and directory privileges are configured,
you might need to run this command with `sudo`.
Now the `express` command on your system is updated to the
Express 4 generator.
<h3 id="">Changes to the app generator </h3>
Command options and use largely remain the same, with the following exceptions:
{: .doclist }
* Removed the `--sessions` option.
* Removed the `--jshtml` option.
* Added the `--hogan` option to support [Hogan.js](http://twitter.github.io/hogan.js/).
<h3 id="">Example</h3>
Execute the following command to create an Express 4 app:
```console
$ express app4
```
If you look at the contents of the `app4/app.js` file, you will notice
that all the middleware functions (except `express.static`) that are required for
the app are loaded as independent modules, and the `router` middleware
is no longer explicitly loaded in the app.
You will also notice that the `app.js` file is now a Node.js module, in contrast to the standalone app that was generated by the old generator.
After installing the dependencies, start the app by using the following command:
```console
$ npm start
```
If you look at the `npm start` script in the `package.json` file,
you will notice that the actual command that starts the app is
`node ./bin/www`, which used to be `node app.js`
in Express 3.
Because the `app.js` file that was generated by the Express 4 generator
is now a Node.js module, it can no longer be started independently as an app
(unless you modify the code). The module must be loaded in a Node.js file
and started via the Node.js file. The Node.js file is `./bin/www`
in this case.
Neither the `bin` directory nor the extensionless `www`
file is mandatory for creating an Express app or starting the app. They are
just suggestions made by the generator, so feel free to modify them to suit your
needs.
To get rid of the `www` directory and keep things the "Express 3 way",
delete the line that says `module.exports = app;` at the end of the
`app.js` file, then paste the following code in its place:
```js
app.set('port', process.env.PORT || 3000)
var server = app.listen(app.get('port'), () => {
debug('Express server listening on port ' + server.address().port)
})
```
Ensure that you load the `debug` module at the top of the `app.js` file by using the following code:
```js
var debug = require('debug')('app4')
```
Next, change `"start": "node ./bin/www"` in the `package.json` file to `"start": "node app.js"`.
You have now moved the functionality of `./bin/www` back to
`app.js`. This change is not recommended, but the exercise helps you
to understand how the `./bin/www` file works, and why the `app.js` file
no longer starts on its own.

147
id/guide/migrating-5.md Executable file
View File

@@ -0,0 +1,147 @@
---
layout: page
title: Migrating to Express 5
menu: guide
lang: id
---
# Moving to Express 5
<h2 id="overview">Overview</h2>
Express 5.0 is still in the beta release stage, but here is a preview of the changes that will be in the release and how to migrate your Express 4 app to Express 5.
To install the latest beta and to preview Express 5, enter the following command in your application root directory:
```console
$ npm install "express@>=5.0.0-beta.1" --save
```
You can then run your automated tests to see what fails, and fix problems according to the updates listed below. After addressing test failures, run your app to see what errors occur. You'll find out right away if the app uses any methods or properties that are not supported.
<h2 id="changes">Changes in Express 5</h2>
**Removed methods and properties**
<ul class="doclist">
<li><a href="#app.del">app.del()</a></li>
<li><a href="#app.param">app.param(fn)</a></li>
<li><a href="#plural">Pluralized method names</a></li>
<li><a href="#leading">Leading colon in name argument to app.param(name, fn)</a></li>
<li><a href="#req.param">req.param(name)</a></li>
<li><a href="#res.json">res.json(obj, status)</a></li>
<li><a href="#res.jsonp">res.jsonp(obj, status)</a></li>
<li><a href="#res.send.body">res.send(body, status)</a></li>
<li><a href="#res.send.status">res.send(status)</a></li>
<li><a href="#res.sendfile">res.sendfile()</a></li>
</ul>
**Changed**
<ul class="doclist">
<li><a href="#path-syntax">Path route matching syntax</a></li>
<li><a href="#rejected-promises">Rejected promises handled from middleware and handlers</a></li>
<li><a href="#app.router">app.router</a></li>
<li><a href="#req.host">req.host</a></li>
<li><a href="#req.query">req.query</a></li>
</ul>
**Improvements**
<ul class="doclist">
<li><a href="#res.render">res.render()</a></li>
</ul>
<h3>Removed methods and properties</h3>
If you use any of these methods or properties in your app, it will crash. So, you'll need to change your app after you update to version 5.
<h4 id="app.del">app.del()</h4>
Express 5 no longer supports the `app.del()` function. If you use this function, an error is thrown. For registering HTTP DELETE routes, use the `app.delete()` function instead.
Initially, `del` was used instead of `delete`, because `delete` is a reserved keyword in JavaScript. However, as of ECMAScript 6, `delete` and other reserved keywords can legally be used as property names.
<h4 id="app.param">app.param(fn)</h4>
The `app.param(fn)` signature was used for modifying the behavior of the `app.param(name, fn)` function. It has been deprecated since v4.11.0, and Express 5 no longer supports it at all.
<h4 id="plural">Pluralized method names</h4>
The following method names have been pluralized. In Express 4, using the old methods resulted in a deprecation warning. Express 5 no longer supports them at all:
`req.acceptsCharset()` is replaced by `req.acceptsCharsets()`.
`req.acceptsEncoding()` is replaced by `req.acceptsEncodings()`.
`req.acceptsLanguage()` is replaced by `req.acceptsLanguages()`.
<h4 id="leading">Leading colon (:) in the name for app.param(name, fn)</h4>
A leading colon character (:) in the name for the `app.param(name, fn)` function is a remnant of Express 3, and for the sake of backwards compatibility, Express 4 supported it with a deprecation notice. Express 5 will silently ignore it and use the name parameter without prefixing it with a colon.
This should not affect your code if you follow the Express 4 documentation of [app.param](/{{ page.lang }}/4x/api.html#app.param), as it makes no mention of the leading colon.
<h4 id="req.param">req.param(name)</h4>
This potentially confusing and dangerous method of retrieving form data has been removed. You will now need to specifically look for the submitted parameter name in the `req.params`, `req.body`, or `req.query` object.
<h4 id="res.json">res.json(obj, status)</h4>
Express 5 no longer supports the signature `res.json(obj, status)`. Instead, set the status and then chain it to the `res.json()` method like this: `res.status(status).json(obj)`.
<h4 id="res.jsonp">res.jsonp(obj, status)</h4>
Express 5 no longer supports the signature `res.jsonp(obj, status)`. Instead, set the status and then chain it to the `res.jsonp()` method like this: `res.status(status).jsonp(obj)`.
<h4 id="res.send.body">res.send(body, status)</h4>
Express 5 no longer supports the signature `res.send(obj, status)`. Instead, set the status and then chain it to the `res.send()` method like this: `res.status(status).send(obj)`.
<h4 id="res.send.status">res.send(status)</h4>
Express 5 no longer supports the signature <code>res.send(<em>status</em>)</code>, where _`status`_ is a number. Instead, use the `res.sendStatus(statusCode)` function, which sets the HTTP response header status code and sends the text version of the code: "Not Found", "Internal Server Error", and so on.
If you need to send a number by using the `res.send()` function, quote the number to convert it to a string, so that Express does not interpret it as an attempt to use the unsupported old signature.
<h4 id="res.sendfile">res.sendfile()</h4>
The `res.sendfile()` function has been replaced by a camel-cased version `res.sendFile()` in Express 5.
<h3>Changed</h3>
<h4 id="path-syntax">Path route matching syntax</h4>
Path route matching syntax is when a string is supplied as the first parameter to the `app.all()`, `app.use()`, `app.METHOD()`, `router.all()`, `router.METHOD()`, and `router.use()` APIs. The following changes have been made to how the path string is matched to an incoming request:
- Add new `?`, `*`, and `+` parameter modifiers.
- Matching group expressions are only RegExp syntax.
* `(*)` is no longer valid and must be written as `(.*)`, for example.
- Named matching groups no longer available by position in `req.params`.
* `/:foo(.*)` only captures as `req.params.foo` and not available as `req.params[0]`.
- Regular expressions can only be used in a matching group.
* `/\\d+` is no longer valid and must be written as `/(\\d+)`.
- Special `*` path segment behavior removed.
* `/foo/*/bar` will match a literal `*` as the middle segment.
<h4 id="rejected-promises">Rejected promises handled from middleware and handlers</h4>
Request middleware and handlers that return rejected promises are now handled by forwarding the rejected value as an `Error` to the error handling middleware. This means that using `async` functions as middleware and handlers are easier than ever. When an error is thrown in an `async` function or a rejected promise is `await`ed inside an async function, those errors will be passed to the error handler as if calling `next(err)`.
Details of how Express handles errors is covered in the [error handling documentation](/en/guide/error-handling.html).
<h4 id="app.router">app.router</h4>
The `app.router` object, which was removed in Express 4, has made a comeback in Express 5. In the new version, this object is a just a reference to the base Express router, unlike in Express 3, where an app had to explicitly load it.
<h4 id="req.host">req.host</h4>
In Express 4, the `req.host` function incorrectly stripped off the port number if it was present. In Express 5, the port number is maintained.
<h4 id="req.query">req.query</h4>
The `req.query` property is no longer a writable property and is instead a getter. The default query parser has been changed from "extended" to "simple".
<h3>Improvements</h3>
<h4 id="res.render">res.render()</h4>
This method now enforces asynchronous behavior for all view engines, avoiding bugs caused by view engines that had a synchronous implementation and that violated the recommended interface.

View File

@@ -0,0 +1,74 @@
---
layout: page
title: Overriding the Express API
menu: guide
lang: id
---
<div id="page-doc" markdown="1">
# Overriding the Express API
The Express API consists of various methods and properties on the request and response objects. These are inherited by prototype. There are two extension points for the Express API:
1. The global prototypes at `express.request` and `express.response`.
2. App-specific prototypes at `app.request` and `app.response`.
Altering the global prototypes will affect all loaded Express apps in the same process. If desired, alterations can be made app-specific by only altering the app-specific prototypes after creating a new app.
## Methods
You can override the signature and behavior of existing methods with your own, by assigning a custom function.
Following is an example of overriding the behavior of [res.sendStatus](/4x/api.html#res.sendStatus).
```js
app.response.sendStatus = function (statusCode, type, message) {
// code is intentionally kept simple for demonstration purpose
return this.contentType(type)
.status(statusCode)
.send(message)
}
```
The above implementation completely changes the original signature of `res.sendStatus`. It now accepts a status code, encoding type, and the message to be sent to the client.
The overridden method may now be used this way:
```js
res.sendStatus(404, 'application/json', '{"error":"resource not found"}')
```
## Properties
Properties in the Express API are either:
1. Assigned properties (ex: `req.baseUrl`, `req.originalUrl`)
2. Defined as getters (ex: `req.secure`, `req.ip`)
Since properties under category 1 are dynamically assigned on the `request` and `response` objects in the context of the current request-response cycle, their behavior cannot be overridden.
Properties under category 2 can be overwritten using the Express API extensions API.
The following code rewrites how the value of `req.ip` is to be derived. Now, it simply returns the value of the `Client-IP` request header.
```js
Object.defineProperty(app.request, 'ip', {
configurable: true,
enumerable: true,
get () { return this.get('Client-IP') }
})
```
## Prototype
In order to provide the Express API, the request/response objects passed to Express (via `app(req, res)`, for example) need to inherit from the same prototype chain. By default, this is `http.IncomingRequest.prototype` for the request and `http.ServerResponse.prototype` for the response.
Unless necessary, it is recommended that this be done only at the application level, rather than globally. Also, take care that the prototype that is being used matches the functionality as closely as possible to the default prototypes.
```js
// Use FakeRequest and FakeResponse in place of http.IncomingRequest and http.ServerResponse
// for the given app reference
Object.setPrototypeOf(Object.getPrototypeOf(app.request), FakeRequest.prototype)
Object.setPrototypeOf(Object.getPrototypeOf(app.response), FakeResponse.prototype)
```
</div>

355
id/guide/routing.md Executable file
View File

@@ -0,0 +1,355 @@
---
layout: page
title: Express routing
menu: guide
lang: id
---
# Routing
_Routing_ refers to how an application's endpoints (URIs) respond to client requests.
For an introduction to routing, see [Basic routing](/{{ page.lang }}/starter/basic-routing.html).
You define routing using methods of the Express `app` object that correspond to HTTP methods;
for example, `app.get()` to handle GET requests and `app.post` to handle POST requests. For a full list,
see [app.METHOD](/{{ page.lang }}/4x/api.html#app.METHOD). You can also use [app.all()](/{{ page.lang }}/4x/api.html#app.all) to handle all HTTP methods and [app.use()](/{{ page.lang }}/4x/api.html#app.use) to
specify middleware as the callback function (See [Using middleware](/{{ page.lang }}/guide/using-middleware.html) for details).
These routing methods specify a callback function (sometimes called "handler functions") called when the application receives a request to the specified route (endpoint) and HTTP method. In other words, the application "listens" for requests that match the specified route(s) and method(s), and when it detects a match, it calls the specified callback function.
In fact, the routing methods can have more than one callback function as arguments.
With multiple callback functions, it is important to provide `next` as an argument to the callback function and then call `next()` within the body of the function to hand off control
to the next callback.
The following code is an example of a very basic route.
```js
const express = require('express')
const app = express()
// respond with "hello world" when a GET request is made to the homepage
app.get('/', (req, res) => {
res.send('hello world')
})
```
<h2 id="route-methods">Route methods</h2>
A route method is derived from one of the HTTP methods, and is attached to an instance of the `express` class.
The following code is an example of routes that are defined for the GET and the POST methods to the root of the app.
```js
// GET method route
app.get('/', (req, res) => {
res.send('GET request to the homepage')
})
// POST method route
app.post('/', (req, res) => {
res.send('POST request to the homepage')
})
```
Express supports methods that correspond to all HTTP request methods: `get`, `post`, and so on.
For a full list, see [app.METHOD](/{{ page.lang }}/4x/api.html#app.METHOD).
There is a special routing method, `app.all()`, used to load middleware functions at a path for _all_ HTTP request methods. For example, the following handler is executed for requests to the route "/secret" whether using GET, POST, PUT, DELETE, or any other HTTP request method supported in the [http module](https://nodejs.org/api/http.html#http_http_methods).
```js
app.all('/secret', (req, res, next) => {
console.log('Accessing the secret section ...')
next() // pass control to the next handler
})
```
<h2 id="route-paths">Route paths</h2>
Route paths, in combination with a request method, define the endpoints at which requests can be made. Route paths can be strings, string patterns, or regular expressions.
The characters `?`, `+`, `*`, and `()` are subsets of their regular expression counterparts. The hyphen (`-`) and the dot (`.`) are interpreted literally by string-based paths.
If you need to use the dollar character (`$`) in a path string, enclose it escaped within `([` and `])`. For example, the path string for requests at "`/data/$book`", would be "`/data/([\$])book`".
<div class="doc-box doc-info" markdown="1">
Express uses [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) for matching the route paths; see the path-to-regexp documentation for all the possibilities in defining route paths. [Express Route Tester](http://forbeslindesay.github.io/express-route-tester/) is a handy tool for testing basic Express routes, although it does not support pattern matching.
</div>
<div class="doc-box doc-warn" markdown="1">
Query strings are not part of the route path.
</div>
Here are some examples of route paths based on strings.
This route path will match requests to the root route, `/`.
```js
app.get('/', (req, res) => {
res.send('root')
})
```
This route path will match requests to `/about`.
```js
app.get('/about', (req, res) => {
res.send('about')
})
```
This route path will match requests to `/random.text`.
```js
app.get('/random.text', (req, res) => {
res.send('random.text')
})
```
Here are some examples of route paths based on string patterns.
This route path will match `acd` and `abcd`.
```js
app.get('/ab?cd', (req, res) => {
res.send('ab?cd')
})
```
This route path will match `abcd`, `abbcd`, `abbbcd`, and so on.
```js
app.get('/ab+cd', (req, res) => {
res.send('ab+cd')
})
```
This route path will match `abcd`, `abxcd`, `abRANDOMcd`, `ab123cd`, and so on.
```js
app.get('/ab*cd', (req, res) => {
res.send('ab*cd')
})
```
This route path will match `/abe` and `/abcde`.
```js
app.get('/ab(cd)?e', (req, res) => {
res.send('ab(cd)?e')
})
```
Examples of route paths based on regular expressions:
This route path will match anything with an "a" in it.
```js
app.get(/a/, (req, res) => {
res.send('/a/')
})
```
This route path will match `butterfly` and `dragonfly`, but not `butterflyman`, `dragonflyman`, and so on.
```js
app.get(/.*fly$/, (req, res) => {
res.send('/.*fly$/')
})
```
<h2 id="route-parameters">Route parameters</h2>
Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the `req.params` object, with the name of the route parameter specified in the path as their respective keys.
```
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
```
To define routes with route parameters, simply specify the route parameters in the path of the route as shown below.
```js
app.get('/users/:userId/books/:bookId', (req, res) => {
res.send(req.params)
})
```
<div class="doc-box doc-notice" markdown="1">
The name of route parameters must be made up of "word characters" ([A-Za-z0-9_]).
</div>
Since the hyphen (`-`) and the dot (`.`) are interpreted literally, they can be used along with route parameters for useful purposes.
```
Route path: /flights/:from-:to
Request URL: http://localhost:3000/flights/LAX-SFO
req.params: { "from": "LAX", "to": "SFO" }
```
```
Route path: /plantae/:genus.:species
Request URL: http://localhost:3000/plantae/Prunus.persica
req.params: { "genus": "Prunus", "species": "persica" }
```
To have more control over the exact string that can be matched by a route parameter, you can append a regular expression in parentheses (`()`):
```
Route path: /user/:userId(\d+)
Request URL: http://localhost:3000/user/42
req.params: {"userId": "42"}
```
<div class="doc-box doc-warn" markdown="1">
Because the regular expression is usually part of a literal string, be sure to escape any <code>\</code> characters with an additional backslash, for example <code>\\d+</code>.
</div>
<div class="doc-box doc-warn" markdown="1">
In Express 4.x, <a href="https://github.com/expressjs/express/issues/2495">the <code>*</code> character in regular expressions is not interpreted in the usual way</a>. As a workaround, use <code>{0,}</code> instead of <code>*</code>. This will likely be fixed in Express 5.
</div>
<h2 id="route-handlers">Route handlers</h2>
You can provide multiple callback functions that behave like [middleware](/{{ page.lang }}/guide/using-middleware.html) to handle a request. The only exception is that these callbacks might invoke `next('route')` to bypass the remaining route callbacks. You can use this mechanism to impose pre-conditions on a route, then pass control to subsequent routes if there's no reason to proceed with the current route.
Route handlers can be in the form of a function, an array of functions, or combinations of both, as shown in the following examples.
A single callback function can handle a route. For example:
```js
app.get('/example/a', (req, res) => {
res.send('Hello from A!')
})
```
More than one callback function can handle a route (make sure you specify the `next` object). For example:
```js
app.get('/example/b', (req, res, next) => {
console.log('the response will be sent by the next function ...')
next()
}, (req, res) => {
res.send('Hello from B!')
})
```
An array of callback functions can handle a route. For example:
```js
const cb0 = function (req, res, next) {
console.log('CB0')
next()
}
const cb1 = function (req, res, next) {
console.log('CB1')
next()
}
const cb2 = function (req, res) {
res.send('Hello from C!')
}
app.get('/example/c', [cb0, cb1, cb2])
```
A combination of independent functions and arrays of functions can handle a route. For example:
```js
const cb0 = function (req, res, next) {
console.log('CB0')
next()
}
const cb1 = function (req, res, next) {
console.log('CB1')
next()
}
app.get('/example/d', [cb0, cb1], (req, res, next) => {
console.log('the response will be sent by the next function ...')
next()
}, (req, res) => {
res.send('Hello from D!')
})
```
<h2 id="response-methods">Response methods</h2>
The methods on the response object (`res`) in the following table can send a response to the client, and terminate the request-response cycle. If none of these methods are called from a route handler, the client request will be left hanging.
| Method | Description |
| --------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| [res.download()](/{{ page.lang }}/4x/api.html#res.download) | Prompt a file to be downloaded. |
| [res.end()](/{{ page.lang }}/4x/api.html#res.end) | End the response process. |
| [res.json()](/{{ page.lang }}/4x/api.html#res.json) | Send a JSON response. |
| [res.jsonp()](/{{ page.lang }}/4x/api.html#res.jsonp) | Send a JSON response with JSONP support. |
| [res.redirect()](/{{ page.lang }}/4x/api.html#res.redirect) | Redirect a request. |
| [res.render()](/{{ page.lang }}/4x/api.html#res.render) | Render a view template. |
| [res.send()](/{{ page.lang }}/4x/api.html#res.send) | Send a response of various types. |
| [res.sendFile()](/{{ page.lang }}/4x/api.html#res.sendFile) | Send a file as an octet stream. |
| [res.sendStatus()](/{{ page.lang }}/4x/api.html#res.sendStatus) | Set the response status code and send its string representation as the response body. |
<h2 id="app-route">app.route()</h2>
You can create chainable route handlers for a route path by using `app.route()`.
Because the path is specified at a single location, creating modular routes is helpful, as is reducing redundancy and typos. For more information about routes, see: [Router() documentation](/{{ page.lang }}/4x/api.html#router).
Here is an example of chained route handlers that are defined by using `app.route()`.
```js
app.route('/book')
.get((req, res) => {
res.send('Get a random book')
})
.post((req, res) => {
res.send('Add a book')
})
.put((req, res) => {
res.send('Update the book')
})
```
<h2 id="express-router">express.Router</h2>
Use the `express.Router` class to create modular, mountable route handlers. A `Router` instance is a complete middleware and routing system; for this reason, it is often referred to as a "mini-app".
The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.
Create a router file named `birds.js` in the app directory, with the following content:
```js
const express = require('express')
const router = express.Router()
// middleware that is specific to this router
const timeLog = (req, res, next) => {
console.log('Time: ', Date.now())
next()
}
router.use(timeLog)
// define the home page route
router.get('/', (req, res) => {
res.send('Birds home page')
})
// define the about route
router.get('/about', (req, res) => {
res.send('About birds')
})
module.exports = router
```
Then, load the router module in the app:
```js
const birds = require('./birds')
// ...
app.use('/birds', birds)
```
The app will now be able to handle requests to `/birds` and `/birds/about`, as well as call the `timeLog` middleware function that is specific to the route.

View File

@@ -0,0 +1,268 @@
---
layout: page
title: Using Express middleware
menu: guide
lang: id
---
# Using middleware
Express is a routing and middleware web framework that has minimal functionality of its own: An Express application is essentially a series of middleware function calls.
_Middleware_ functions are functions that have access to the [request object](/{{ page.lang }}/4x/api.html#req) (`req`), the [response object](/{{ page.lang }}/4x/api.html#res) (`res`), and the next middleware function in the application's request-response cycle. The next middleware function is commonly denoted by a variable named `next`.
Middleware functions can perform the following tasks:
* Execute any code.
* Make changes to the request and the response objects.
* End the request-response cycle.
* Call the next middleware function in the stack.
If the current middleware function does not end the request-response cycle, it must call `next()` to pass control to the next middleware function. Otherwise, the request will be left hanging.
An Express application can use the following types of middleware:
- [Application-level middleware](#middleware.application)
- [Router-level middleware](#middleware.router)
- [Error-handling middleware](#middleware.error-handling)
- [Built-in middleware](#middleware.built-in)
- [Third-party middleware](#middleware.third-party)
You can load application-level and router-level middleware with an optional mount path.
You can also load a series of middleware functions together, which creates a sub-stack of the middleware system at a mount point.
<h2 id='middleware.application'>Application-level middleware</h2>
Bind application-level middleware to an instance of the [app object](/{{ page.lang }}/4x/api.html#app) by using the `app.use()` and `app.METHOD()` functions, where `METHOD` is the HTTP method of the request that the middleware function handles (such as GET, PUT, or POST) in lowercase.
This example shows a middleware function with no mount path. The function is executed every time the app receives a request.
```js
const express = require('express')
const app = express()
app.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
```
This example shows a middleware function mounted on the `/user/:id` path. The function is executed for any type of
HTTP request on the `/user/:id` path.
```js
app.use('/user/:id', (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
```
This example shows a route and its handler function (middleware system). The function handles GET requests to the `/user/:id` path.
```js
app.get('/user/:id', (req, res, next) => {
res.send('USER')
})
```
Here is an example of loading a series of middleware functions at a mount point, with a mount path.
It illustrates a middleware sub-stack that prints request info for any type of HTTP request to the `/user/:id` path.
```js
app.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
```
Route handlers enable you to define multiple routes for a path. The example below defines two routes for GET requests to the `/user/:id` path. The second route will not cause any problems, but it will never get called because the first route ends the request-response cycle.
This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path.
```js
app.get('/user/:id', (req, res, next) => {
console.log('ID:', req.params.id)
next()
}, (req, res, next) => {
res.send('User Info')
})
// handler for the /user/:id path, which prints the user ID
app.get('/user/:id', (req, res, next) => {
res.send(req.params.id)
})
```
To skip the rest of the middleware functions from a router middleware stack, call `next('route')` to pass control to the next route.
**NOTE**: `next('route')` will work only in middleware functions that were loaded by using the `app.METHOD()` or `router.METHOD()` functions.
This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path.
```js
app.get('/user/:id', (req, res, next) => {
// if the user ID is 0, skip to the next route
if (req.params.id === '0') next('route')
// otherwise pass the control to the next middleware function in this stack
else next()
}, (req, res, next) => {
// send a regular response
res.send('regular')
})
// handler for the /user/:id path, which sends a special response
app.get('/user/:id', (req, res, next) => {
res.send('special')
})
```
Middleware can also be declared in an array for reusability.
This example shows an array with a middleware sub-stack that handles GET requests to the `/user/:id` path
```js
function logOriginalUrl (req, res, next) {
console.log('Request URL:', req.originalUrl)
next()
}
function logMethod (req, res, next) {
console.log('Request Type:', req.method)
next()
}
const logStuff = [logOriginalUrl, logMethod]
app.get('/user/:id', logStuff, (req, res, next) => {
res.send('User Info')
})
```
<h2 id='middleware.router'>Router-level middleware</h2>
Router-level middleware works in the same way as application-level middleware, except it is bound to an instance of `express.Router()`.
```js
const router = express.Router()
```
Load router-level middleware by using the `router.use()` and `router.METHOD()` functions.
The following example code replicates the middleware system that is shown above for application-level middleware, by using router-level middleware:
```js
const express = require('express')
const app = express()
const router = express.Router()
// a middleware function with no mount path. This code is executed for every request to the router
router.use((req, res, next) => {
console.log('Time:', Date.now())
next()
})
// a middleware sub-stack shows request info for any type of HTTP request to the /user/:id path
router.use('/user/:id', (req, res, next) => {
console.log('Request URL:', req.originalUrl)
next()
}, (req, res, next) => {
console.log('Request Type:', req.method)
next()
})
// a middleware sub-stack that handles GET requests to the /user/:id path
router.get('/user/:id', (req, res, next) => {
// if the user ID is 0, skip to the next router
if (req.params.id === '0') next('route')
// otherwise pass control to the next middleware function in this stack
else next()
}, (req, res, next) => {
// render a regular page
res.render('regular')
})
// handler for the /user/:id path, which renders a special page
router.get('/user/:id', (req, res, next) => {
console.log(req.params.id)
res.render('special')
})
// mount the router on the app
app.use('/', router)
```
To skip the rest of the router's middleware functions, call `next('router')`
to pass control back out of the router instance.
This example shows a middleware sub-stack that handles GET requests to the `/user/:id` path.
```js
const express = require('express')
const app = express()
const router = express.Router()
// predicate the router with a check and bail out when needed
router.use((req, res, next) => {
if (!req.headers['x-auth']) return next('router')
next()
})
router.get('/user/:id', (req, res) => {
res.send('hello, user!')
})
// use the router and 401 anything falling through
app.use('/admin', router, (req, res) => {
res.sendStatus(401)
})
```
<h2 id='middleware.error-handling'>Error-handling middleware</h2>
<div class="doc-box doc-notice" markdown="1">
Error-handling middleware always takes _four_ arguments. You must provide four arguments to identify it as an error-handling middleware function. Even if you don't need to use the `next` object, you must specify it to maintain the signature. Otherwise, the `next` object will be interpreted as regular middleware and will fail to handle errors.
</div>
Define error-handling middleware functions in the same way as other middleware functions, except with four arguments instead of three, specifically with the signature `(err, req, res, next)`:
```js
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Something broke!')
})
```
For details about error-handling middleware, see: [Error handling](/{{ page.lang }}/guide/error-handling.html).
<h2 id='middleware.built-in'>Built-in middleware</h2>
Starting with version 4.x, Express no longer depends on [Connect](https://github.com/senchalabs/connect). The middleware
functions that were previously included with Express are now in separate modules; see [the list of middleware functions](https://github.com/senchalabs/connect#middleware).
Express has the following built-in middleware functions:
- [express.static](/en/4x/api.html#express.static) serves static assets such as HTML files, images, and so on.
- [express.json](/en/4x/api.html#express.json) parses incoming requests with JSON payloads. **NOTE: Available with Express 4.16.0+**
- [express.urlencoded](/en/4x/api.html#express.urlencoded) parses incoming requests with URL-encoded payloads. **NOTE: Available with Express 4.16.0+**
<h2 id='middleware.third-party'>Third-party middleware</h2>
Use third-party middleware to add functionality to Express apps.
Install the Node.js module for the required functionality, then load it in your app at the application level or at the router level.
The following example illustrates installing and loading the cookie-parsing middleware function `cookie-parser`.
```console
$ npm install cookie-parser
```
```js
const express = require('express')
const app = express()
const cookieParser = require('cookie-parser')
// load the cookie-parsing middleware
app.use(cookieParser())
```
For a partial list of third-party middleware functions that are commonly used with Express, see: [Third-party middleware](../resources/middleware.html).

View File

@@ -0,0 +1,76 @@
---
layout: page
title: Using template engines with Express
menu: guide
lang: id
---
# Using template engines with Express
A _template engine_ enables you to use static template files in your application. At runtime, the template engine replaces
variables in a template file with actual values, and transforms the template into an HTML file sent to the client.
This approach makes it easier to design an HTML page.
Some popular template engines that work with Express are [Pug](https://pugjs.org/api/getting-started.html),
[Mustache](https://www.npmjs.com/package/mustache), and [EJS](https://www.npmjs.com/package/ejs).
The [Express application generator](/{{ page.lang }}/starter/generator.html) uses [Jade](https://www.npmjs.com/package/jade) as its default, but it also supports several others.
See [Template Engines (Express wiki)](https://github.com/expressjs/express/wiki#template-engines)
for a list of template engines you can use with Express.
See also [Comparing JavaScript Templating Engines: Jade, Mustache, Dust and More](https://strongloop.com/strongblog/compare-javascript-templates-jade-mustache-dust/).
<div class="doc-box doc-notice" markdown="1">
**Note**: Jade has been renamed to [Pug](https://www.npmjs.com/package/pug). You can continue to use Jade in your app, and it will work just fine. However if you want the latest updates to the template engine, you must replace Jade with Pug in your app.
</div>
To render template files, set the following [application setting properties](/{{ page.lang }}/4x/api.html#app.set), set in `app.js` in the default app created by the generator:
* `views`, the directory where the template files are located. Eg: `app.set('views', './views')`.
This defaults to the `views` directory in the application root directory.
* `view engine`, the template engine to use. For example, to use the Pug template engine: `app.set('view engine', 'pug')`.
Then install the corresponding template engine npm package; for example to install Pug:
```console
$ npm install pug --save
```
<div class="doc-box doc-notice" markdown="1">
Express-compliant template engines such as Jade and Pug export a function named `__express(filePath, options, callback)`,
which is called by the `res.render()` function to render the template code.
Some template engines do not follow this convention. The [Consolidate.js](https://www.npmjs.org/package/consolidate)
library follows this convention by mapping all of the popular Node.js template engines, and therefore works seamlessly within Express.
</div>
After the view engine is set, you don't have to specify the engine or load the template engine module in your app;
Express loads the module internally, as shown below (for the above example).
```js
app.set('view engine', 'pug')
```
Create a Pug template file named `index.pug` in the `views` directory, with the following content:
```pug
html
head
title= title
body
h1= message
```
Then create a route to render the `index.pug` file. If the `view engine` property is not set,
you must specify the extension of the `view` file. Otherwise, you can omit it.
```js
app.get('/', (req, res) => {
res.render('index', { title: 'Hey', message: 'Hello there!' })
})
```
When you make a request to the home page, the `index.pug` file will be rendered as HTML.
Note: The view engine cache does not cache the contents of the template's output, only the underlying template itself. The view is still re-rendered with every request even when the cache is on.
To learn more about how template engines work in Express, see:
["Developing template engines for Express"](/{{ page.lang }}/advanced/developing-template-engines.html).

217
id/guide/writing-middleware.md Executable file
View File

@@ -0,0 +1,217 @@
---
layout: page
title: Writing middleware for use in Express apps
menu: guide
lang: id
---
# Writing middleware for use in Express apps
<h2>Overview</h2>
_Middleware_ functions are functions that have access to the [request object](/{{ page.lang }}/4x/api.html#req) (`req`), the [response object](/{{ page.lang }}/4x/api.html#res) (`res`), and the `next` function in the application's request-response cycle. The `next` function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.
Middleware functions can perform the following tasks:
* Execute any code.
* Make changes to the request and the response objects.
* End the request-response cycle.
* Call the next middleware in the stack.
If the current middleware function does not end the request-response cycle, it must call `next()` to pass control to the next middleware function. Otherwise, the request will be left hanging.
The following figure shows the elements of a middleware function call:
<table id="mw-fig">
<tr><td id="mw-fig-imgcell">
<img src="/images/express-mw.png" id="mw-fig-img" />
</td>
<td class="mw-fig-callouts">
<div class="callout" id="callout1">HTTP method for which the middleware function applies.</div>
<div class="callout" id="callout2">Path (route) for which the middleware function applies.</div>
<div class="callout" id="callout3">The middleware function.</div>
<div class="callout" id="callout4">Callback argument to the middleware function, called "next" by convention.</div>
<div class="callout" id="callout5">HTTP <a href="/{{ page.lang }}/4x/api.html#res">response</a> argument to the middleware function, called "res" by convention.</div>
<div class="callout" id="callout6">HTTP <a href="/{{ page.lang }}/4x/api.html#req">request</a> argument to the middleware function, called "req" by convention.</div>
</td></tr>
</table>
Starting with Express 5, middleware functions that return a Promise will call `next(value)` when they reject or throw an error. `next` will be called with either the rejected value or the thrown Error.
<h2>Example</h2>
Here is an example of a simple "Hello World" Express application.
The remainder of this article will define and add three middleware functions to the application:
one called `myLogger` that prints a simple log message, one called `requestTime` that
displays the timestamp of the HTTP request, and one called `validateCookies` that validates incoming cookies.
```js
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000)
```
<h3>Middleware function myLogger</h3>
Here is a simple example of a middleware function called "myLogger". This function just prints "LOGGED" when a request to the app passes through it. The middleware function is assigned to a variable named `myLogger`.
```js
const myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
```
<div class="doc-box doc-notice" markdown="1">
Notice the call above to `next()`. Calling this function invokes the next middleware function in the app.
The `next()` function is not a part of the Node.js or Express API, but is the third argument that is passed to the middleware function. The `next()` function could be named anything, but by convention it is always named "next".
To avoid confusion, always use this convention.
</div>
To load the middleware function, call `app.use()`, specifying the middleware function.
For example, the following code loads the `myLogger` middleware function before the route to the root path (/).
```js
const express = require('express')
const app = express()
const myLogger = function (req, res, next) {
console.log('LOGGED')
next()
}
app.use(myLogger)
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(3000)
```
Every time the app receives a request, it prints the message "LOGGED" to the terminal.
The order of middleware loading is important: middleware functions that are loaded first are also executed first.
If `myLogger` is loaded after the route to the root path, the request never reaches it and the app doesn't print "LOGGED", because the route handler of the root path terminates the request-response cycle.
The middleware function `myLogger` simply prints a message, then passes on the request to the next middleware function in the stack by calling the `next()` function.
<h3>Middleware function requestTime</h3>
Next, we'll create a middleware function called "requestTime" and add a property called `requestTime`
to the request object.
```js
const requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
```
The app now uses the `requestTime` middleware function. Also, the callback function of the root path route uses the property that the middleware function adds to `req` (the request object).
```js
const express = require('express')
const app = express()
const requestTime = function (req, res, next) {
req.requestTime = Date.now()
next()
}
app.use(requestTime)
app.get('/', (req, res) => {
let responseText = 'Hello World!<br>'
responseText += `<small>Requested at: ${req.requestTime}</small>`
res.send(responseText)
})
app.listen(3000)
```
When you make a request to the root of the app, the app now displays the timestamp of your request in the browser.
<h3>Middleware function validateCookies</h3>
Finally, we'll create a middleware function that validates incoming cookies and sends a 400 response if cookies are invalid.
Here's an example function that validates cookies with an external async service.
```js
async function cookieValidator (cookies) {
try {
await externallyValidateCookie(cookies.testCookie)
} catch {
throw new Error('Invalid cookies')
}
}
```
Here, we use the [`cookie-parser`](/resources/middleware/cookie-parser.html) middleware to parse incoming cookies off the `req` object and pass them to our `cookieValidator` function. The `validateCookies` middleware returns a Promise that upon rejection will automatically trigger our error handler.
```js
const express = require('express')
const cookieParser = require('cookie-parser')
const cookieValidator = require('./cookieValidator')
const app = express()
async function validateCookies (req, res, next) {
await cookieValidator(req.cookies)
next()
}
app.use(cookieParser())
app.use(validateCookies)
// error handler
app.use((err, req, res, next) => {
res.status(400).send(err.message)
})
app.listen(3000)
```
<div class="doc-box doc-notice" markdown="1">
Note how `next()` is called after `await cookieValidator(req.cookies)`. This ensures that if `cookieValidator` resolves, the next middleware in the stack will get called. If you pass anything to the `next()` function (except the string `'route'` or `'router'`), Express regards the current request as being an error and will skip any remaining non-error handling routing and middleware functions.
</div>
Because you have access to the request object, the response object, the next middleware function in the stack, and the whole Node.js API, the possibilities with middleware functions are endless.
For more information about Express middleware, see: [Using Express middleware](/{{ page.lang }}/guide/using-middleware.html).
<h2>Configurable middleware</h2>
If you need your middleware to be configurable, export a function which accepts an options object or other parameters, which, then returns the middleware implementation based on the input parameters.
File: `my-middleware.js`
```js
module.exports = function (options) {
return function (req, res, next) {
// Implement the middleware function based on the options object
next()
}
}
```
The middleware can now be used as shown below.
```js
const mw = require('./my-middleware.js')
app.use(mw({ option1: '1', option2: '2' }))
```
Refer to [cookie-session](https://github.com/expressjs/cookie-session) and [compression](https://github.com/expressjs/compression) for examples of configurable middleware.

49
id/index.md Normal file
View File

@@ -0,0 +1,49 @@
---
layout: home
title: Express - Kerangka kerja aplikasi web Node.js
menu: home
lang: id
---
<section id="home-content">
{% include header/header-{{ page.lang }}.html %}
<div id="overlay"></div>
<div id="homepage-leftpane" class="pane">
<section id="description">
<div class="express"><a href="/">Express</a><a href="{{ page.lang }}/changelog/4x.html#{{ site.data.express.current_version }}" id="express-version">{{ site.data.express.current_version }}</a></div>
<span class="description">Kerangka web yang cepat, tidak beropini, dan minimalis untuk <a href='https://nodejs.org/en/'>Node.js</a></span>
</section>
<div id="install-command">$ npm install express --save</div>
</div>
<div id="homepage-rightpane" class="pane">
<iframe src="https://www.youtube.com/embed/HxGt_3F0ULg" frameborder="0" allowfullscreen></iframe>
</div>
</section>
<section id="announcements">
{% include announcement/announcement-{{ page.lang }}.md %}
</section>
<section id="intro">
<div id="boxes" class="clearfix">
<div id="web-applications">
<h3>Aplikasi Web</h3> Express adalah kerangka kerja aplikasi web Node.js yang minimalis dan fleksibel serta menyediakan serangkaian fitur tangguh untuk pembuatan aplikasi web dan seluler.
</div>
<div id="apis">
<h3>APIs</h3> dengan segudang metode untuk utilitas HTTP dan middleware yang sesuai dengan keinginan Anda, maka membuat API yang kuat dapat dilakukan dengan cepat dan mudah.
</div>
<div id="performance">
<h3>Kinerja</h3> Express menyediakan selapis tipis fitur dasar aplikasi web, tanpa mengaburkan fitur Node.js yang Anda kenal dan sukai.
</div>
<div id="middleware">
<h3>Middleware</h3>
Express memiliki kerangka perutean yang ringan dan fleksibel dengan fitur inti yang minimalis
hal ini dimaksudkan dapat ditingkatkan melalui penggunaan modul dari Express <a href="{{ page.lang }}/resources/middleware.html">middleware</a>.
</div>
</div>
</section>

75
id/resources/community.md Executable file
View File

@@ -0,0 +1,75 @@
---
layout: page
title: Express community
menu: resources
lang: id
---
# Community
## Technical committee
The Express technical committee meets online every two weeks (as needed) to discuss development and maintenance of Express,
and other issues relevant to the Express project. Each meeting is typically announced in an
[expressjs/discussions issue](https://github.com/expressjs/discussions/issues) with a link to join or view the meeting, which is
open to all observers.
The meetings are recorded; for a list of the recordings, see the [Express.js YouTube channel](https://www.youtube.com/channel/UCYjxjAeH6TRik9Iwy5nXw7g).
Members of the Express technical committee are:
**Active:**
- [@blakeembrey](https://github.com/blakeembrey) - Blake Embrey
- [@crandmck](https://github.com/crandmck) - Rand McKinney
- [@dougwilson](https://github.com/dougwilson) - Douglas Wilson
- [@LinusU](https://github.com/LinusU) - Linus Unnebäck
- [@ulisesgascon](https://github.com/ulisesGascon) - Ulises Gascón
- [@sheplu](https://github.com/sheplu) - Jean Burellier
- [@wesleytodd](https://github.com/wesleytodd) - Wes Todd
- [@jonchurch](https://github.com/jonchurch) - Jon Church
**Inactive:**
- [@hacksparrow](https://github.com/hacksparrow) - Hage Yaapa
- [@jonathanong](https://github.com/jonathanong) - jongleberry
- [@niftylettuce](https://github.com/niftylettuce) - niftylettuce
- [@troygoode](https://github.com/troygoode) - Troy Goode
## Express is made of many modules
Our vibrant community has created a large variety of extensions,
[middleware modules](/{{ page.lang }}/resources/middleware.html) and higher-level frameworks.
Additionally, the Express community maintains modules in these two GitHub orgs:
- [jshttp](https://jshttp.github.io/) modules providing useful utility functions; see [Utility modules](/{{ page.lang }}/resources/utils.html).
- [pillarjs](https://pillarjs.github.io/): low-level modules that Express uses internally.
To keep up with what is going on in the whole community, check out the [ExpressJS StatusBoard](https://expressjs.github.io/statusboard/).
## Gitter
The [expressjs/express chatroom](https://gitter.im/expressjs/express) is great place
for developers interested in the everyday discussions related to Express.
## Issues
If you've come across what you think is a bug, or just want to make
a feature request open a ticket in the [issue queue](https://github.com/expressjs/express/issues).
## Examples
View dozens of Express application [examples](https://github.com/expressjs/express/tree/master/examples)
in the repository covering everything from API design and authentication to template engine integration.
## Mailing List
Join over 2000 Express users or browse over 5000
discussions in the [Google Group](https://groups.google.com/group/express-js).
## IRC channel
Hundreds of developers idle in #express on freenode every day.
If you have questions about the framework, jump in for quick
feedback.

View File

@@ -0,0 +1,304 @@
---
layout: page
title: Contributing to Express
menu: resources
lang: id
---
# Contributing to Express
Express and the other projects in the [expressjs organization on GitHub](https://github.com/expressjs) are projects of the [Node.js Foundation](https://nodejs.org/foundation/).
These projects are governed under the general policies and guidelines of the Node.js Foundation along with the additional guidelines below.
* [Technical committee](#technical-committee)
* [Community contributing guide](#community-contributing-guide)
* [Collaborator's guide](#collaborators-guide)
* [Security policies and procedures](#security-policies-and-procedures)
## Technical committee
The Express technical committee consists of active project members, and guides development and maintenance of the Express project. For more information, see [Express Community - Technical committee](community.html#technical-committee).
## Community contributing guide
<!-- SRC: expressjs/express Contributing.md -->
The goal of this document is to create a contribution process that:
* Encourages new contributions.
* Encourages contributors to remain involved.
* Avoids unnecessary processes and bureaucracy whenever possible.
* Creates a transparent decision making process that makes it clear how
contributors can be involved in decision making.
### Vocabulary
* A **Contributor** is any individual creating or commenting on an issue or pull request.
* A **Committer** is a subset of contributors who have been given write access to the repository.
* A **Project Captain** is the lead maintainer of a repository.
* A **TC (Technical Committee)** is a group of committers representing the required technical
expertise to resolve rare disputes.
* A **Triager** is a subset of contributors who have been given triage access to the repository.
### Logging Issues
Log an issue for any question or problem you might have. When in doubt, log an issue, and
any additional policies about what to include will be provided in the responses. The only
exception is security disclosures which should be sent privately.
Committers may direct you to another repository, ask for additional clarifications, and
add appropriate metadata before the issue is addressed.
Please be courteous and respectful. Every participant is expected to follow the
project's Code of Conduct.
### Contributions
Any change to resources in this repository must be through pull requests. This applies to all changes
to documentation, code, binary files, etc. Even long term committers and TC members must use
pull requests.
No pull request can be merged without being reviewed.
For non-trivial contributions, pull requests should sit for at least 36 hours to ensure that
contributors in other timezones have time to review. Consideration should also be given to
weekends and other holiday periods to ensure active committers all have reasonable time to
become involved in the discussion and review process if they wish.
The default for each contribution is that it is accepted once no committer has an objection.
During a review, committers may also request that a specific contributor who is most versed in a
particular area gives a "LGTM" before the PR can be merged. There is no additional "sign off"
process for contributions to land. Once all issues brought by committers are addressed it can
be landed by any committer.
In the case of an objection being raised in a pull request by another committer, all involved
committers should seek to arrive at a consensus by way of addressing concerns being expressed
by discussion, compromise on the proposed change, or withdrawal of the proposed change.
If a contribution is controversial and committers cannot agree about how to get it to land
or if it should land then it should be escalated to the TC. TC members should regularly
discuss pending contributions in order to find a resolution. It is expected that only a
small minority of issues be brought to the TC for resolution and that discussion and
compromise among committers be the default resolution mechanism.
### Becoming a Triager
Anyone can become a triager! Read more about the process of being a triager in
[the triage process document](https://github.com/expressjs/express/blob/master/Triager-Guide.md).
Currently, any existing [organization member](https://github.com/orgs/expressjs/people) can nominate
a new triager. If you are interested in becoming a triager, our best advice is to actively participate
in the community by helping triaging issues and pull requests. As well we recommend
to engage in other community activities like attending the TC meetings, and participating in the Slack
discussions.
You can also reach out to any of the [organization members](https://github.com/orgs/expressjs/people)
if you have questions or need guidance.
### Becoming a Committer
All contributors who land a non-trivial contribution should be on-boarded in a timely manner,
and added as a committer, and be given write access to the repository.
Committers are expected to follow this policy and continue to send pull requests, go through
proper review, and have other committers merge their pull requests.
### TC Process
The TC uses a "consensus seeking" process for issues that are escalated to the TC.
The group tries to find a resolution that has no open objections among TC members.
If a consensus cannot be reached that has no objections then a majority wins vote
is called. It is also expected that the majority of decisions made by the TC are via
a consensus seeking process and that voting is only used as a last-resort.
Resolution may involve returning the issue to project captains with suggestions on
how to move forward towards a consensus. It is not expected that a meeting of the TC
will resolve all issues on its agenda during that meeting and may prefer to continue
the discussion happening among the project captains.
Members can be added to the TC at any time. Any TC member can nominate another committer
to the TC and the TC uses its standard consensus seeking process to evaluate whether or
not to add this new member. The TC will consist of a minimum of 3 active members and a
maximum of 10. If the TC should drop below 5 members the active TC members should nominate
someone new. If a TC member is stepping down, they are encouraged (but not required) to
nominate someone to take their place.
TC members will be added as admin's on the Github orgs, npm orgs, and other resources as
necessary to be effective in the role.
To remain "active" a TC member should have participation within the last 12 months and miss
no more than six consecutive TC meetings. Our goal is to increase participation, not punish
people for any lack of participation, this guideline should be only be used as such
(replace an inactive member with a new active one, for example). Members who do not meet this
are expected to step down. If A TC member does not step down, an issue can be opened in the
discussions repo to move them to inactive status. TC members who step down or are removed due
to inactivity will be moved into inactive status.
Inactive status members can become active members by self nomination if the TC is not already
larger than the maximum of 10. They will also be given preference if, while at max size, an
active member steps down.
### Project Captains
The Express TC can designate captains for individual projects/repos in the
organizations. These captains are responsible for being the primary
day-to-day maintainers of the repo on a technical and community front.
Repo captains are empowered with repo ownership and package publication rights.
When there are conflicts, especially on topics that effect the Express project
at large, captains are responsible to raise it up to the TC and drive
those conflicts to resolution. Captains are also responsible for making sure
community members follow the community guidelines, maintaining the repo
and the published package, as well as in providing user support.
Like TC members, Repo captains are a subset of committers.
To become a captain for a project the candidate is expected to participate in that
project for at least 6 months as a committer prior to the request. They should have
helped with code contributions as well as triaging issues. They are also required to
have 2FA enabled on both their GitHub and npm accounts. Any TC member or existing
captain on the repo can nominate another committer to the captain role, submit a PR to
this doc, under `Current Project Captains` section (maintaining the sort order) with
the project, their GitHub handle and npm username (if different). The PR will require
at least 2 approvals from TC members and 2 weeks hold time to allow for comment and/or
dissent. When the PR is merged, a TC member will add them to the proper GitHub/npm groups.
#### Current Project Captains
- `expressjs/express`: @wesleytodd
- `expressjs/discussions`: @wesleytodd
- `expressjs/expressjs.com`: @crandmck, @jonchurch
- `expressjs/body-parser`: @wesleytodd, @jonchurch
- `expressjs/multer`: @LinusU
- `expressjs/morgan`: @jonchurch
- `expressjs/cookie-parser`: @wesleytodd
- `expressjs/cors`: @jonchurch
- `expressjs/generator`: @wesleytodd
- `expressjs/statusboard`: @wesleytodd
- `pillarjs/encodeurl`: @blakeembrey
- `pillarjs/path-to-regexp`: @blakeembrey
- `pillarjs/router`: @dougwilson, @wesleytodd
- `pillarjs/finalhandler`: @wesleytodd
- `pillarjs/request`: @wesleytodd
- `jshttp/http-errors`: @wesleytodd, @jonchurch
- `jshttp/cookie`: @wesleytodd
- `jshttp/on-finished`: @wesleytodd
- `jshttp/forwarded`: @wesleytodd
- `jshttp/proxy-addr`: @wesleytodd
#### Current Initiative Captains
- Triage team [ref](https://github.com/expressjs/discussions/issues/227): @UlisesGascon
## Collaborator's guide
<!-- SRC: expressjs/express Collaborator-Guide.md -->
### Website Issues
Open issues for the expressjs.com website in https://github.com/expressjs/expressjs.com.
### PRs and Code contributions
* Tests must pass.
* Follow the [JavaScript Standard Style](http://standardjs.com/) and `npm run lint`.
* If you fix a bug, add a test.
### Branches
Use the `master` branch for bug fixes or minor work that is intended for the
current release stream.
Use the correspondingly named branch, e.g. `5.0`, for anything intended for
a future release of Express.
### Steps for contributing
1. [Create an issue](https://github.com/expressjs/express/issues/new) for the
bug you want to fix or the feature that you want to add.
2. Create your own [fork](https://github.com/expressjs/express) on GitHub, then
checkout your fork.
3. Write your code in your local copy. It's good practice to create a branch for
each new issue you work on, although not compulsory.
4. To run the test suite, first install the dependencies by running `npm install`,
then run `npm test`.
5. Ensure your code is linted by running `npm run lint` -- fix any issue you
see listed.
6. If the tests pass, you can commit your changes to your fork and then create
a pull request from there. Make sure to reference your issue from the pull
request comments by including the issue number e.g. `#123`.
### Issues which are questions
We will typically close any vague issues or questions that are specific to some
app you are writing. Please double check the docs and other references before
being trigger happy with posting a question issue.
Things that will help get your question issue looked at:
* Full and runnable JS code.
* Clear description of the problem or unexpected behavior.
* Clear description of the expected result.
* Steps you have taken to debug it yourself.
If you post a question and do not outline the above items or make it easy for
us to understand and reproduce your issue, it will be closed.
## Security Policies and Procedures
<!-- SRC: expressjs/express Security.md -->
This document outlines security procedures and general policies for the Express
project.
* [Reporting a Bug](#reporting-a-bug)
* [Disclosure Policy](#disclosure-policy)
* [Comments on this Policy](#comments-on-this-policy)
### Reporting a Bug
The Express team and community take all security bugs in Express seriously.
Thank you for improving the security of Express. We appreciate your efforts and
responsible disclosure and will make every effort to acknowledge your
contributions.
Report security bugs by emailing the lead maintainer in the Readme.md file.
To ensure the timely response to your report, please ensure that the entirety
of the report is contained within the email body and not solely behind a web
link or an attachment.
The lead maintainer will acknowledge your email within 48 hours, and will send a
more detailed response within 48 hours indicating the next steps in handling
your report. After the initial reply to your report, the security team will
endeavor to keep you informed of the progress towards a fix and full
announcement, and may ask for additional information or guidance.
Report security bugs in third-party modules to the person or team maintaining
the module.
### Pre-release Versions
Alpha and Beta releases are unstable and **not suitable for production use**.
Vulnerabilities found in pre-releases should be reported according to the [Reporting a Bug](#reporting-a-bug) section.
Due to the unstable nature of the branch it is not guaranteed that any fixes will be released in the next pre-release.
### Disclosure Policy
When the security team receives a security bug report, they will assign it to a
primary handler. This person will coordinate the fix and release process,
involving the following steps:
* Confirm the problem and determine the affected versions.
* Audit code to find any potential similar problems.
* Prepare fixes for all releases still under maintenance. These fixes will be
released as fast as possible to npm.
### The Express Threat Model
We are currently working on a new version of the security model, the most updated version can be found [here](https://github.com/expressjs/security-wg/blob/main/docs/ThreatModel.md)
### Comments on this Policy
If you have suggestions on how this process could be improved please submit a
pull request.

56
id/resources/glossary.md Executable file
View File

@@ -0,0 +1,56 @@
---
layout: page
title: Express glossary
menu: resources
lang: id
---
# Glossary
### application
In general, one or more programs that are designed to carry out operations for a specific purpose. In the context of Express, a program that uses the Express API running on the Node.js platform. Might also refer to an [app object](/{{ page.lang }}/api.html#express).
### API
Application programming interface. Spell out the abbreviation when it is first used.
### Express
A fast, un-opinionated, minimalist web framework for Node.js applications. In general, "Express" is preferred to "Express.js," though the latter is acceptable.
### libuv
A multi-platform support library which focuses on asynchronous I/O, primarily developed for use by Node.js.
### middleware
A function that is invoked by the Express routing layer before the final request handler, and thus sits in the middle between a raw request and the final intended route. A few fine points of terminology around middleware:
* `var foo = require('middleware')` is called _requiring_ or _using_ a Node.js module. Then the statement `var mw = foo()` typically returns the middleware.
* `app.use(mw)` is called _adding the middleware to the global processing stack_.
* `app.get('/foo', mw, function (req, res) { ... })` is called _adding the middleware to the "GET /foo" processing stack_.
### Node.js
A software platform that is used to build scalable network applications. Node.js uses JavaScript as its scripting language, and achieves high throughput via non-blocking I/O and a single-threaded event loop. See [nodejs.org](https://nodejs.org/en/). **Usage note**: Initially, "Node.js," thereafter "Node".
### open-source, open source
When used as an adjective, hyphenate; for example: "This is open-source software." See [Open-source software on Wikipedia](http://en.wikipedia.org/wiki/Open-source_software). Note: Although it is common not to hyphenate this term, we are using the standard English rules for hyphenating a compound adjective.
### request
An HTTP request. A client submits an HTTP request message to a server, which returns a response. The request must use one of several [request methods](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods) such as GET, POST, and so on.
### response
An HTTP response. A server returns an HTTP response message to the client. The response contains completion status information about the request and might also contain requested content in its message body.
### route
Part of a URL that identifies a resource. For example, in `http://foo.com/products/id`, "/products/id" is the route.
### router
See [router](/{{ page.lang }}/api.html#router) in the API reference.

57
id/resources/middleware.md Executable file
View File

@@ -0,0 +1,57 @@
---
layout: middleware
title: Express middleware
menu: resources
lang: id
module: mw-home
---
## Express middleware
The Express middleware modules listed here are maintained by the
[Expressjs team](https://github.com/orgs/expressjs/people).
|Middleware module | Description | Replaces built-in function (Express 3)|
|---------------------------|---------------------|----------------------|
| [body-parser](/resources/middleware/body-parser.html) | Parse HTTP request body. See also: [body](https://github.com/raynos/body), [co-body](https://github.com/visionmedia/co-body), and [raw-body](https://github.com/stream-utils/raw-body). | express.bodyParser |
| [compression](/resources/middleware/compression.html) | Compress HTTP responses. | express.compress |
| [connect-rid](/resources/middleware/connect-rid.html) | Generate unique request ID. | NA |
| [cookie-parser](/resources/middleware/cookie-parser.html) | Parse cookie header and populate `req.cookies`. See also [cookies](https://github.com/jed/cookies) and [keygrip](https://github.com/jed/keygrip). | express.cookieParser|
| [cookie-session](/resources/middleware/cookie-session.html) | Establish cookie-based sessions.| express.cookieSession |
| [cors](/resources/middleware/cors.html) | Enable cross-origin resource sharing (CORS) with various options.| NA
| [errorhandler](/resources/middleware/errorhandler.html) |Development error-handling/debugging. |express.errorHandler |
| [method-override](/resources/middleware/method-override.html) |Override HTTP methods using header. |express.methodOverride |
| [morgan](/resources/middleware/morgan.html) | HTTP request logger. | express.logger |
| [multer](/resources/middleware/multer.html) | Handle multi-part form data. | express.bodyParser |
| [response-time](/resources/middleware/response-time.html) | Record HTTP response time. |express.responseTime |
| [serve-favicon](/resources/middleware/serve-favicon.html) | Serve a favicon. |express.favicon |
| [serve-index](/resources/middleware/serve-index.html) | Serve directory listing for a given path.| express.directory |
| [serve-static](/resources/middleware/serve-static.html) |Serve static files. |express.static |
| [session](/resources/middleware/session.html) | Establish server-based sessions (development only). | express.session |
| [timeout](/resources/middleware/timeout.html) | Set a timeout period for HTTP request processing.|express.timeout |
| [vhost](/resources/middleware/vhost.html) |Create virtual domains.|express.vhost|
## Additional middleware modules
These are some additional popular middleware modules.
{% include community-caveat.html %}
|Middleware&nbsp;module | Description |
|---------------------------|---------------------|
| [cls-rtracer](https://github.com/puzpuzpuz/cls-rtracer) | Middleware for CLS-based request id generation. An out-of-the-box solution for adding request ids into your logs.|
| [connect-image-optimus](https://github.com/msemenistyi/connect-image-optimus) | Optimize image serving. Switches images to `.webp` or `.jxr`, if possible.|
| [error-handler-json](https://github.com/mifi/error-handler-json) | An error handler for JSON APIs (fork of `api-error-handler`.)|
| [express-debug](https://github.com/devoidfury/express-debug) | Development tool that adds information about template variables (locals), current session, and so on.|
| [express-partial-response](https://github.com/nemtsov/express-partial-response) | Filters out parts of JSON responses based on the `fields` query-string; by using Google API's Partial Response.|
| [express-simple-cdn](https://github.com/jamiesteven/express-simple-cdn) | Use a CDN for static assets, with multiple host support.|
| [express-slash](https://github.com/ericf/express-slash) | Handles routes with and without trailing slashes.|
| [express-uncapitalize](https://github.com/jamiesteven/express-uncapitalize) | Redirects HTTP requests containing uppercase to a canonical lowercase form.|
| [helmet](https://github.com/helmetjs/helmet) | Helps secure your apps by setting various HTTP headers.|
| [join-io](https://github.com/coderaiser/join-io) | Joins files on the fly to reduce the requests count.|
| [passport](https://github.com/jaredhanson/passport) | Authentication using "strategies" such as OAuth, OpenID and many others. See [http://passportjs.org/](http://passportjs.org/) for more information.|
| [static-expiry](https://github.com/paulwalker/connect-static-expiry) | Fingerprint URLs or caching headers for static assets.|
| [view-helpers](https://github.com/madhums/node-view-helpers) | Common helper methods for views.|
| [sriracha-admin](https://github.com/hdngr/siracha) | Dynamically generate an admin site for Mongoose. |
For more middleware modules, see [http-framework](https://github.com/Raynos/http-framework#modules).

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express body-parser middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/body-parser.html'
module: body-parser
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express compression middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/compression.html'
module: compression
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express connect-rid middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/connect-rid.html'
module: connect-rid
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express cookie-parser middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/cookie-parser.html'
module: cookie-parser
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express cookie-session middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/cookie-session.html'
module: cookie-session
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express cors middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/cors.html'
module: cors
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express errorhandler middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/errorhandler.html'
module: errorhandler
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express method-override middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/method-override.html'
module: method-override
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express morgan middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/morgan.html'
module: morgan
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express multer middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/multer.html'
module: multer
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express response-time middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/response-time.html'
module: response-time
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express serve-favicon middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/serve-favicon.html'
module: serve-favicon
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express serve-index middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/serve-index.html'
module: serve-index
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express serve-static middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/serve-static.html'
module: serve-static
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express session middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/session.html'
module: session
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express timeout middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/timeout.html'
module: timeout
---

View File

@@ -0,0 +1,8 @@
---
layout: middleware
title: Express vhost middleware
menu: resources
lang: en
redirect_from: '/resources/middleware/vhost.html'
module: vhost
---

28
id/resources/utils.md Normal file
View File

@@ -0,0 +1,28 @@
---
layout: page
title: Express utilities
menu: resources
lang: id
---
## Express utility functions
The [pillarjs](https://github.com/pillarjs) GitHub organization contains a number of modules
for utility functions that may be generally useful.
| Utility modules | Description|
|-----------------|------------|
| [cookies](https://www.npmjs.com/package/cookies) | Get and set HTTP(S) cookies that can be signed to prevent tampering, using Keygrip. Can be used with the Node.js HTTP library or as Express middleware.|
| [csrf](https://www.npmjs.com/package/csrf) | Contains the logic behind CSRF token creation and verification. Use this module to create custom CSRF middleware.|
| [finalhandler](https://www.npmjs.com/package/finalhandler) | Function to invoke as the final step to respond to HTTP request.|
| [parseurl](https://www.npmjs.com/package/parseurl) | Parse a URL with caching. |
| [path-match](https://www.npmjs.com/package/path-match) | Thin wrapper around [path-to-regexp](https://github.com/component/path-to-regexp) to make extracting parameter names easier.|
| [path-to-regexp](https://www.npmjs.com/package/path-to-regexp) | Turn an Express-style path string such as ``/user/:name` into a regular expression.|
| [resolve-path](https://www.npmjs.com/package/resolve-path) | Resolves a relative path against a root path with validation. |
| [router](https://www.npmjs.com/package/router) | Simple middleware-style router. |
| [routington](https://www.npmjs.com/package/routington) | Trie-based URL router for defining and matching URLs. |
| [send](https://www.npmjs.com/package/send) | Library for streaming files as a HTTP response, with support for partial responses (ranges), conditional-GET negotiation, and granular events.|
| [templation](https://www.npmjs.com/package/templation) | View system similar to `res.render()` inspired by [co-views](https://github.com/visionmedia/co-views) and [consolidate.js](https://github.com/visionmedia/consolidate.js/). |
For additional low-level HTTP-related modules, see [jshttp](http://jshttp.github.io/).

67
id/starter/basic-routing.md Executable file
View File

@@ -0,0 +1,67 @@
---
layout: page
title: Dasar routing Express
menu: starter
lang: id
---
# Dasar _routing_
_Routing_ mengacu pada cara menentukan bagaimana aplikasi merespons permintaan klien ke titik akhir (_endpoint_) tertentu, yang merupakan URI (atau jalur) dan mengirimkan metode permintaan HTTP tertentu (GET, POST, dan seterusnya).
Setiap rute dapat memiliki satu atau lebih fungsi pengendali, yang dijalankan ketika rute yang dipanggil tersebut cocok.
Definisi rute tersebut mengambil struktur sebagai berikut:
```js
app.METHOD(PATH, HANDLER)
```
Dimana:
- `app` adalah sebuah _class_ dari `express`.
- `METHOD` adalah sebuah [Metode _HTTP request_](https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods), dalam huruf kecil.
- `PATH` adalah _path_ atau jalur yang didefinisikan di server.
- `HANDLER` adalah _function_ yang dijalankan ketika rute yang dipanggil cocok.
<div class="doc-box doc-notice" markdown="1">
Pada tutorial ini mengasumsikan bahwa <em>class</em> dari `express` bernama `app` telah dibuat dan server sedang berjalan. Jika Anda belum terbiasa dalam membuat sebuah aplikasi dan memulainya, Anda dapat melihat [Contoh hello world](/{{ page.lang }}/starter/hello-world.html).
</div>
Contoh berikut ini akan mengilustrasikan cara pendefinisian rute secara sederhana.
Respons dengan `Hello World!` di halaman _home_:
```js
app.get('/', (req, res) => {
res.send('Hello World!')
})
```
Respons dengan metode _request_ POST pada rute _root_ (`/`), halaman _home_ aplikasi:
```js
app.post('/', (req, res) => {
res.send('Got a POST request')
})
```
Respons dengan metode _request_ PUT pada rute `/user`:
```js
app.put('/user', (req, res) => {
res.send('Got a PUT request at /user')
})
```
Respons dengan metode _request_ DELETE pada rute `/user`:
```js
app.delete('/user', (req, res) => {
res.send('Got a DELETE request at /user')
})
```
Untuk detail lebih lanjut tentang perutean, Anda dapat melihat [panduan _routing_](/{{ page.lang }}/guide/routing.html).
### [Previous: Express application generator ](/{{ page.lang }}/starter/generator.html)&nbsp;&nbsp;&nbsp;&nbsp;[Next: Serving static files in Express ](/{{ page.lang }}/starter/static-files.html)

23
id/starter/examples.md Executable file
View File

@@ -0,0 +1,23 @@
---
layout: page
title: Contoh Penggunaan Express
menu: starter
lang: id
---
{% capture examples %}{% include readmes/express-master/examples.md %}{% endcapture %}
{{ examples | replace: "](.", "](https://github.com/expressjs/express/tree/master/examples" }}
## Contoh tambahan
Ini adalah beberapa contoh tambahan penggunaan Express dengan integrasi yang lebih luas.
{% include community-caveat.html %}
- [prisma-express-graphql](https://github.com/prisma/prisma-examples/tree/latest/typescript/graphql-express) - GraphQL API dengan `express-graphql` menggunakan [Prisma](https://www.npmjs.com/package/prisma) sebagai ORM
- [prisma-fullstack](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-nextjs-express) - Aplikasi fullstack dengan Next.js menggunakan [Prisma](https://www.npmjs.com/package/prisma) sebagai ORM
- [prisma-rest-api-js](https://github.com/prisma/prisma-examples/tree/latest/javascript/rest-express) - REST API dengan Express dalam JavaScript menggunakan [Prisma](https://www.npmjs.com/package/prisma) sebagai ORM
- [prisma-rest-api-ts](https://github.com/prisma/prisma-examples/tree/latest/typescript/rest-express) - REST API dengan Express dalam TypeScript menggunakan [Prisma](https://www.npmjs.com/package/prisma) sebagai ORM
### [Previous: Static Files ](/{{ page.lang }}/starter/static-files.html)&nbsp;&nbsp;&nbsp;&nbsp;[Next: FAQ ](/{{ page.lang }}/starter/faq.html)

92
id/starter/faq.md Executable file
View File

@@ -0,0 +1,92 @@
---
layout: page
title: Express FAQ
menu: starter
lang: id
---
# FAQ
## Bagaimana sebaiknya struktur aplikasi saya?
Tidak ada jawaban pasti untuk pertanyaan ini. Jawabannya tergantung
pada skala aplikasi Anda dan tim yang terlibat. Sefleksibel mungkin, sehingga Express tidak membuat asumsi dalam hal struktur.
Kumpulan rute dan logika khusus lainnya di dalam aplikasi dapat berada di
banyak file sesuai keinginan Anda, dalam struktur direktori apa pun yang Anda
inginkan. Lihat contoh berikut ini sebagai inspirasi:
* [Route listings](https://github.com/expressjs/express/blob/4.13.1/examples/route-separation/index.js#L32-L47)
* [Route map](https://github.com/expressjs/express/blob/4.13.1/examples/route-map/index.js#L52-L66)
* [MVC style controllers](https://github.com/expressjs/express/tree/master/examples/mvc)
Selain itu, ada ekstensi (_extension_) dari pihak ketiga untuk Express, yang menyederhanakan beberapa pola berikut:
* [Resourceful routing](https://github.com/expressjs/express-resource)
## Bagaimana cara mendefinisikan model?
Express tidak memiliki gagasan tentang database. Jadi, konsep ini
diserahkan kepada modul Node dari pihak ketiga, memungkinkan Anda
melakukannya secara antarmuka dengan hampir semua database.
Lihat [LoopBack](http://loopback.io) untuk kerangka kerja berbasis
Express yang berpusat pada model.
## Bagaimana cara mengautentikasi pengguna?
Otentikasi adalah area yang beropini (_opinionated area_) lainnya yang
tidak dimasuki oleh Express. Sehingga Anda dapat menggunakan skema otentikasi apa pun yang Anda inginkan. Untuk skema _username/password_
sederhana, Anda dapat melihat [contoh ini](https://github.com/expressjs/express/tree/master/examples/auth).
## _Template engines_ mana saja yang mendukung Express?
Express mendukung _template engine_ apa pun yang sesuai dengan _signature_ `(path, locals, callback)`.
Untuk menormalkan antarmuka mesin _template engine_ dan _caching_, lihat
[consolidate.js](https://github.com/visionmedia/consolidate.js)
daftar _template engine_ yang mendukung express. _Template engine_ yang tidak terdaftar mungkin masih mendukung _signature_ dari Express.
Untuk informasi lebih lanjut, lihat [Penggunaan _template engine_ dengan Express](/{{page.lang}}/guide/using-template-engines.html).
## Bagaimana cara menangani respon 404?
Di Express, respon 404 bukanlah hasil dari sebuah _error_, jadi
_error-handler middleware_ tidak akan menangkapnya. Perilaku ini terjadi
karena respon 404 hanya menunjukkan tidak adanya pekerjaan tambahan yang harus dilakukan;
dengan kata lain, Express telah menjalankan semua fungsi dan rute dari _middleware_ yang ada,
kemudian menemukan bahwa tidak ada satupun dari mereka yang merespons. Jadi, yang Anda perlukan lakukan adalah menambahkan fungsi middleware di bagian paling bawah dari _stack_ yang ada (di bawah semua fungsi lainnya).
Oleh karena itu, untuk menangani respon 404 secara sederhana adalah sebagai berikut:
```js
app.use((req, res, next) => {
res.status(404).send('Maaf data tidak dapat ditemukan!')
})
```
Tambahkan rute secara dinamis saat runtime pada _class_ (_instance_) `express.Router()` sehingga rute tidak digantikan oleh fungsi middleware.
## Bagaimana cara membuat _error handler_?
Anda dapat mendefinisikan _error-handler middleware_ dengan cara yang sama seperti _middleware_ lainnya, kecuali dengan empat argumen, bukan tiga; secara khusus dengan _signature_ `(err, req, res, next)`:
```js
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('Ada yang salah!')
})
```
Untuk informasi selengkapnya, lihat [Penanganan _Error_](/{{ page.lang }}/guide/error-handling.html).
## Bagaimana cara merender HTML biasa?
Jangan lakukan! Tidak perlu "merender" HTML dengan fungsi `res.render()`.
Jika Anda memiliki file tertentu, gunakan fungsi `res.sendFile()`.
Jika Anda menyajikan banyak aset dari sebuah direktori, gunakan fungsi middleware `express.static()`.
## Versi Node.js apa yang dibutuhkan Express?
* [Express versi 4.x](/{{ page.lang }}/4x/api.html) memerlukan Node.js versi 0.10 atau yang lebih tinggi.
* [Express versi 5.x](/{{ page.lang }}/5x/api.html) memerlukan Node.js versi 18 atau yang lebih tinggi.
### [Previous: More examples ](/{{ page.lang }}/starter/examples.html)

127
id/starter/generator.md Executable file
View File

@@ -0,0 +1,127 @@
---
layout: page
title: Generator aplikasi Express
menu: starter
lang: id
---
# Generator aplikasi Express
Gunakan alat generator aplikasi, `express-generator`, untuk membuat kerangka aplikasi dengan cepat.
Anda dapat menjalankan generator aplikasi dengan perintah `npx` (tersedia di Node.js versi 8.2.0).
```console
$ npx express-generator
```
Untuk versi Node sebelumnya, instal generator aplikasi sebagai paket npm secara global lalu jalankan:
```console
$ npm install -g express-generator
$ express
```
Tampilkan daftar opsi perintah dengan opsi `-h`:
```console
$ express -h
Usage: express [options] [dir]
Options:
-h, --help output usage information
--version output the version number
-e, --ejs add ejs engine support
--hbs add handlebars engine support
--pug add pug engine support
-H, --hogan add hogan.js engine support
--no-view generate without view engine
-v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade)
-c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css)
--git add .gitignore
-f, --force force on non-empty directory
```
Misal, tutorial berikut ini kita akan membuat aplikasi Express bernama _myapp_. Aplikasi akan dibuat dalam folder bernama _myapp_ di direktori kerja saat ini dan _view engine_ yang akan digunakan adalah <a href="https://pugjs.org/" target="_blank" title="Pug documentation">Pug</a>:
```console
$ express --view=pug myapp
create : myapp
create : myapp/package.json
create : myapp/app.js
create : myapp/public
create : myapp/public/javascripts
create : myapp/public/images
create : myapp/routes
create : myapp/routes/index.js
create : myapp/routes/users.js
create : myapp/public/stylesheets
create : myapp/public/stylesheets/style.css
create : myapp/views
create : myapp/views/index.pug
create : myapp/views/layout.pug
create : myapp/views/error.pug
create : myapp/bin
create : myapp/bin/www
```
Kemudian instal semua dependensi project:
```console
$ cd myapp
$ npm install
```
Di MacOS atau Linux, jalankan aplikasi dengan perintah ini:
```console
$ DEBUG=myapp:* npm start
```
Di _Command Prompt_ Windows, gunakan perintah ini:
```console
> set DEBUG=myapp:* & npm start
```
Di _PowerShell_ Windows, gunakan perintah ini:
```console
PS> $env:DEBUG='myapp:*'; npm start
```
Kemudian, kunjungi `http://localhost:3000/` di browser Anda untuk mengakses aplikasi.
Aplikasi yang dihasilkan memiliki struktur direktori sebagai berikut:
```console
.
├── app.js
├── bin
│ └── www
├── package.json
├── public
│ ├── images
│ ├── javascripts
│ └── stylesheets
│ └── style.css
├── routes
│ ├── index.js
│ └── users.js
└── views
├── error.pug
├── index.pug
└── layout.pug
7 directories, 9 files
```
<div class="doc-box doc-info" markdown="1">
Struktur aplikasi yang dibuat oleh generator hanyalah salah satu dari banyak cara untuk membuat struktur aplikasi Express. Jangan ragu untuk menggunakan struktur ini atau memodifikasinya agar sesuai dengan kebutuhan Anda.
</div>
### [Previous: Hello World ](/{{ page.lang }}/starter/hello-world.html)&nbsp;&nbsp;&nbsp;&nbsp;[Next: Basic routing](/{{ page.lang }}/starter/basic-routing.html)

58
id/starter/hello-world.md Executable file
View File

@@ -0,0 +1,58 @@
---
layout: page
title: Contoh Express "Hello World"
menu: starter
lang: id
---
# Contoh hello world
<div class="doc-box doc-info" markdown="1">
Contoh di bawah ini pada dasarnya adalah aplikasi Express paling sederhana yang dapat Anda buat. Ini adalah aplikasi file tunggal &mdash; _bukan_ apa yang akan Anda dapatkan jika menggunakan [Generator Express](/{{ page.lang }}/starter/generator.html), yang membuat struktur untuk aplikasi lengkap dengan banyak file JavaScript, dengan templat Jade, dan sub- direktori untuk berbagai tujuan.
</div>
<script src="https://embed.runkit.com" data-element-id="hello-example" data-mode="endpoint" async defer></script>
<div id="hello-example"><pre><code class="language-js">
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
</code></pre></div>
Aplikasi ini memulai server dan mendengarkan koneksi pada _port_ 3000. Aplikasi merespon dengan "Hello World!" untuk _request_
ke URL _root_ (`/`) atau _route_. Untuk setiap jalur lainnya, ia akan merespons dengan **404 Not Found**.
Contoh di atas sebenarnya adalah server yang berfungsi: Silakan klik URL yang ditampilkan. Anda akan mendapat respons, dengan log real-time di halaman, dan perubahan apa pun yang Anda buat akan terlihat secara real-time. Hal ini didukung oleh [RunKit](https://runkit.com), yang menyediakan _playground_ untuk JavaScript secara interaktif yang terhubung ke lingkungan Node secara lengkap yang berjalan di browser web Anda.
Di bawah ini adalah petunjuk untuk menjalankan aplikasi yang sama di komputer lokal Anda.
<div class="doc-box doc-info" markdown="1">
RunKit adalah layanan pihak ketiga yang tidak berafiliasi dengan proyek Express.
</div>
### Berjalan secara Lokal
Pertama buat direktori bernama `myapp`, masuk ke direktori tersebut dan jalankan `npm init`. Kemudian, instal `express` sebagai dependensi, sesuai dengan [panduan instalasi](/{{ page.lang }}/starter/installing.html).
Di direktori `myapp`, buat file bernama `app.js` dan salin kode dari contoh di atas.
<div class="doc-box doc-notice" markdown="1">
`req` (<em>request</em>) dan `res` (<em>response</em>) adalah <em>objects</em> yang sama persis dengan yang disediakan Node, sehingga Anda dapat memanggilnya
`req.pipe()`, `req.on('data', callback)`, dan apa pun yang akan Anda lakukan tanpa melibatkan Express.
</div>
Jalankan aplikasi dengan perintah berikut:
```console
$ node app.js
```
Kemudian, kunjungi `http://localhost:3000/` di browser untuk melihat hasilnya.
### [Previous: Installing ](/{{ page.lang }}/starter/installing.html)&nbsp;&nbsp;&nbsp;&nbsp;[Next: Express Generator ](/{{ page.lang }}/starter/generator.html)

52
id/starter/installing.md Executable file
View File

@@ -0,0 +1,52 @@
---
layout: page
title: Menginstal Ekspres
menu: starter
lang: id
---
# Menginstal
Kami asumsikan Anda telah menginstal [Node.js](https://nodejs.org/), buatlah direktori untuk menyimpan aplikasi Anda, dan jadikan itu sebagai direktori kerja Anda.
* [Express versi 4.x](/{{ page.lang }}/4x/api.html) memerlukan Node.js versi 0.10 atau yang lebih tinggi.
* [Express versi 5.x](/{{ page.lang }}/5x/api.html) memerlukan Node.js versi 18 atau yang lebih tinggi.
```console
$ mkdir myapp
$ cd myapp
```
Gunakan perintah `npm init` untuk membuat file `package.json` untuk aplikasi Anda.
Untuk informasi selengkapnya tentang cara kerja `package.json`, lihat [Spesifikasi penggunaan package.json dari npm](https://docs.npmjs.com/files/package.json).
```console
$ npm init
```
Perintah ini menanyakan beberapa hal, seperti nama dan versi aplikasi Anda.
Untuk saat ini, Anda cukup menekan RETURN/ENTER untuk menerima default sebagian besar, dengan pengecualian berikut:
```
entry point: (index.js)
```
Masukan `app.js`, atau apa pun nama file utamanya yang Anda inginkan. Jika Anda menginginkannya menjadi `index.js`, tekan RETURN/ENTER untuk menerima nama file default yang disarankan.
Sekarang, instal Express di direktori `myapp` dan simpan di daftar dependensi. Misalnya:
```console
$ npm install express
```
Untuk menginstal Express secara sementara dan tidak menambahkannya ke daftar dependensi, jalankan perintah berikut:
```console
$ npm install express --no-save
```
<div class="doc-box doc-info" markdown="1">
Secara default versi npm 5.0+, ketika menjalankan perintah `npm install` akan menambahkan modul ke daftar `dependencies` di file `package.json`; sedangkan untuk versi npm sebelumnya, Anda harus menentukan opsi `--save` secara eksplisit. Kemudian, setelah itu, menjalankan `npm install --save` di direktori aplikasi akan secara otomatis menginstal modul dalam daftar dependensi.
</div>
### [Next: Hello World ](/{{ page.lang }}/starter/hello-world.html)

78
id/starter/static-files.md Executable file
View File

@@ -0,0 +1,78 @@
---
layout: page
title: Menampilkan file statis di Express
menu: starter
lang: id
---
# Menampilkan file statis di Express
Untuk menamplikan file statis seperti gambar, file CSS, dan file JavaScript, dapat menggunakan fungsi middleware bawaan `express.static` di Express.
_Signature_ fungsinya adalah:
```js
express.static(root, [options])
```
Argumen `root` menentukan direktori _root_ tempat aset statis akan ditampilkan.
Untuk informasi selengkapnya tentang argumen `options`, lihat [express.static](/{{page.lang}}/4x/api.html#express.static).
Misalnya, gunakan kode berikut untuk menyajikan gambar, file CSS, dan file JavaScript dalam direktori bernama `public`:
```js
app.use(express.static('public'))
```
Sekarang, Anda dapat melihat file yang ada di direktori `public`:
```plain-text
http://localhost:3000/images/kitten.jpg
http://localhost:3000/css/style.css
http://localhost:3000/js/app.js
http://localhost:3000/images/bg.png
http://localhost:3000/hello.html
```
<div class="doc-box doc-info">
Express mencari file yang berdasarkan lokasi dari direktori statisnya, sehingga nama direktori statis bukan bagian dari URL.
</div>
Untuk menggunakan beberapa direktori aset statis, panggil fungsi middleware `express.static` beberapa kali:
```js
app.use(express.static('public'))
app.use(express.static('files'))
```
Express akan mencari file sesuai urutan Anda mengatur direktori statis melalui fungsi middleware `express.static`.
<div class="doc-box doc-info" markdown="1">CATATAN: Untuk hasil terbaik, [gunakan reverse proxy](/{{page.lang}}/advanced/best-practice-performance.html#use-a-reverse-proxy) cache untuk meningkatkan kinerja penyajian aset statis.
</div>
Untuk membuat awalan jalur virtual (yang jalurnya sebenarnya tidak ada dalam sistem file) untuk file yang akan ditampilkan oleh fungsi `express.static`, [tentukan jalur pemasangan](/{{ page.lang }}/4x /api.html#app.use) untuk direktori statis, seperti yang ditunjukkan di bawah ini:
```js
app.use('/static', express.static('public'))
```
Sekarang, Anda dapat melihat file yang ada di direktori `public` menggunakan awalan jalur `/static`.
```plain-text
http://localhost:3000/static/images/kitten.jpg
http://localhost:3000/static/css/style.css
http://localhost:3000/static/js/app.js
http://localhost:3000/static/images/bg.png
http://localhost:3000/static/hello.html
```
Namun, jalur yang Anda berikan ke fungsi `express.static` adalah relatif terhadap direktori tempat Anda meluncurkan proses `node`. Jika Anda menjalankan aplikasi ekspres dari direktori lain, lebih aman menggunakan jalur absolut dari direktori yang ingin Anda ditampilkan:
```js
const path = require('path')
app.use('/static', express.static(path.join(__dirname, 'public')))
```
Untuk detail selengkapnya tentang fungsi `serve-static` dan opsinya, lihat [serve-static](/resources/middleware/serve-static.html).
### [Previous: Basic Routing ](/{{ page.lang }}/starter/basic-routing.html)&nbsp;&nbsp;&nbsp;&nbsp;[Next: More examples ](/{{ page.lang }}/starter/examples.html)

3071
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff