Итак, недавно я играл с MTA Bus API. Это довольно круто. Вы можете получить список всех автобусных линий, автобусных остановок и т. д. и даже местонахождение всех транспортных средств в режиме реального времени! В сафари все работало отлично. Я смог получить массу данных JSON из API-интерфейсов MTA и создать объекты JavaScript для каждого из них, например:

Но в Chrome это вообще не работало. Я бы получил такие ошибки:

Что это за заголовок Access-Control-Allow-Origin? И зачем он мне нужен? А почему его нет? И если он мне действительно нужен, почему он работает в Safari!?
(На последний вопрос я еще не ответил. Но все же.)
Я хотел узнать, как решить эту проблему. Посоветовавшись со своими инструкторами в школе Flatiron и погуглив, я обнаружил множество различных ресурсов в Интернете, пытающихся помочь людям решить эту проблему. Но я заметил нечто странное. Почти все опубликованные решения предполагали, что вы являетесь владельцем API; что вы контролировали сервер и могли вносить в него изменения. Видите ли, все, что вам нужно сделать, это отправить обратно заголовок «Access-Control-Allow-Origin» «*», и все будет отлично работать!
Но, увы, я не являюсь Управлением городского транспорта Нью-Йорка и не контролирую их серверы. Так что же происходит?
Оказывается, CORS — это стандарт, принудительный для браузера, и он не разрешает запросы между источниками, если только об этом не указано в заголовке «Access-Control-Allow-Origin». Так в чем же разница между запросом из разных источников и запросом одного и того же источника?
Давайте посмотрим на этот пример:
Server sending the request: bustime.mta.info
Server receiving the request: bustime.mta.info
Вышеупомянутое будет считаться запросом того же происхождения.
Server sending the request: www.mywebsite.com
Server receiving the request: bustime.mta.info
Это будет считаться запросом из другого источника.
Итак, предположим, что у MTA есть собственное внутреннее веб-приложение по адресу bustime.mta.info. Это веб-приложение может отправлять запросы одного и того же происхождения к своему серверному API в течение всего дня, и CORS даже не будет задействован. Эта настройка обычно используется для API, которые предназначены только для внутреннего использования, другими словами, не являются общедоступными.
Если у MTA есть другое веб-приложение с другим URL-адресом (не bustime.mta.info), они могут настроить свой заголовок «Access-Control-Allow-Origin», чтобы разрешить запросы с этого конкретного URL-адреса. Они знают, откуда будет поступать запрос, так как это их собственное приложение, поэтому нужно просто настроить их API, чтобы разрешить этот запрос.
Но вы можете сказать, что это нормально для API, который не отправляет данные сторонним разработчикам. Но предполагается, что это общедоступный API. Зачем блокировать запросы из разных источников в общедоступном API!?
Я тоже давно об этом думал. А потом я нашел этот пост в группе MTA Developer BusTime Google. Это говорит
«Потоки данных MTA предоставляются бесплатно разработчикам, которые соглашаются со следующим:
1. При разработке вашего приложения вы должны обеспечить, чтобы поток данных MTA был доступен другим только с сервера, не являющегося MTA. Соответственно, вы будете загружать и хранить поток данных MTA на сервере, отличном от MTA, к которому пользователи вашего приложения будут обращаться для получения данных. MTA запрещает разработку приложения, которое делало бы данные доступными для других непосредственно с серверов MTA».
Далее предлагается вместо этого предоставить свой внутренний сервер, чтобы делать запросы и загружать фид MTA, а затем передавать эти данные через свой собственный фид API. Поскольку запрос делает не браузер, CORS не будет проблемой.
Так что, увы, похоже, что я не смогу обойти эту проблему в ближайшее время. Думаю, пришло время для rails new — api.