[Брат, ты хочешь знать о кросс-доменном] ServerProxy

Node.js внешний интерфейс

Серия статей:

в серии статейпервый разПричина, по которой мы говорили о междоменных проблемах, заключается в том, чтобраузерПолитика одного и того же происхождения. Тогда связь между серверами не будет ограничена соответствующими условиями. Так можем ли мы использовать сервер того же домена, чтобы помочь получить доступ к API других доменных имен? Если да, сможем ли мы получить доступ к кому угодно мы хотим??Ограничения, несуществующие...

2018-12-12-23-32-26

PS: эта статья включает в себя некоторые базовые знания, и вам нужно немного ихnodejs koaБазовый. В основном используется для созданияwebСервер, конечно, не беда, если у вас нет фундамента, идите первымnode koaПроверьте официальный сайт. Вы не можете вернуться???

как вам будет угодно 😄

Создать каталог проекта

Перейдите к предыдущему шагу, в этой статье будет создан только серверный проект, поэтому нет необходимости./feСоздайте интерфейсный проект в каталоге, каталог проекта выглядит следующим образом.

2018-12-12-23-50-07

в,serverProxydirectory является основным каталогом проекта.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

2018-12-13-00-05-48

В настоящее времякод

представлять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

2018-12-13-00-26-23

HTML-страница, подготовленная ранее, впечатляет 😄. На данный момент служба статических файлов успешно построена (эквивалентна нашей собственной реализации одногоlive-server)кодовый адрес

Доступ к текущему внутреннему интерфейсу через ajax

пройти черезkoa-staticMiddleware, мы создали свой собственный статический файловый сервер Далее мы продемонстрируем не междоменный запрос...

2018-12-15-21-51-02

  • Сначала измените внутренний код
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Интерфейс, доступный через браузер, выглядит следующим образом:

2018-12-15-22-09-17пс: нужно выполнить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>

Обновите браузер, консоль отобразится следующим образом: ошибки нет, а возвращаемая информация получена напрямую из внешнего интерфейса.2018-12-15-22-18-18

Оказывается, взаимодействие с данными настолько просто, когда фронт и бэкэнд находятся в одном домене.2018-12-15-22-22-07

Фаза обкатки передних и задних концовкод

Улучшение сторонних сервисов

При разработке проектов часто используются некоторые базовые сервисы, такие как информация о погоде, информация о географическом местоположении и т. д. Эти сервисные возможности обычно достигаются за счет вызова сторонних интерфейсов (вы разрабатываете сайт, сначала запускаете в небо метеоспутник. Не очень На этом шаге мы создаем два сторонних сервиса, которые обеспечивают операции сложения и вычитания.

Дополнительный сервис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Полученные результаты следующие, указывающие на то, что служба вычисления сложения успешно запущена.2018-12-15-23-18-53

Служба вычитания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Полученные результаты следующие, указывающие на то, что служба вычисления вычитания успешно запущена.2018-12-15-23-23-55

В настоящее времякод

Доступ к сторонним сервисам через серверный прокси

После создания сервисов сложения и вычитания нам все же повезло, и мы не можем не зайти на фронтенд-проект и попробовать его, а вдруг он заработает?

2018-12-16-00-57-43

Изменить адрес интерфейса во внешнем кодеxhr.open('GET', 'http://localhost:1111/?a=1&b=2') полный код, затем обновите браузер напрямую (пожалуйста, подумайте, почему измененный файл js должен быть выполненnode ...Перезапустите службу и измените html-файл, просто нужно обновить браузер?).

2018-12-15-23-34-33Это все еще предыдущая ошибка, это все еще знакомый вкус, он не прост в использовании...

Вспомните предыдущую идею. Браузер имеет сервер ограничений политик того же происхождения. Наш интерфейсный проект размещается во внутреннем проекте, поэтому доступ к нашему внутреннему серверу не является междоменным. Наш внутренний запрос третий -тусовочные услуги без ограничений.Тогда ^_^

2018-12-15-23-41-03

  • воплощать в жизнь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>

конечный результат:server-proxy-dfasdfasfas

Вывод: принцип ServerProxy, вероятно, таков: доступ к внутреннему сервису того же домена через ajax, внутренний сервис обращается к целевому сервису и прозрачно передает контент, возвращаемый целевым сервисом, во внешний интерфейс. , реальная работа будет не такой простой как на примере.Очередной цикл моих статей[Возьмем вас за руку с инструментом тестирования интерфейса]Будут подробно представлены более сложные ситуации, в том числе различные типы запросов, настройки заголовка запроса и получение заголовка ответа и т. д. Я надеюсь, что заинтересованные партнеры продолжат обращать внимание.

Другие способы междоменного доступа:document.domainМожно сделать одну строку кода, подходящую для разных поддоменов одного и того же основного домена.postMessageНеобходимо добавить дополнительные фреймы, общая реализация относительно проста, и можно сделать API Заинтересованные студенты могут посмотретьДокументация, Есть и еще несколько нишевых практикflash CSSTТеги img, используемые во внешнем интерфейсе и т. д., здесь не перечислены, этому нет конца.

2018-12-16-01-38-47