Серия статей:
- [Младший брат, ты хочешь знать о кросс-доменном] JSONP
- [Брат, ты хочешь знать о кросс-доменном] Основы CORS
- [Брат, ты хочешь узнать о междоменных ресурсах] Расширенные статьи CORS
- [Брат, ты хочешь знать о кросс-доменном] обратном прокси NGINX
- [Брат, ты хочешь знать о кросс-доменном] ServerProxy
в серии статейпервый разПричина, по которой мы говорили о междоменных проблемах, заключается в том, чтобраузерПолитика одного и того же происхождения. Тогда связь между серверами не будет ограничена соответствующими условиями. Так можем ли мы использовать сервер того же домена, чтобы помочь получить доступ к API других доменных имен? Если да, сможем ли мы получить доступ к кому угодно мы хотим??Ограничения, несуществующие...
PS: эта статья включает в себя некоторые базовые знания, и вам нужно немного ихnodejs
koa
Базовый. В основном используется для созданияweb
Сервер, конечно, не беда, если у вас нет фундамента, идите первымnode koaПроверьте официальный сайт. Вы не можете вернуться???
как вам будет угодно 😄
Создать каталог проекта
Перейдите к предыдущему шагу, в этой статье будет создан только серверный проект, поэтому нет необходимости./fe
Создайте интерфейсный проект в каталоге, каталог проекта выглядит следующим образом.
в,serverProxy
directory является основным каталогом проекта.www
Каталог — это каталог хостинга для статических файлов внешнего интерфейса.base.js
Для внутренней основной программыadd.js subtract.js
соответственно представляют собой две сторонние службы, которые обеспечивают возможность вычисления сложения и вычитания соответственно.
установить коа
- сначала выполнить
cd be/serverProxy
Переключить путь кserverProxy
- воплощать в жизнь
npm init -y
Инициализировать как проект узла - воплощать в жизнь
npm i koa -S
Заканчиватьkoa
установка
проверятьkoa
Установка завершена
- редактировать
base.js
напишите следующее
const Koa = require('koa');
const app = new Koa();
const PORT = 1234;
app.use((ctx) => {
ctx.body = 'Hello World';
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
- Выполнить, когда закончите
node base.js
Посмотрите вывод из командной строкиthe server is listen: 1234
Указывает, что запуск прошел успешно - доступ через браузерlocalhost
В настоящее времякод
представлятьkoa-static
модуль
В предыдущих статьях нам всегда приходилось проходитьlive-server
Запустите локальную службу статических ресурсов. Используется для размещения внешних статических файлов.koa
В экосистеме есть готовые промежуточные программыkoa-static
Может предоставить возможность создавать службы статических ресурсов непосредственно в бэкэнд-проекте.
- сначала выполнить
npm i koa-static -S
Установитьkoa-static
- Корректирование
base.js
const Koa = require('koa');
// 引入 koa-static
const koaStatic = require('koa-static');
const app = new Koa();
const PORT = 1234;
// 使用 koa-static 中间件, 并指定静态文件目录为 www
app.use(koaStatic('./www'));
app.use((ctx) => {
console.log(ctx.req.url);
ctx.body = 'Hello World';
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
- написать интерфейс
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ServerProxy 实现跨域</title>
</head>
<body>
ServerProxy 实现跨域
</body>
</html>
- воплощать в жизнь
node base.js
перезапустить проект - браузер открытlocalhost:1234/index.html
HTML-страница, подготовленная ранее, впечатляет 😄. На данный момент служба статических файлов успешно построена (эквивалентна нашей собственной реализации одногоlive-server
)кодовый адрес
Доступ к текущему внутреннему интерфейсу через ajax
пройти черезkoa-static
Middleware, мы создали свой собственный статический файловый сервер Далее мы продемонстрируем не междоменный запрос...
- Сначала измените внутренний код
const Koa = require('koa');
const koaStatic = require('koa-static');
const app = new Koa();
const PORT = 1234;
app.use(koaStatic('./www'));
app.use((ctx) => {
let ret;
// 获取本次接收的请求的请求路径
const path = ctx.req.url;
// 如果请求路径以api开头, 那么作为接口请求处理
if (path.startsWith('/api')) {
// 这样实现的路由不是很优雅, 但是能用 😂
switch (path) {
case '/api/getFriend':
ret = { name: 'quanquan', friend: 'gl' };
break;
default:
ret = { errno: 1, errmsg: '未知接口' };
break;
}
}
ctx.body = ret;
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
Приведенный выше код определяет/api/getFriend
Интерфейс, доступный через браузер, выглядит следующим образом:
пс: нужно выполнитьnode base.js
Перезапустите серверный проект
Далее измените код интерфейса. Доступ к интерфейсу через AJAX
Измените внешний код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ServerProxy 实现跨域</title>
</head>
<body>
ServerProxy 实现跨域
<script>
// 一个常规的 ajax, 感兴趣的兄弟们也看看. 手写 ajax 好多面试官还在考
var xhr = new XMLHttpRequest()
xhr.open('GET', '/api/getFriend')
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log('接口返回的数据为: ', xhr.responseText)
}
}
xhr.send()
</script>
</body>
</html>
Обновите браузер, консоль отобразится следующим образом: ошибки нет, а возвращаемая информация получена напрямую из внешнего интерфейса.
Оказывается, взаимодействие с данными настолько просто, когда фронт и бэкэнд находятся в одном домене.
Фаза обкатки передних и задних концовкод
Улучшение сторонних сервисов
При разработке проектов часто используются некоторые базовые сервисы, такие как информация о погоде, информация о географическом местоположении и т. д. Эти сервисные возможности обычно достигаются за счет вызова сторонних интерфейсов (вы разрабатываете сайт, сначала запускаете в небо метеоспутник. Не очень На этом шаге мы создаем два сторонних сервиса, которые обеспечивают операции сложения и вычитания.
Дополнительный сервисadd.js
const Koa = require('koa');
const app = new Koa();
const PORT = 1111;
app.use((ctx) => {
// 获取参数
const { a, b } = ctx.query;
// 尝试将参数转化为数字后进行加法操作
const result = Number(a) + Number(b);
ctx.body = { result };
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
Выполнение заказаnode add.js
Запустите программу, а затем войдите в браузерlocalhostПолученные результаты следующие, указывающие на то, что служба вычисления сложения успешно запущена.
Служба вычитанияsubtract.js
const Koa = require('koa');
const app = new Koa();
const PORT = 2222;
app.use((ctx) => {
// 获取参数
const { a, b } = ctx.query;
// 尝试将参数转化为数字后进行减法操作
const result = Number(a) - Number(b);
ctx.body = { result };
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
Выполнение заказаnode subtract.js
Запустите программу, а затем войдите в браузерlocalhostПолученные результаты следующие, указывающие на то, что служба вычисления вычитания успешно запущена.
В настоящее времякод
Доступ к сторонним сервисам через серверный прокси
После создания сервисов сложения и вычитания нам все же повезло, и мы не можем не зайти на фронтенд-проект и попробовать его, а вдруг он заработает?
Изменить адрес интерфейса во внешнем кодеxhr.open('GET', 'http://localhost:1111/?a=1&b=2')
полный код, затем обновите браузер напрямую (пожалуйста, подумайте, почему измененный файл js должен быть выполненnode ...
Перезапустите службу и измените html-файл, просто нужно обновить браузер?).
Это все еще предыдущая ошибка, это все еще знакомый вкус, он не прост в использовании...
Вспомните предыдущую идею. Браузер имеет сервер ограничений политик того же происхождения. Наш интерфейсный проект размещается во внутреннем проекте, поэтому доступ к нашему внутреннему серверу не является междоменным. Наш внутренний запрос третий -тусовочные услуги без ограничений.Тогда ^_^
- воплощать в жизнь
npm i axios -S
Установка axios, через которую тыловой конец запроса целевого сервера - Изменить код
base.js
const Koa = require('koa');
const koaStatic = require('koa-static');
const axios = require('axios');
const app = new Koa();
const PORT = 1234;
app.use(koaStatic('./www'));
app.use(async (ctx) => {
let ret;
// 获取本次接收的请求的请求路径
const path = ctx.req.url.split('?')[0];
console.log('ctx.query.server', ctx.query.server);
// 如果请求路径以api开头, 那么作为接口请求处理
if (path.startsWith('/api')) {
// 这样实现的路由不是很优雅, 但是能用 😂
switch (path) {
case '/api/getFriend':
ret = { name: 'quanquan', friend: 'gl' };
break;
// 如果接口需要代理接口路径为 /api/proxy
case '/api/proxy':
// axios 直接访问前端给出的目标服务器url, 并将目标服务器返回的数据直接返回给前端
ret = (await axios.get(ctx.query.server)).data;
break;
default:
ret = { errno: 1, errmsg: '未知接口' };
break;
}
}
ctx.body = ret;
});
app.listen(PORT, () => {
console.log('the server is listen: ', PORT);
});
Интерфейсный код:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>ServerProxy 实现跨域</title>
</head>
<body>
<h3>ServerProxy 实现跨域</h3>
a: <input type="text" id="a" value="1">
b: <input type="text" id="b" value="2">
<button id="add">计算加法</button>
<button id="subtrnct">计算减法</button>
<div>计算结果为: <span id="ret"></span></div>
<script>
var aDom = document.getElementById('a')
var bDom = document.getElementById('b')
var addBtn = document.getElementById('add')
var subtrnctDom = document.getElementById('subtrnct')
var retDom = document.getElementById('ret')
function add() {
if(!a.value.trim() || !b.value.trim()) return
var xhr = new XMLHttpRequest()
xhr.open('GET', '/api/proxy' + '?server=' + encodeURIComponent('http://localhost:1111/?a='+ a.value +'&b=' + b.value))
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log('接口返回的数据为: ', xhr.responseText)
retDom.innerHTML = JSON.parse(xhr.responseText).result
}
}
xhr.send()
}
function subtrnct() {
if(!a.value.trim() || !b.value.trim()) return
var xhr = new XMLHttpRequest()
xhr.open('GET', '/api/proxy' + '?server=' + encodeURIComponent('http://localhost:2222/?a='+ a.value +'&b=' + b.value))
xhr.onreadystatechange = function() {
if(xhr.readyState === 4 && xhr.status === 200) {
console.log('接口返回的数据为: ', xhr.responseText)
retDom.innerHTML = JSON.parse(xhr.responseText).result
}
}
xhr.send()
}
addBtn.addEventListener('click', add)
subtrnctDom.addEventListener('click', subtrnct)
</script>
</body>
</html>
конечный результат:
Вывод: принцип ServerProxy, вероятно, таков: доступ к внутреннему сервису того же домена через ajax, внутренний сервис обращается к целевому сервису и прозрачно передает контент, возвращаемый целевым сервисом, во внешний интерфейс. , реальная работа будет не такой простой как на примере.Очередной цикл моих статей[Возьмем вас за руку с инструментом тестирования интерфейса]Будут подробно представлены более сложные ситуации, в том числе различные типы запросов, настройки заголовка запроса и получение заголовка ответа и т. д. Я надеюсь, что заинтересованные партнеры продолжат обращать внимание.
Другие способы междоменного доступа:document.domainМожно сделать одну строку кода, подходящую для разных поддоменов одного и того же основного домена.postMessageНеобходимо добавить дополнительные фреймы, общая реализация относительно проста, и можно сделать API Заинтересованные студенты могут посмотретьДокументация, Есть и еще несколько нишевых практикflash
CSST
Теги img, используемые во внешнем интерфейсе и т. д., здесь не перечислены, этому нет конца.