[JavaScript, Node.JS, Программирование, Разработка веб-сайтов] Руководство по Express.js. Часть 2 (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Доброго времени суток, друзья!
Представляю вашему вниманию перевод второй части Руководства по Express — веб-феймворку для Node.js автора Flavio Copes.
Предполагается, что вы знакомы с Node.js. Если нет, то прошу сюда.
Без дальнейших предисловий.
11. Управление куки
Для управления куки используйте метод Response.cookie().
Например:
res.cookie('username', 'John')
Данный метод принимает третий аргумент, содержащий определенные настройки:
res.cookie('username', 'John', { domain: '.exmaple.com', path: '/admin', secure: true })
res.cookie('username', 'John', { expires: new Date(Date.now() + 900000), httpOnly: true })
Самыми полезными настройками являются следующие:
Значение
Описание
domain
название домена куки
expires
определяет время жизни куки. При отсутствии или при значении, равном 0, куки будет удалена по окончанию сессии (при закрытии вкладки браузера)
httpOnly
если true, то куки будет доступна только через веб-сервер
maxAge
время жизни куки относительно текущего времени, определяется в миллисекундах
path
путь к куки. По умолчанию /
secure
если true, то куки будет доступна только по протоколу HTTPS
signed
делает куки подписанной
sameSite
если true, то куки доступна только запросам из одного источника
Куки можно удалить с помощью:
res.clearCookie('username')
12. Работа с HTTP-заголовками
Получение заголовков из запроса
Заголовки запроса можно получить через свойство Request.headers:
app.get('/', (req, res) => {
console.log(req.headers)
})
Метод Request.header() используется для получения конкретного заголовка:
app.get('/', (req, res) => {
req.header('User-Agent')
})
Изменение значения заголовка в ответе
Значение любого заголовка можно изменить с помощью метода Response.set():
res.set('Content-Type': 'text/html')
Для заголовка Content-Type имеется сокращенный вариант:
res.type('.html') // => 'text/html'
res.type('html') // => 'text/html'
res.type('json') // => 'application/json'
res.type('application/json') // => 'application/json'
res.type('png') // => 'image/png'
13. Перенаправления
Перенаправления являются распространенным явлением в веб-разработке. Для перенаправления используется метод Response.redirect():
res.redirect('/go-there')
Это создает постоянное перенаправление (302).
Временное перенаправление (301) можно сделать так:
res.redirect(301, '/go-there')
В качестве аргумента может использоваться абсолютный путь (/go-there), абсолютный URL (https://anothersite.com), относительный путь (go-there) или… для того, чтобы подняться на один уровень выше.
res.redirect('../go-there')
res.redirect('..')
Также можно вернуться к странице, указанной в заголовке Referer (по умолчанию имеет значение /):
res.redirect('back')
14. Маршрутизация
Маршрутизация или роутинг — это определение того, что должно произойти при обращении к конкретному URL. Другими словами, это определение того, какие части приложения должны обрабатывать конкретные запросы.
В примере Hello World мы использовали следующее:
app.get('/', (req, res) => {/* */})
Здесь обрабатываем GET-запросы к корневому домену /, отправляя определенный ответ.
Именованные параметры
Что если мы хотим обрабатывать определенные запросы. Допустим, мы хотим принимать строку и возвращать эту же строку, но состоящую только из заглавных букв и, при этом, не хотим использовать строку запроса. В этом случае нам на помощь приходят именованные параметры:
app.get('/uppercase/:theValue', (req, res) => res.send(req.params.theValue.toUpperCase()))
Если мы отправим такой запрос: /uppercase/test, то получим TEST в теле ответа.
В одном URL можно указывать несколько именованных параметров, все они будут сохранены в свойстве req.params.
Использлование регулярного выражения для определения пути
Для обработки нескольких запросов одним роутером можно использовать регулярные выражения:
app.get(/post/, (req, res) => {/* */})
В данном случае совпадения будут найдены для /post, /post/first, /thepost, /posting/something и т.д.
15. SOP (политика общего происхождения или одного источника)
JavaScript-приложения, запущенные в браузере, как правило, могут получать только ресурсы, находящиеся в том же источнике (origin — протокол, хост и порт).
Загрузка изображений или стилей/скриптов, обычно, работает, но запросы XHR или Fetch к другому серверу терпят неудачу до тех пор, пока сервер не разрешит совместное использование ресурсов.
Данный механизм называется CORS (Cross-Origin Resource Sharing).
Загрузка веб-шрифтов с помощью @font-face также следует этой политике, впрочем, как и загрузка других вещей (таких как текстуры WebGL или ресурсы для метода drawImage Canvas API).
Более того, CORS применяется и в отношении ES6 модулей.
Если вы не определите CORS на сервере для отправки ответов на запросы из других источников, эти запросы будут отклонены.
Пример отклонения Fetch-запроса:
Пример отклонения XHR-запроса:
Запросы из другого источника завершаются неудачно, если обращение осуществляется:
- К другому домену
- К другому поддомену
- К другому порту
- К другому протоколу
Это делается для вашей безопасности: для того, чтобы злонамеренные пользователи не сломали приложение.
Однако, если вы контролируете и сервер, и клиента, у вас есть все основания для того, чтобы разрешить им общаться между собой.
Как это сделать?
Это зависит от того, какие технологии используются на сервере.
Пример с Express
Если вы используете Node.js и фреймворк Express, ППО CORS — это то, что вам нужно.
Вот реализация простого сервера:
const express = require('express')
const app = express()
app.get('/without-cors', (req, res, next) => {
res.json({ msg: ':( no cors, no party!' })
})
const server = app.listen(3000, () => {
console.log('Listening on port %s', server.address().port)
})
Если вы отправите запрос к этому серверу из другого источника, то получите ошибку.
Для того, чтобы это стало возможным, необходимо определить cors и добавить его в качестве ППО в роутер:
const express = require('express')
const cors = require('cors')
const app = express()
app.get('/with-cors', cors(), (req, res, next) => {
res.json({ msg: 'With cors it work! :)' })
})
Я сделал небольшой пример. Вот код клиента: https://glitch.com/edit/#!/flavio-cors-client
А вот код сервера: https://glitch.com/edit/#!/flaviocopes-cors-example-express
Обратите внимание, что ответы на неудачные запросы все равно отправляются. В соответствующем разделе инструментов разработчика (Network, сеть) можно увидеть сообщение от сервера:
Разрешаем только запросы из определенного источника
У рассмотренного подхода есть один существенный недостаток: любой запрос будет рассматриваться сервером как допустимый.
Как видите, ответ содержит заголовок Access-Control-Allow-Origin со значением *:
Нам необходимо настроить сервер таким образом, чтобы он допускал запросы лишь из определенных источников.
Перепишем наш код:
const cors = require('cors')
const corsOptions = {
origin: 'https://yourdomain.com'
}
app.get('/products/:id', cors(corsOptions), (req, res, next) => {
// ...
})
Также можно определить несколько допустимых источников:
const whitelist = ['https://example.com', 'https://example2.com']
const corsOptions = {
origin: (origin, cb) =>
(whitelist.indexOf(origin) !== -1)
? cb(null, true)
: cb(new Error('Not allowed by CORS'))
}
Отправка предаврительных запросов
Некоторые запросы являются простыми, например, GET, POST, HEAD.
Что касается POST-запроса, то он является простым только в том случае, если его заголовок Content-Type имеет одно из следующих значений:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
Все остальные запросы нуждаются в отправке предварительного запроса. Это требуется браузеру для предоставления или отказа в доступе на основании информации из OPTIONS-запроса.
Предварительный запрос содержит несколько заголовков, позволяющих браузеру определить права на доступ:
OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST
Access-Control-Request-Headers: origin, x-requested-with, accept
Origin: https://yourdomain.com
Ответ сервера выглядит примерно так:
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://yourdomain.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE
Мы провели проверку для POST-запроса, однако сервер сообщил нам, что мы можем использовать и другие запросы.
Возвращаясь к Express, вот как сервер должен обрабатывать OPTIONS-запросы:
const express = require('express')
const cors = require('cors')
const app = express()
// разрешаем OPTIONS для одного ресурса
app.options('the/resource/you/request', cors())
// разрешаем OPTIONS для всех ресурсов
app.options('*', cors())
На сегодня это все. В следующей части мы поговорим о шаблонизации (Pug), промежуточном программном обеспечении (промежуточном слое), работе со статическими файлами, отправке файлов и сессиях.
Следите за обновлениями. Благодарю за внимание и хорошего дня.
===========
Источник:
habr.com
===========
===========
Автор оригинала: Flavio Copes
===========Похожие новости:
- [D, Go, Rust, Программирование] Портируем утилиту командной строки с Go/Rust на D (перевод)
- [Программирование, Go] Вариативные функции в Go (перевод)
- [C, C++, Open source, Программирование] Проверка QEMU с помощью PVS-Studio
- [C, C++, Open source, Программирование] Checking QEMU using PVS-Studio
- [JavaScript, Программирование] Как я искал работу в Берлине
- [PHP, Программирование] Перечисления в PHP
- [JavaScript, Программирование] Как улучшить SEO с помощью Next.js (перевод)
- [Разработка веб-сайтов, PHP] Ты решил написать свой фреймворк. Стоило оно того?
- [Ненормальное программирование, Программирование, Совершенный код] Dark code-style academy: line breaks, spacing, and indentation
- [Разработка веб-сайтов, JavaScript, Программирование] Рецепты по приготовлению оффлайн-приложений (перевод)
Теги для поиска: #_javascript, #_node.js, #_programmirovanie (Программирование), #_razrabotka_vebsajtov (Разработка веб-сайтов), #_javascript, #_node.js, #_nodejs, #_node, #_express.js, #_expressjs, #_express, #_guide, #_rukovodstvo (руководство), #_javascript, #_node.js, #_programmirovanie (
Программирование
), #_razrabotka_vebsajtov (
Разработка веб-сайтов
)
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:29
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Доброго времени суток, друзья! Представляю вашему вниманию перевод второй части Руководства по Express — веб-феймворку для Node.js автора Flavio Copes. Предполагается, что вы знакомы с Node.js. Если нет, то прошу сюда. Без дальнейших предисловий. 11. Управление куки Для управления куки используйте метод Response.cookie(). Например: res.cookie('username', 'John')
Данный метод принимает третий аргумент, содержащий определенные настройки: res.cookie('username', 'John', { domain: '.exmaple.com', path: '/admin', secure: true })
res.cookie('username', 'John', { expires: new Date(Date.now() + 900000), httpOnly: true }) Самыми полезными настройками являются следующие: Значение Описание domain название домена куки expires определяет время жизни куки. При отсутствии или при значении, равном 0, куки будет удалена по окончанию сессии (при закрытии вкладки браузера) httpOnly если true, то куки будет доступна только через веб-сервер maxAge время жизни куки относительно текущего времени, определяется в миллисекундах path путь к куки. По умолчанию / secure если true, то куки будет доступна только по протоколу HTTPS signed делает куки подписанной sameSite если true, то куки доступна только запросам из одного источника Куки можно удалить с помощью: res.clearCookie('username')
12. Работа с HTTP-заголовками Получение заголовков из запроса Заголовки запроса можно получить через свойство Request.headers: app.get('/', (req, res) => {
console.log(req.headers) }) Метод Request.header() используется для получения конкретного заголовка: app.get('/', (req, res) => {
req.header('User-Agent') }) Изменение значения заголовка в ответе Значение любого заголовка можно изменить с помощью метода Response.set(): res.set('Content-Type': 'text/html')
Для заголовка Content-Type имеется сокращенный вариант: res.type('.html') // => 'text/html'
res.type('html') // => 'text/html' res.type('json') // => 'application/json' res.type('application/json') // => 'application/json' res.type('png') // => 'image/png' 13. Перенаправления Перенаправления являются распространенным явлением в веб-разработке. Для перенаправления используется метод Response.redirect(): res.redirect('/go-there')
Это создает постоянное перенаправление (302). Временное перенаправление (301) можно сделать так: res.redirect(301, '/go-there')
В качестве аргумента может использоваться абсолютный путь (/go-there), абсолютный URL (https://anothersite.com), относительный путь (go-there) или… для того, чтобы подняться на один уровень выше. res.redirect('../go-there')
res.redirect('..') Также можно вернуться к странице, указанной в заголовке Referer (по умолчанию имеет значение /): res.redirect('back')
14. Маршрутизация Маршрутизация или роутинг — это определение того, что должно произойти при обращении к конкретному URL. Другими словами, это определение того, какие части приложения должны обрабатывать конкретные запросы. В примере Hello World мы использовали следующее: app.get('/', (req, res) => {/* */})
Здесь обрабатываем GET-запросы к корневому домену /, отправляя определенный ответ. Именованные параметры Что если мы хотим обрабатывать определенные запросы. Допустим, мы хотим принимать строку и возвращать эту же строку, но состоящую только из заглавных букв и, при этом, не хотим использовать строку запроса. В этом случае нам на помощь приходят именованные параметры: app.get('/uppercase/:theValue', (req, res) => res.send(req.params.theValue.toUpperCase()))
Если мы отправим такой запрос: /uppercase/test, то получим TEST в теле ответа. В одном URL можно указывать несколько именованных параметров, все они будут сохранены в свойстве req.params. Использлование регулярного выражения для определения пути Для обработки нескольких запросов одним роутером можно использовать регулярные выражения: app.get(/post/, (req, res) => {/* */})
В данном случае совпадения будут найдены для /post, /post/first, /thepost, /posting/something и т.д. 15. SOP (политика общего происхождения или одного источника) JavaScript-приложения, запущенные в браузере, как правило, могут получать только ресурсы, находящиеся в том же источнике (origin — протокол, хост и порт). Загрузка изображений или стилей/скриптов, обычно, работает, но запросы XHR или Fetch к другому серверу терпят неудачу до тех пор, пока сервер не разрешит совместное использование ресурсов. Данный механизм называется CORS (Cross-Origin Resource Sharing). Загрузка веб-шрифтов с помощью @font-face также следует этой политике, впрочем, как и загрузка других вещей (таких как текстуры WebGL или ресурсы для метода drawImage Canvas API). Более того, CORS применяется и в отношении ES6 модулей. Если вы не определите CORS на сервере для отправки ответов на запросы из других источников, эти запросы будут отклонены. Пример отклонения Fetch-запроса: Пример отклонения XHR-запроса: Запросы из другого источника завершаются неудачно, если обращение осуществляется:
Это делается для вашей безопасности: для того, чтобы злонамеренные пользователи не сломали приложение. Однако, если вы контролируете и сервер, и клиента, у вас есть все основания для того, чтобы разрешить им общаться между собой. Как это сделать? Это зависит от того, какие технологии используются на сервере. Пример с Express Если вы используете Node.js и фреймворк Express, ППО CORS — это то, что вам нужно. Вот реализация простого сервера: const express = require('express')
const app = express() app.get('/without-cors', (req, res, next) => { res.json({ msg: ':( no cors, no party!' }) }) const server = app.listen(3000, () => { console.log('Listening on port %s', server.address().port) }) Если вы отправите запрос к этому серверу из другого источника, то получите ошибку. Для того, чтобы это стало возможным, необходимо определить cors и добавить его в качестве ППО в роутер: const express = require('express')
const cors = require('cors') const app = express() app.get('/with-cors', cors(), (req, res, next) => { res.json({ msg: 'With cors it work! :)' }) }) Я сделал небольшой пример. Вот код клиента: https://glitch.com/edit/#!/flavio-cors-client А вот код сервера: https://glitch.com/edit/#!/flaviocopes-cors-example-express Обратите внимание, что ответы на неудачные запросы все равно отправляются. В соответствующем разделе инструментов разработчика (Network, сеть) можно увидеть сообщение от сервера: Разрешаем только запросы из определенного источника У рассмотренного подхода есть один существенный недостаток: любой запрос будет рассматриваться сервером как допустимый. Как видите, ответ содержит заголовок Access-Control-Allow-Origin со значением *: Нам необходимо настроить сервер таким образом, чтобы он допускал запросы лишь из определенных источников. Перепишем наш код: const cors = require('cors')
const corsOptions = { origin: 'https://yourdomain.com' } app.get('/products/:id', cors(corsOptions), (req, res, next) => { // ... }) Также можно определить несколько допустимых источников: const whitelist = ['https://example.com', 'https://example2.com']
const corsOptions = { origin: (origin, cb) => (whitelist.indexOf(origin) !== -1) ? cb(null, true) : cb(new Error('Not allowed by CORS')) } Отправка предаврительных запросов Некоторые запросы являются простыми, например, GET, POST, HEAD. Что касается POST-запроса, то он является простым только в том случае, если его заголовок Content-Type имеет одно из следующих значений:
Все остальные запросы нуждаются в отправке предварительного запроса. Это требуется браузеру для предоставления или отказа в доступе на основании информации из OPTIONS-запроса. Предварительный запрос содержит несколько заголовков, позволяющих браузеру определить права на доступ: OPTIONS /the/resource/you/request
Access-Control-Request-Method: POST Access-Control-Request-Headers: origin, x-requested-with, accept Origin: https://yourdomain.com Ответ сервера выглядит примерно так: HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://yourdomain.com Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE Мы провели проверку для POST-запроса, однако сервер сообщил нам, что мы можем использовать и другие запросы. Возвращаясь к Express, вот как сервер должен обрабатывать OPTIONS-запросы: const express = require('express')
const cors = require('cors') const app = express() // разрешаем OPTIONS для одного ресурса app.options('the/resource/you/request', cors()) // разрешаем OPTIONS для всех ресурсов app.options('*', cors()) На сегодня это все. В следующей части мы поговорим о шаблонизации (Pug), промежуточном программном обеспечении (промежуточном слое), работе со статическими файлами, отправке файлов и сессиях. Следите за обновлениями. Благодарю за внимание и хорошего дня. =========== Источник: habr.com =========== =========== Автор оригинала: Flavio Copes ===========Похожие новости:
Программирование ), #_razrabotka_vebsajtov ( Разработка веб-сайтов ) |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 17:29
Часовой пояс: UTC + 5