The Web is my API

Paul Kinlan
Available in: English (Original) Deutsch Español Français 日本語 मानक हिन्दी tiếng Việt தமிழ் bahasa Indonesia

Michael Mahemoff многому научил меня возможностям Интернета. До работы с Майком я построил в Интернете, и я понял такие преимущества, как связывание и открытие, но у меня никогда не было полной картины того, что было бы возможно.

Одна вещь, о которой говорил Майк, была «Веб - мой API», где он рассказывал о том, как можно подвергать свой сайт и ваши данные на странице с помощью микроформатов и других структурированных данных и иметь доступ к нему непосредственно из другой другой контекст браузера, используя простой XMLHttpRequest и API CORS:

Anyway, what’s cool about this is you can treat the web as an API. The Web is my API. “Scraping a web page” may sound dirtier than “consuming a web service”, but it’s the cleaner approach in principle. A website sitting in your browser is a perfectly human-readable depiction of a resource your program can get hold of, so it’s an API that’s self-documenting. The best kind of API. But a whole HTML document is a lot to chew on, so we need to make sure it’s structured nicely, and that’s where microformats come in, gloriously defining lightweight standards for declaring info in your web page. There’s another HTML5 tie-in here, because we now have a similar concept in the standard, microdata.

Примерно в то же время я начал работать над Web Intents, дух которого был похож на mdash; предоставить пользователям доступ к данным и сервисам из другого источника - mdash; но это было намного сложнее. Я хотел включить открытие сервисов, а затем для взаимодействия с этими страницами. И Майк хотел перевести Интернет на предоставление доступа к данным и услугам. Он застрял со мной. Даже если я забыл оригинальную атрибуцию.

Недавно я поговорил о Nordic JS, где я подчеркнул, что мы не строим действительно встроенные надежные взаимосвязанные сервисы в Интернете, и когда мы делаем это, следует модель взаимодействия от сервера к серверу. Это веб-сайт будет интегрирован с сторонним сервисом, маршрутизируя весь запрос API через свой сервер на удаленную службу и управляя всеми сложностями, которые возникают с этим.

Он работает, у нас есть весь веб-сайт с этим, но он может быть невероятно сложным, если вы рассматриваете аутентификацию, авторизацию, транспортные протоколы и различные методы RPC (REST, GraphQL и т. Д.). Майк предлагал нечто более элегантное, что с сайтами CORS и небольшим количеством JavaScript мы можем напрямую общаться с удаленной службой, используя сайт.

Между ними возникло несколько проблем. Основная проблема заключается в том, что, хотя CORS широко поддерживается в браузерах, разработчики редко используют его. CORS - это защита, которая нам нужна в Интернете, но ее сложно настроить и отладить, а «Интернет как API» на самом деле не слишком сильно толкнул.

Мы переходим в мир, где сайты генерируются в клиенте с помощью JS, а сеансы и состояние для пользователя управляются полностью на клиенте.

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

Каждый веб-сайт должен иметь возможность раскрывать API, которым владеет владелец сайта, непосредственно другим клиентам.

Хорошей новостью является то, что мы уже можем это сделать, у нас были примитивы на платформе не менее 7 лет (postMessage иMessageChannel) и навсегда с window.open, но мы не используем эти инструменты взаимодействуют с сайтами по тем же причинам, почему мы не используем CORS: это сложно, и практически невозможно определить здравый API, который прост и последователен в использовании, и это не требует привлечения огромных сторонних библиотек для каждой службы с которыми вы хотите взаимодействовать.

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

У нас есть библиотека, которая помогает: Comlink.

Comlink - это небольшой API, который абстрагирует API-интерфейс MessageChannel и PostMessage API для API, который выглядит так, будто вы создаете удаленные классы и функции в локальном контексте. Например:

Веб-сайт

// Set up.
const worker = w.open('somesite');
const api = Comlink.proxy(w);

// Use the API.
const work = await new api.Test();
const str = await work.say('Yo!');
console.log(str);

** Веб-работник **

class Test {
  say() {
    return `Hi ${this.x++}, ${msg}`;
  }
}

// Expose the API to anyone who connects.
Comlink.expose({Test}, window);

Мы предоставляем API для службы, мы используем API в клиенте через прокси.

Есть ли лучший пример?

