mirror of
https://github.com/expressjs/expressjs.com.git
synced 2026-02-26 02:54:58 +00:00
feat: add remark plugin to rewrite localized links in Markdown content
This commit is contained in:
committed by
GitHub
parent
e8dbc453a1
commit
cb43817148
@@ -2,11 +2,13 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import mdx from '@astrojs/mdx';
|
||||
import icon from 'astro-icon';
|
||||
import remarkRewriteLocalizedLinks from './src/utils/remark/rewrite-localized-links.mjs';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
integrations: [mdx(), icon()],
|
||||
markdown: {
|
||||
remarkPlugins: [[remarkRewriteLocalizedLinks, { prefixes: ['guide', 'starter', 'api'] }]],
|
||||
shikiConfig: {
|
||||
theme: 'github-dark',
|
||||
},
|
||||
|
||||
@@ -6,12 +6,12 @@ description: Learn how to define and use routes in Express.js applications, incl
|
||||
# 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).
|
||||
For an introduction to routing, see [Basic routing](/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 }}/5x/api.html#app.METHOD). You can also use [app.all()](/{{ page.lang }}/5x/api.html#app.all) to handle all HTTP methods and [app.use()](/{{ page.lang }}/5x/api.html#app.use) to
|
||||
specify middleware as the callback function (See [Using middleware](/{{ page.lang }}/guide/using-middleware.html) for details).
|
||||
see [app.METHOD](/api/application/app-METHOD). You can also use [app.all()](/api/application/app-all) to handle all HTTP methods and [app.use()](/api/application/app-use) to
|
||||
specify middleware as the callback function (See [Using middleware](/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.
|
||||
|
||||
@@ -50,7 +50,7 @@ app.post('/', (req, res) => {
|
||||
```
|
||||
|
||||
Express supports methods that correspond to all HTTP request methods: `get`, `post`, and so on.
|
||||
For a full list, see [app.METHOD](/{{ page.lang }}/5x/api.html#app.METHOD).
|
||||
For a full list, see [app.METHOD](/api/application/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).
|
||||
|
||||
@@ -65,7 +65,7 @@ app.all('/secret', (req, res, next) => {
|
||||
|
||||
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.
|
||||
|
||||
{% capture caution-character %} In express 5, the characters `?`, `+`, `*`, `[]`, and `()` are handled differently than in version 4, please review the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
{% capture caution-character %} In express 5, the characters `?`, `+`, `*`, `[]`, and `()` are handled differently than in version 4, please review the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-character %}
|
||||
|
||||
@@ -118,7 +118,7 @@ app.get('/random.text', (req, res) => {
|
||||
|
||||
### Route paths based on string patterns
|
||||
|
||||
{% capture caution-string-patterns %} The string patterns in Express 5 no longer work. Please refer to the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
{% capture caution-string-patterns %} The string patterns in Express 5 no longer work. Please refer to the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-string-patterns %}
|
||||
|
||||
@@ -209,7 +209,7 @@ req.params: { "genus": "Prunus", "species": "persica" }
|
||||
```
|
||||
|
||||
{% capture warning-regexp %}
|
||||
In express 5, Regexp characters are not supported in route paths, for more information please refer to the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax).{% endcapture %}
|
||||
In express 5, Regexp characters are not supported in route paths, for more information please refer to the [migration guide](/guide/migrating-5.html#path-syntax).{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=warning-regexp %}
|
||||
|
||||
@@ -239,7 +239,7 @@ In Express 4.x, <a href="https://github.com/expressjs/express/issues/2495">the `
|
||||
|
||||
<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.
|
||||
You can provide multiple callback functions that behave like [middleware](/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.
|
||||
|
||||
```js
|
||||
app.get('/user/:id', (req, res, next) => {
|
||||
@@ -334,22 +334,22 @@ app.get(
|
||||
|
||||
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 }}/5x/api.html#res.download) | Prompt a file to be downloaded. |
|
||||
| [res.end()](/{{ page.lang }}/5x/api.html#res.end) | End the response process. |
|
||||
| [res.json()](/{{ page.lang }}/5x/api.html#res.json) | Send a JSON response. |
|
||||
| [res.jsonp()](/{{ page.lang }}/5x/api.html#res.jsonp) | Send a JSON response with JSONP support. |
|
||||
| [res.redirect()](/{{ page.lang }}/5x/api.html#res.redirect) | Redirect a request. |
|
||||
| [res.render()](/{{ page.lang }}/5x/api.html#res.render) | Render a view template. |
|
||||
| [res.send()](/{{ page.lang }}/5x/api.html#res.send) | Send a response of various types. |
|
||||
| [res.sendFile()](/{{ page.lang }}/5x/api.html#res.sendFile) | Send a file as an octet stream. |
|
||||
| [res.sendStatus()](/{{ page.lang }}/5x/api.html#res.sendStatus) | Set the response status code and send its string representation as the response body. |
|
||||
| Method | Description |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| [res.download()](/api/response/res-download) | Prompt a file to be downloaded. |
|
||||
| [res.end()](/api/response/res-end) | End the response process. |
|
||||
| [res.json()](/api/response/res-json) | Send a JSON response. |
|
||||
| [res.jsonp()](/api/response/res-jsonp) | Send a JSON response with JSONP support. |
|
||||
| [res.redirect()](/api/response/res-redirect) | Redirect a request. |
|
||||
| [res.render()](/api/response/res-render) | Render a view template. |
|
||||
| [res.send()](/api/response/res-send) | Send a response of various types. |
|
||||
| [res.sendFile()](/api/response/res-sendfile) | Send a file as an octet stream. |
|
||||
| [res.sendStatus()](/api/response/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 }}/5x/api.html#router).
|
||||
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](/api.html#router).
|
||||
|
||||
Here is an example of chained route handlers that are defined by using `app.route()`.
|
||||
|
||||
@@ -410,7 +410,7 @@ 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.
|
||||
|
||||
But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the Router constructor [reference](/{{ page.lang }}/5x/api.html#app.use).
|
||||
But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the Router constructor [reference](/api/application/app-use).
|
||||
|
||||
```js
|
||||
const router = express.Router({ mergeParams: true });
|
||||
|
||||
@@ -6,12 +6,12 @@ description: Learn how to define and use routes in Express.js applications, incl
|
||||
# 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).
|
||||
For an introduction to routing, see [Basic routing](/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 }}/5x/api.html#app.METHOD). You can also use [app.all()](/{{ page.lang }}/5x/api.html#app.all) to handle all HTTP methods and [app.use()](/{{ page.lang }}/5x/api.html#app.use) to
|
||||
specify middleware as the callback function (See [Using middleware](/{{ page.lang }}/guide/using-middleware.html) for details).
|
||||
see [app.METHOD](/api/application/app-METHOD). You can also use [app.all()](/api/application/app-all) to handle all HTTP methods and [app.use()](/api/application/app-use) to
|
||||
specify middleware as the callback function (See [Using middleware](/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.
|
||||
|
||||
@@ -50,7 +50,7 @@ app.post('/', (req, res) => {
|
||||
```
|
||||
|
||||
Express supports methods that correspond to all HTTP request methods: `get`, `post`, and so on.
|
||||
For a full list, see [app.METHOD](/{{ page.lang }}/5x/api.html#app.METHOD).
|
||||
For a full list, see [app.METHOD](/api/application/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).
|
||||
|
||||
@@ -65,7 +65,7 @@ app.all('/secret', (req, res, next) => {
|
||||
|
||||
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.
|
||||
|
||||
{% capture caution-character %} In express 5, the characters `?`, `+`, `*`, `[]`, and `()` are handled differently than in version 4, please review the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
{% capture caution-character %} In express 5, the characters `?`, `+`, `*`, `[]`, and `()` are handled differently than in version 4, please review the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-character %}
|
||||
|
||||
@@ -118,7 +118,7 @@ app.get('/random.text', (req, res) => {
|
||||
|
||||
### Route paths based on string patterns
|
||||
|
||||
{% capture caution-string-patterns %} The string patterns in Express 5 no longer work. Please refer to the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
{% capture caution-string-patterns %} The string patterns in Express 5 no longer work. Please refer to the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-string-patterns %}
|
||||
|
||||
@@ -209,7 +209,7 @@ req.params: { "genus": "Prunus", "species": "persica" }
|
||||
```
|
||||
|
||||
{% capture warning-regexp %}
|
||||
In express 5, Regexp characters are not supported in route paths, for more information please refer to the [migration guide](/{{ page.lang }}/guide/migrating-5.html#path-syntax).{% endcapture %}
|
||||
In express 5, Regexp characters are not supported in route paths, for more information please refer to the [migration guide](/guide/migrating-5.html#path-syntax).{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=warning-regexp %}
|
||||
|
||||
@@ -239,7 +239,7 @@ In Express 4.x, <a href="https://github.com/expressjs/express/issues/2495">the `
|
||||
|
||||
<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.
|
||||
You can provide multiple callback functions that behave like [middleware](/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.
|
||||
|
||||
```js
|
||||
app.get('/user/:id', (req, res, next) => {
|
||||
@@ -334,22 +334,22 @@ app.get(
|
||||
|
||||
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 }}/5x/api.html#res.download) | Prompt a file to be downloaded. |
|
||||
| [res.end()](/{{ page.lang }}/5x/api.html#res.end) | End the response process. |
|
||||
| [res.json()](/{{ page.lang }}/5x/api.html#res.json) | Send a JSON response. |
|
||||
| [res.jsonp()](/{{ page.lang }}/5x/api.html#res.jsonp) | Send a JSON response with JSONP support. |
|
||||
| [res.redirect()](/{{ page.lang }}/5x/api.html#res.redirect) | Redirect a request. |
|
||||
| [res.render()](/{{ page.lang }}/5x/api.html#res.render) | Render a view template. |
|
||||
| [res.send()](/{{ page.lang }}/5x/api.html#res.send) | Send a response of various types. |
|
||||
| [res.sendFile()](/{{ page.lang }}/5x/api.html#res.sendFile) | Send a file as an octet stream. |
|
||||
| [res.sendStatus()](/{{ page.lang }}/5x/api.html#res.sendStatus) | Set the response status code and send its string representation as the response body. |
|
||||
| Method | Description |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| [res.download()](/api/response/res-download) | Prompt a file to be downloaded. |
|
||||
| [res.end()](/api/response/res-end) | End the response process. |
|
||||
| [res.json()](/api/response/res-json) | Send a JSON response. |
|
||||
| [res.jsonp()](/api/response/res-jsonp) | Send a JSON response with JSONP support. |
|
||||
| [res.redirect()](/api/response/res-redirect) | Redirect a request. |
|
||||
| [res.render()](/api/response/res-render) | Render a view template. |
|
||||
| [res.send()](/api/response/res-send) | Send a response of various types. |
|
||||
| [res.sendFile()](/api/response/res-sendFile) | Send a file as an octet stream. |
|
||||
| [res.sendStatus()](/api/response/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 }}/5x/api.html#router).
|
||||
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](/api.html#router).
|
||||
|
||||
Here is an example of chained route handlers that are defined by using `app.route()`.
|
||||
|
||||
@@ -410,7 +410,7 @@ 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.
|
||||
|
||||
But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the Router constructor [reference](/{{ page.lang }}/5x/api.html#app.use).
|
||||
But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the Router constructor [reference](/api/application/app-use).
|
||||
|
||||
```js
|
||||
const router = express.Router({ mergeParams: true });
|
||||
|
||||
417
astro/src/content/docs/es/5x/guide/routing.md
Executable file
417
astro/src/content/docs/es/5x/guide/routing.md
Executable file
@@ -0,0 +1,417 @@
|
||||
---
|
||||
title: Express routing
|
||||
description: Learn how to define and use routes in Express.js applications, including route methods, route paths, parameters, and using Router for modular routing.
|
||||
---
|
||||
|
||||
# Routing
|
||||
|
||||
_Routing_ refers to how an application's endpoints (URIs) respond to client requests.
|
||||
For an introduction to routing, see [Basic routing](/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](/api/application/app-METHOD). You can also use [app.all()](/api/application/app-all) to handle all HTTP methods and [app.use()](/api/application/app-use) to
|
||||
specify middleware as the callback function (See [Using middleware](/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](/api/application/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.
|
||||
|
||||
{% capture caution-character %} In express 5, the characters `?`, `+`, `*`, `[]`, and `()` are handled differently than in version 4, please review the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-character %}
|
||||
|
||||
{% capture note-dollar-character %}In express 4, regular expression characters such as `$` need to be escaped with a `\`.
|
||||
{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=note-dollar-character %}
|
||||
|
||||
{% capture note-path-to-regexp %}
|
||||
|
||||
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 Playground Router](https://bjohansebas.github.io/playground-router/) is a handy tool for testing basic Express routes, although it does not support pattern matching.
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
{% include admonitions/note.html content=note-path-to-regexp %}
|
||||
|
||||
{% capture query-string-note %}
|
||||
|
||||
Query strings are not part of the route path.
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
{% include admonitions/warning.html content=query-string-note %}
|
||||
|
||||
### 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');
|
||||
});
|
||||
```
|
||||
|
||||
### Route paths based on string patterns
|
||||
|
||||
{% capture caution-string-patterns %} The string patterns in Express 5 no longer work. Please refer to the [migration guide](/guide/migrating-5.html#path-syntax) for more information.{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=caution-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');
|
||||
});
|
||||
```
|
||||
|
||||
### 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" }
|
||||
```
|
||||
|
||||
{% capture warning-regexp %}
|
||||
In express 5, Regexp characters are not supported in route paths, for more information please refer to the [migration guide](/guide/migrating-5.html#path-syntax).{% endcapture %}
|
||||
|
||||
{% include admonitions/caution.html content=warning-regexp %}
|
||||
|
||||
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"}
|
||||
```
|
||||
|
||||
{% capture escape-advisory %}
|
||||
|
||||
Because the regular expression is usually part of a literal string, be sure to escape any `\` characters with an additional backslash, for example `\\d+`.
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
{% include admonitions/warning.html content=escape-advisory %}
|
||||
|
||||
{% capture warning-version %}
|
||||
|
||||
In Express 4.x, <a href="https://github.com/expressjs/express/issues/2495">the `*` character in regular expressions is not interpreted in the usual way</a>. As a workaround, use `{0,}` instead of `*`. This will likely be fixed in Express 5.
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
{% include admonitions/warning.html content=warning-version %}
|
||||
|
||||
<h2 id="route-handlers">Route handlers</h2>
|
||||
|
||||
You can provide multiple callback functions that behave like [middleware](/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.
|
||||
|
||||
```js
|
||||
app.get('/user/:id', (req, res, next) => {
|
||||
if (req.params.id === '0') {
|
||||
return next('route');
|
||||
}
|
||||
res.send(`User ${req.params.id}`);
|
||||
});
|
||||
|
||||
app.get('/user/:id', (req, res) => {
|
||||
res.send('Special handler for user ID 0');
|
||||
});
|
||||
```
|
||||
|
||||
In this example:
|
||||
|
||||
- `GET /user/5` → handled by first route → sends "User 5"
|
||||
- `GET /user/0` → first route calls `next('route')`, skipping to the next matching `/user/:id` 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()](/api/response/res-download) | Prompt a file to be downloaded. |
|
||||
| [res.end()](/api/response/res-end) | End the response process. |
|
||||
| [res.json()](/api/response/res-json) | Send a JSON response. |
|
||||
| [res.jsonp()](/api/response/res-jsonp) | Send a JSON response with JSONP support. |
|
||||
| [res.redirect()](/api/response/res-redirect) | Redirect a request. |
|
||||
| [res.render()](/api/response/res-render) | Render a view template. |
|
||||
| [res.send()](/api/response/res-send) | Send a response of various types. |
|
||||
| [res.sendFile()](/api/response/res-sendFile) | Send a file as an octet stream. |
|
||||
| [res.sendStatus()](/api/response/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](/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.
|
||||
|
||||
But if the parent route `/birds` has path parameters, it will not be accessible by default from the sub-routes. To make it accessible, you will need to pass the `mergeParams` option to the Router constructor [reference](/api/application/app-use).
|
||||
|
||||
```js
|
||||
const router = express.Router({ mergeParams: true });
|
||||
```
|
||||
236
astro/src/utils/remark/rewrite-localized-links.mjs
Normal file
236
astro/src/utils/remark/rewrite-localized-links.mjs
Normal file
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* Remark plugin that rewrites selected internal links in Markdown/MDX content.
|
||||
*
|
||||
* Behavior summary:
|
||||
* - Rewrites only absolute internal paths that match configured prefixes
|
||||
* (e.g. `/guide/...`, `/starter/...`, `/api/...`).
|
||||
* - Adds language segment from file path context.
|
||||
* - Adds docs version segment for configured collections (by default: `docs`).
|
||||
* - Preserves query string and hash fragments.
|
||||
* - Skips already-localized paths (e.g. `/en/...`).
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} RewriteContext
|
||||
* @property {'docs'|'resources'|undefined} collection Collection inferred from source path.
|
||||
* @property {string} lang Language inferred from source path or fallback.
|
||||
* @property {string|undefined} version Version inferred from source path when applicable.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} RemarkRewriteLocalizedLinksOptions
|
||||
* @property {string[]} [prefixes=['guide']] Root path segments that should be rewritten.
|
||||
* @property {string} [defaultLang='en'] Language fallback when source path is not parseable.
|
||||
* @property {string} [defaultVersion='5x'] Version fallback for docs pages without explicit version segment.
|
||||
* @property {string[]} [versionedCollections=['docs']] Collections that should include version in rewritten links.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Validates whether a path segment matches version format (e.g. `5x`, `4x`).
|
||||
* @param {string} value
|
||||
*/
|
||||
function isVersionSegment(value) {
|
||||
return /^\d+x$/.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Splits URL into pathname and suffix (`?query#hash`).
|
||||
* @param {string} url
|
||||
*/
|
||||
function splitPathAndSuffix(url) {
|
||||
const match = url.match(/^([^?#]*)(.*)$/);
|
||||
if (!match) {
|
||||
return { pathname: url, suffix: '' };
|
||||
}
|
||||
|
||||
return {
|
||||
pathname: match[1],
|
||||
suffix: match[2] || '',
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether pathname already starts with language code (e.g. `/en/...`, `/pt-br/...`).
|
||||
* @param {string} pathname
|
||||
*/
|
||||
function hasLanguagePrefix(pathname) {
|
||||
return /^\/[a-z]{2}(?:-[a-z]{2})?(?:\/|$)/i.test(pathname);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds trailing slash for non-file paths.
|
||||
* @param {string} pathname
|
||||
*/
|
||||
function ensureTrailingSlash(pathname) {
|
||||
if (pathname.endsWith('/')) {
|
||||
return pathname;
|
||||
}
|
||||
|
||||
if (/\.[a-z\d]+$/i.test(pathname)) {
|
||||
return pathname;
|
||||
}
|
||||
|
||||
return `${pathname}/`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Derives collection/lang/version from the Markdown source file path.
|
||||
*
|
||||
* Expected path examples:
|
||||
* - `/.../src/content/docs/en/5x/guide/routing.md`
|
||||
* - `/.../src/content/resources/en/contributing.md`
|
||||
*
|
||||
* @param {string|undefined} filePath
|
||||
* @param {string} defaultLang
|
||||
* @param {string} defaultVersion
|
||||
* @returns {RewriteContext}
|
||||
*/
|
||||
function deriveContextFromFile(filePath, defaultLang, defaultVersion) {
|
||||
const normalizedPath = (filePath || '').replaceAll('\\', '/');
|
||||
|
||||
const docsMarker = '/src/content/docs/';
|
||||
const resourcesMarker = '/src/content/resources/';
|
||||
|
||||
if (normalizedPath.includes(docsMarker)) {
|
||||
const relativePath = normalizedPath.split(docsMarker)[1] || '';
|
||||
const segments = relativePath.split('/').filter(Boolean);
|
||||
|
||||
const lang = segments[0] || defaultLang;
|
||||
const version = isVersionSegment(segments[1]) ? segments[1] : defaultVersion;
|
||||
|
||||
return {
|
||||
collection: 'docs',
|
||||
lang,
|
||||
version,
|
||||
};
|
||||
}
|
||||
|
||||
if (normalizedPath.includes(resourcesMarker)) {
|
||||
const relativePath = normalizedPath.split(resourcesMarker)[1] || '';
|
||||
const segments = relativePath.split('/').filter(Boolean);
|
||||
|
||||
return {
|
||||
collection: 'resources',
|
||||
lang: segments[0] || defaultLang,
|
||||
version: undefined,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
collection: undefined,
|
||||
lang: defaultLang,
|
||||
version: defaultVersion,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a pathname should be rewritten according to configured prefixes.
|
||||
* @param {string} pathname
|
||||
* @param {Set<string>} prefixesSet
|
||||
*/
|
||||
function shouldRewritePath(pathname, prefixesSet) {
|
||||
if (!pathname.startsWith('/')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const normalized = pathname.replace(/^\/+/, '').replace(/\/+$/, '');
|
||||
const [firstSegment] = normalized.split('/');
|
||||
|
||||
return prefixesSet.has(firstSegment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the final localized/versioned pathname.
|
||||
* @param {string} pathname
|
||||
* @param {RewriteContext} context
|
||||
* @param {Set<string>} versionedCollections
|
||||
*/
|
||||
function rewritePath(pathname, context, versionedCollections) {
|
||||
const cleanTarget = pathname.replace(/^\/+/, '').replace(/\/+$/, '');
|
||||
const segments = [context.lang];
|
||||
|
||||
if (context.collection && versionedCollections.has(context.collection) && context.version) {
|
||||
segments.push(context.version);
|
||||
}
|
||||
|
||||
segments.push(cleanTarget);
|
||||
|
||||
const rewritten = `/${segments.join('/')}`.replace(/\/+/g, '/');
|
||||
return ensureTrailingSlash(rewritten);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rewrites a URL when it matches plugin rules, otherwise returns original value.
|
||||
* @param {string} url
|
||||
* @param {RewriteContext} context
|
||||
* @param {Set<string>} prefixesSet
|
||||
* @param {Set<string>} versionedCollections
|
||||
*/
|
||||
function rewriteUrl(url, context, prefixesSet, versionedCollections) {
|
||||
if (typeof url !== 'string' || !url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const { pathname, suffix } = splitPathAndSuffix(url);
|
||||
|
||||
if (!pathname || pathname === '/' || pathname.startsWith('#')) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (hasLanguagePrefix(pathname)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
if (!shouldRewritePath(pathname, prefixesSet)) {
|
||||
return url;
|
||||
}
|
||||
|
||||
const rewrittenPath = rewritePath(pathname, context, versionedCollections);
|
||||
return `${rewrittenPath}${suffix}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic depth-first AST traversal utility.
|
||||
* @param {any} node
|
||||
* @param {(node: any) => void} visitor
|
||||
*/
|
||||
function walkTree(node, visitor) {
|
||||
if (!node || typeof node !== 'object') {
|
||||
return;
|
||||
}
|
||||
|
||||
visitor(node);
|
||||
|
||||
if (Array.isArray(node.children)) {
|
||||
for (const child of node.children) {
|
||||
walkTree(child, visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remark plugin factory.
|
||||
*
|
||||
* @param {RemarkRewriteLocalizedLinksOptions} [options]
|
||||
*/
|
||||
export default function remarkRewriteLocalizedLinks(options = {}) {
|
||||
const {
|
||||
prefixes = ['guide'],
|
||||
defaultLang = 'en',
|
||||
defaultVersion = '5x',
|
||||
versionedCollections = ['docs'],
|
||||
} = options;
|
||||
|
||||
const prefixesSet = new Set(prefixes);
|
||||
const versionedCollectionsSet = new Set(versionedCollections);
|
||||
|
||||
return (tree, file) => {
|
||||
const context = deriveContextFromFile(file?.path, defaultLang, defaultVersion);
|
||||
|
||||
walkTree(tree, (node) => {
|
||||
if (node.type === 'link' || node.type === 'definition') {
|
||||
node.url = rewriteUrl(node.url, context, prefixesSet, versionedCollectionsSet);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user