Я создал сайт, который подписывается на конечную точку pubsubhubbub, и когда он получает пинг, он отправляет сообщение JSON] (0) в конечную точку, определенную пользователем. Я не хотел управлять инфраструктурой push-уведомлений для этого небольшого приложения, другой сайт, который я построил (webpush.rocks), может сделать все это, я просто хочу использовать интеграцию с этой службой.

Но как мне получить URL-адрес подписки (часть данных, которую мне нужно, чтобы отправлять уведомления), хранящиеся в клиенте webpush.rocks, обратно на мой сайт?

Когда я изначально построил этот сайт, все, что вы могли сделать, это позволить пользователю открыть сайт, а затем скопировать и вставить URL-адрес между страницами. Почему бы просто не опубликовать API, который мог бы использовать любой сайт? Вот что я сделал.

webpush.rocks определяет API под названием «PushManager», который имеет единственный метод на нем subscriptionId. Когда страница загружается, этот API открывается в окно следующим образом:

class PushManager {
  constructor() {
  }

  async subscriptionId() {
    //global var ick...
    let reg = await navigator.serviceWorker.getRegistration();
    let sub = await reg.pushManager.getSubscription();
    if(sub) {
        return `${location.origin}/send?id=${sub.endpoint}`;
    }
    else {
        return ``;
    }
  }
}

Comlink.expose({PushManager}, window);

API взаимодействует с API-интерфейсом PushSubscriptionManager в DOM и возвращает пользовательский URL-адрес вызывающему сайту. Важно то, что, поскольку он работает асинхронно, я могу дождаться проверки пользователя, что они хотят выполнить действие (или нет).

Назад на вызывающий клиентский сайт (приложение, которое хочет получить подписку). Когда пользователь нажимает на ссылку, мы получаем ссылку на только что открытое окно и подключаем к нему прокси-сервер «Comlink». API-интерфейс сервисов теперь открыт для нашего клиента, и мы можем создать экземпляр API-интерфейса PushManager, так как это была локальная служба, но все это взаимодействует с удаленной службой экземпляра в другом окне.

let endpointWindow = window.open('', 'endpointUrlWindow');

let pushAPI = Comlink.proxy(endpointWindow);
let pm = await new pushAPI.PushManager();
let id = await pm.subscriptionId();

// Update the UI.
endpointUrlEl.value = id;

Вот очень быстрое видео о том, что происходит. Очень простое и легкое взаимодействие, оно открывает сервис, а затем получает требуемый идентификатор.

В качестве поставщика услуг я обнаружил ограниченный набор функциональных возможностей, который доступен только на клиенте на другом сайте, и я могу его защитить и запросить согласие с пользователем в одно и то же время, прежде чем я верну данные обратно пользователю, все с простым для использования API.

Веб-интерфейс - API._

Совершенно справедливо, что мы не позволяем сайтам проверять или манипулировать DOM или состоянием другого происхождения, но я полагаю, что если у вас есть контроль над сервисами и функциональными возможностями вашего сайта и как пользователи взаимодействуют с ним, вы можете предоставить самую важную информацию и услуги любому клиенту, который надежно использует ваш сервис (вы контролируете), и он позволяет:

  • Сосредоточьтесь на том, на что вы хороши.
  • Быстрая передача данных между сайтами и приложениями, потому что это все в клиенте.
  • IPC даже в автономном режиме.
  • Запустить код в исходном контексте

Какие API должны размещать сайты?

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

Я хотел бы добраться до места, где каждый сайт может предоставлять согласованный API для пользователей и способ обнаруживать другие функции и службы.

Каждый владелец сайта мог бы предоставить только основные функции для их обслуживания, чтобы мы могли выполнять операции на основе CRUD. Мы могли бы иметь сложные взаимодействия.

Мы могли бы добраться до сети, где у нас есть сервисы Unix, которые хорошо что-то делают, и пользователь соединяет их вместе на клиенте.

Каждый сайт может выставить VDOM подмножества страницы, которое определено владельцем службы, чтобы мы могли последовательно переносить данные на основе DOM между сайтами.

Я мог представить себе, что нам может потребоваться быстрый доступ ко всем объектам на основе schema.org или другим структурированным данным на странице (они могут быть динамически сгенерированы), как это сделал Майк в своем оригинальном посте.

Comlink дает нам возможность быстро и легко выявлять и потреблять услуги поверх примитивов платформы, которые существуют уже много лет. Наконец, у нас есть много штук, которые позволяют нам превращать веб-интерфейс в API.

_The Web - это мой API. Сделай это тоже.

Paul Kinlan

Trying to make the web and developers better.

RSS Github Medium