Как сделать api запрос на php
БЛОГ ПРО WEB
Рассказываю о web-разработке
и помогаю создавать сайты
Простой API для Вашего сайта
Возникла ситуация, когда необходимо использовать 2 БД MySQL на разных серверах для снижения нагрузки.
1 БД для основных задач и 2 БД для хранения различной статистики по всем модулям. А Статистика, как всем известно, — это куча цифр, которыми не хочется засорять основную БД.
Так как решил использовать сторонний сервер, на ум приходит API. В принципе, для меня то, что нужно, так как возможно может пригодиться и для моих пользователей для вывода своей статистики на своих проектах.
Oauth использовать решил не стоит, да и было интересно как выйдет API своими руками.
API, ну или Парсер
Да, действительно, способ проще чем кажется. Можно данный способ организации назвать как Парсер, ведь будем использовать @file_get_contents()
Но мне важен результат!
Качаем исходники тут и разбираем что к чему
Собираем функционал API
У нас в итоге получится 2 части.
Файлы клиентской части
А теперь по порядку каждый файл
Клиентская часть
$url — это адрес к нашему серверу, а точнее к файлу api.php (о нем читать ниже).
Дальше мы отправляем запрос @file_get_contents($get); к серверу и получаем ответ с результатом в формате json_decode()
Начал с клиентской части потому что, мне кажется интереснее посмотреть что получится, а не то как это сделано. И поэтому, вот как использовать MySQL удаленно
Подключаем function.api.php на нужных страницах для связи с API сервера со статистикой к примеру.
А остальное все итак понятно. Там написал все 4 функции для примера, используя таблицу в бд следующего вида
И тут логично понятные параметры
query — запрос (SELECT, UPDATE, INSERT или DELETE)
table — таблица в бд (в моем случае ‘scripts’)
where — условия обычного формата (тут не стал что то изобретать. Типа, [id=5 OR >
values — и тут передаем параметры для добавления и редактирования в следующем формате
Мне кажется, просто и понятно…
Серверная часть API
Конечно же config.php
Проверка и отправка запроса в БД через класс API
Конечно как вы понимаете, проверка такого рода
лишь как пример. Тут надо делать проверку ключа и ID пользователя на соответствие. Тут проблем думаю не будет.
И файл class.a.php для разных запросов и возвращения результата
местами требуются некоторые проверки для защиты, но не критичны. Даю код, чтобы смысл был понятен. Дальше уже сами дорабатывайте)
Расписывать не буду, итак ясно что делает данный файл…
Введение в REST API — RESTful веб-сервисы
Эта статья начинает серию постов о разработке REST API:
Intro to RESTful Web Services
REST означает REpresentational State Transfer (Википедия: «передача состояния представления»). Это популярный архитектурный подход для создания API в современном мире.
Вы изучите:
Что такое REST?
REST расшифровывается как REpresentational State Transfer. Это был термин, первоначально введен Роем Филдингом (Roy Fielding), который также был одним из создателей протокола HTTP. Отличительной особенностью сервисов REST является то, что они позволяют наилучшим образом использовать протокол HTTP. Теперь давайте кратко рассмотрим HTTP.
Краткий обзор HTTP
Давайте сначала откроем браузер и зайдем на веб-страницу:
А затем щелкните на одной из страниц результатов:
Далее мы можем нажать на ссылку на странице, на которой мы оказались:
И перейти на другую страницу:
Вот как мы обычно просматриваем веб страницы.
Когда мы просматриваем страницы в Интернете, за кулисами происходит много вещей. Ниже приведено упрощенное представление о том, что происходит между браузером и серверами, работающими на посещаемых веб-сайтах:
Протокол HTTP
Когда вы вводите в браузере URL-адрес, например www.google.com, на сервер отправляется запрос на веб-сайт, идентифицированный URL-адресом.
Затем этот сервер формирует и выдает ответ. Важным является формат этих запросов и ответов. Эти форматы определяются протоколом HTTP — Hyper Text Transfer Protocol.
Когда вы набираете URL в браузере, он отправляет запрос GET на указанный сервер. Затем сервер отвечает HTTP-ответом, который содержит данные в формате HTML — Hyper Text Markup Language. Затем браузер получает этот HTML-код и отображает его на экране.
Допустим, вы заполняете форму, присутствующую на веб-странице, со списком элементов. В таком случае, когда вы нажимаете кнопку «Submit» (Отправить), HTTP-запрос POST отправляется на сервер.
HTTP и RESTful веб-сервисы
HTTP обеспечивает базовый уровень для создания веб-сервисов. Поэтому важно понимать HTTP. Вот несколько ключевых абстракций.
Ресурс
Ресурс — это ключевая абстракция, на которой концентрируется протокол HTTP. Ресурс — это все, что вы хотите показать внешнему миру через ваше приложение. Например, если мы пишем приложение для управления задачами, экземпляры ресурсов будут следующие:
URI ресурса
Когда вы разрабатываете RESTful сервисы, вы должны сосредоточить свое внимание на ресурсах приложения. Способ, которым мы идентифицируем ресурс для предоставления, состоит в том, чтобы назначить ему URI — универсальный идентификатор ресурса. Например:
REST и Ресурсы
Важно отметить, что с REST вам нужно думать о приложении с точки зрения ресурсов:
Определите, какие ресурсы вы хотите открыть для внешнего мира
Используйте глаголы, уже определенные протоколом HTTP, для выполнения операций с этими ресурсами.
Вот как обычно реализуется служба REST:
Компоненты HTTP
HTTP определяет следующую структуру запроса:
Методы HTTP-запроса
Метод, используемый в HTTP-запросе, указывает, какое действие вы хотите выполнить с этим запросом. Важные примеры:
Код статуса ответа HTTP
Код состояния всегда присутствует в ответе HTTP. Типичные примеры:
Резюме
В статье приведен на верхнем уровне обзор архитектурного стиля REST. Подчеркивается тот факт, что HTTP является основным строительным блоком REST сервисов. HTTP — это протокол, который используется для определения структуры запросов и ответов браузера. Мы видели, что HTTP имеет дело главным образом с ресурсами, доступными на веб-серверах. Ресурсы идентифицируются с помощью URI, а операции над этими ресурсами выполняются с использованием глаголов, определенных протоколом HTTP.
Наконец, мы рассмотрели, как службы REST наилучшим образом используют функции, предлагаемые HTTP, для предоставления ресурсов внешнему миру. REST не накладывает никаких ограничений на форматы представления ресурсов или на определение сервиса.
Как сделать запрос к API?
API InSales позволяет работать с бэк-офисом магазина, используя HTTP-запросы. При помощи API можно получать, добавлять, изменять и удалять информацию о различных объектах (например, товарах, категориях, дополнительных полях и т.д.)
Предполагается, что работа с API организована на внешнем сервере (НЕ на сервере платформы), который отправляет к серверу платформы запросы определенного типа. Для удобства в этой статье будет рассмотрена отправка запросов при помощи приложения Postman. В качестве альтернативы можно использовать Advanced REST Client.
Все доступные запросы в форматах XML и JSON описаны на api.insales.ru. Типовые запросы в формате XML с более подробным описанием можно найти на api.insales.ru.
Ограничения
На платформе присутствует ограничение в 500 запросов к API в течение 5 минут. Время рассчитывается с момента первого запроса в серии. Количество выполненных запросов в текущем промежутке времени передается в HTTP-заголовке API-Usage-Limit (например, API-Usage-Limit: 1/500).
При достижении лимита доступ к API ограничивается до окончания текущих 5 минут. При этом в HTTP-заголовке Retry-After передается время в секундах до восстановления доступа.
Авторизация
Для отправки запросов к API необходимо создать ключ доступа.
Внимание! Не используйте логин-пароль от бэк-офиса для работы с API, иначе ваш аккаунт может быть заблокирован.
Далее в статье мы будем использовать созданные логин (идентификатор) и пароль. Их можно указывать как в адресе запроса:
Так и в виде HTTP-заголовка Authorization:
Authorization: Basic ZGlnaXRhbC1nb29kczpjNTFjOTA3MDdhMTNjZTNmZmYyMTNhZmJiNWNkMTI3MA==
Вместо shop-47483-27.myinsales.ru необходимо использовать технический или обычный домен вашего магазина. Его можно взять, например, из строки “Пример URL” около выданного ключа доступа.
Общие принципы
API InSales принимает POST, GET, PUT и DELETE-запросы в зависимости от выполняемого действия. Тип и адрес запроса для требуемого действия можно найти на api.insales.ru.
Текст самого запроса должен соответствовать формату XML или JSON. В зависимости от формата меняется адрес запроса и значение HTTP-заголовка Content-Type.
Для XML необходим Content-Type: application/xml
На скриншоте программы Postman показан выбранный тип запроса, адрес и заголовки. После нажатия кнопки Send появится ответ сервера InSales.
Примеры XML-запросов
Рассмотрим GET-запрос к товару с id 143570988. Такой запрос не требует передачи серверу каких-либо параметров. В качестве адреса необходимо указать https://логин:пароль@shop-47483-27.myinsales.ru/admin/products/143570988.xml
В ответ сервер пришлёт всю доступную информацию об этом товаре.
PUT-запрос служит для обновления данных выбранного объекта. Для обновления названия того же товара с id 143570988 потребуется отправить запрос с телом
В ответ сервер пришлёт обновлённую информацию о товаре (в том числе новое название). Соответственно, в бэк-офисе также будет отображаться новое название товара. В ответе виден код 200, что означает успешное выполнение операции.
Примеры JSON-запросов
Запросы в формате JSON отличаются адресом и заголовком Content-Type.
Тело PUT-запроса на обновление названия товара выглядит следующим образом:
Примеры работы с API через PHP
Можно ли где то увидеть простейшие примеры работы с API через PHP? Только начинаю разбираться со складом и пока мало что понятно.
Комментарии
Видел я тот SDK. Дело в том что я PHP знаю постольку поскольку, скажем на троечку, и мне он показался сложноватым для понимая.
Опять же там речь идет о работе с API используя этот SDK, а я прошу простой пример работы на чистом PHP.
Короче, помогите какими-то примитивами, а то вообще не знаю как к этому подступиться.
По вопросам php не консультируем.
Для авторизации в АПИ используется такой же логин как и на сайте, то есть из вашего примера, логин в АПИ будет admin@emshop.
Наши интеграторы пишут на разных языках программирования, поэтому в привязке к конкретному языку консультаций мы не даем. Но в качестве рекомендации даем ссылки на СДК наших интеграторов.
С авторизацией я разобрался, а так же научился создавать новый заказ и доп. поля к нему.
“Но в качестве рекомендации даем ссылки на СДК наших интеграторов.”
У вас к сожалению лишь одна ссылка на какой-то мутный SDK, автор которого написал, что там еще пилить его и пилить. Лучше бы вы давали так же ссылки на конкретные примеры работы со Складом по данному языку.
А на вопрос общего плана вы можете ответить? Не касаемо конкретной реализации.
При добавлении товара если не указать его цену, то она автоматически не подставляется из самого товара. Хотя она в нем указана. И в результате цена заказа 0. Можно ли сформировать такой запрос API чтобы цена бралась та, что задана у товара по умолчанию?
Можете предоставить более подробную информацию о том куда и как вы добавляете товар?
Вот кусок PHP кода:
$product_id = ‘56474ec4-a355-11e8-9ff4-31500042cb83’;
$post[‘positions’][0][‘quantity’] = 5;
$post[‘positions’][0][‘assortment’][‘meta’][‘href’] = “https://online.moysklad.ru/api/remap/1.1/entity/product/$product_id”;
$post[‘positions’][0][‘assortment’][‘meta’][‘type’] = “product”;
$post[‘positions’][0][‘assortment’][‘meta’][‘mediaType’] = “application/json”;
То есть, как видите я указываю количество, но не указываю стоимость товара. Потому что стоимость у товара задана уже вот здесь https://yadi.sk/i/52mdXB75EjI6EA
Но после выполнения запроса получаю новый заказ с пустым значением цены в товаре: https://yadi.sk/i/h_Rn-pZLXL9q-g
Да, все верно, при создание заказа покупателя в нем нужно явно указывать стоимость продажи.
Если вы хотите создать заказ покупателя в котором в стоимости продажи будет проставлена цена товара, то вы можете предварительно запросить сам товар, и полученую в нем цену передать как стомоисть продажи.
Выглядит немного странным что у товара есть цена, но чтобы ее проставить в заказе надо сделать дополнительный отдельный запрос на ее получение. Казало бы куда уж логичнее дать возможность подставить ее из товара. Ну ок. Если никак иначе, значит так.
Но оказалось, что это не так. С таким ID товар не выбирается при создании заказа. А выбирается только вот с таким ID: 56474ec4-a355-11e8-9ff4-31500042cb83
Этот ID товара я смог получить только путем запроса к API. Как видите эти 2 ID очень похожи, но все же разные. Почему так? Почему нельзя использовать для товара тот же ID что и в URL при его редактировании? И откуда нам брать “правильный” ID, чтобы по нему добавлять товар в заказ?
Откуда мы можем взять тот ID, по которому можно получить цену товара и потом по нему же добавить товар в заказ? Он где то доступен в интерфейсе?
Нет, данный ID доступен только через АПИ
Предполагается, что если вы строите интеграцию через АПИ, вам нет смысла завязываать на UUID с UI. В таком кейсе uuidHref носит чисто справочную информацию
Смотрите, я создаю добавляю товар в заказ как написано в документации. Там есть вот такая строка
Может товар можно добавить в заказ по другому? Чтобы вместо этого ID использовать что-то, что видно при редактировании товара через интерфейс пользователя?
Запросить ID товаров в АПИ вы можете только через запрос списка товаров. И далее выбирать например по имени, какой подставлять в заказ
Тут приходится строить более сложную интеграцию.
Мы выгружаем на сайт id всех товаров из МС и цены, чтобы сайт при отправке заказа мог использовать эти id.
Сопоставление товаров при выгрузке у нас делается по полю “код товара” (в МС нужно включить флажок, чтобы проверялась уникальность этого поля).
Создаю счет на основе заказа покупателю:
В ответ получаю ошибку
Что делать? Путь-то вроде верный, скопирован из доков.
Приведенной вами части кода недостаточно, что бы определить в чем заключается проблема.
Можете предоставить выполняемый вами запрос в виде curl-запроса?
Проблема была в том, что запрос на создание шаблона счета должен идти методом PUT, а я посылал его методом POST.
Поменял POST на PUT и в результате получил некий новый шаблон созданный на основании заказа покупателя. Что мне с ним дальше делать? Как создать счет на основании этого шаблона?
Для создания счета на основе шаблона, вам необходимо отправить полученый объект в запросе к ендпоинту
Не забудьте задать в полученном объекте значение поля name, так как в шаблоне оно отсутвует, но является обязательным для создания.
В ответ на запрос создания счета покупателю, вам прийдет json объект созданного счета, вам необходимо скопировать объект meta созданного счета, он потребуется далее.
Я так полагаю, что вы хотите привязать полученный счет покупателю к заказу покупателя, а после его оплаты, установить статус заказа как оплаченный.
Для привязки полученного счета покупателя к заказу, через ендпоинт
Передаем в поле invoicesOut, в массиве, полученный ранее объект метаданных счета покупателю. Таким образом счет покупателя будет привязан к заказу покупателя.
Для того что бы изменить статус заказа покупателя, необходимо, через тот же ендпоинт изменить заказ, передав в поле “state” объект метаданных требуемого статуса заказа.
Получить список доступных состояний заказов покупателя и их метаданные можно через ендпоинт
Принципы построения REST JSON API

Зачем
Надеюсь, читающий уже понимает, зачем ему вообще нужен именно REST api, а не какой-нибудь монстр типа SOAP. Вопрос в том, зачем соблюдать какие-то стандарты и практики, если браузеры вроде бы позволяют делать что хочешь.
Структура запросов и ответов
Любой http-запрос начинается со строки
где METHOD — это метод доступа (GET, PUT и т.д.), а URI — адрес запрашиваемого ресурса.
В начале запроса идут заголовки — просто текстовые строки вида key: value
Затем передаётся пустая строка, означающая конец секции заголовков, и затем — тело запроса, если оно есть.
В ответе сначала передаётся строка с версией http, кодом и строковым статусом ответа (например HTTP/1.1 200 OK ), далее текстовые заголовки ответа, потом пустая строка, потом тело ответа.
Тут вроде всё просто.
Кодирование запросов и ответов
Кодировка для всех и запросов, и ответов — UTF-8 и только UTF-8, т.к. некоторые, кхм, “браузеры” имеют привычку игнорировать содержимое заголовка charset.
Использование кодов символов и html-сущностей не допускается, т.е. режим JSON_UNESCAPED_UNICODE обязателен. Не все клиенты знают всю таблицу html сущностей (типа каких-нибудь ù ), да и при чём тут html. Не все клиенты готовы/хотят заниматься перекодированием \uXXXX; и &#XX;. Плюс возможны “весёлые” ситуации с избыточным экранированием или пропаданием слэшей и амперсандов.
Все данные, кроме URI и двоичных файлов, передаются в формате JSON. Обратите внимание, что далеко не всякий валидный javascript код является валидным JSON.
В частности, для строк используются только двойные кавычки. Одинарные кавычки в json-данных, хотя и допустимы в “обычном” javascript, могут вызвать непредсказуемые плохо отлавливаемые баги.
В запросах обязательно указывается заголовок
Вызовы к API отличаются от прочих вызовов (например, обычной загрузки html страницы по данному URI) именно по наличию application/json в Accept.
В ответах 2хх с непустым телом обязательно наличие заголовка ответа
При наличии тела запроса также обязателен заголовок запроса
либо, при загрузке файлов,
и далее, в первой части
после чего для каждого файла
Если вы используете защиту от CSRF (а лучше бы вам её использовать), то удобнее передавать CSRF-токен в отдельном заголовке (типа X-CSRF-Token) для всех запросов, а не внедрять вручную в каждый запрос. Хранить CSRF токен в куках плохо по той причине, что куки можно украсть, в чём собственно и состоит суть CSRF атаки.
Структура URI
Нагородить можно всякое, но лучшая практика — чтобы все URI имели вид
ну, или если у вас api лежит в какой-то папке,
Для разбора части URI до знака вопроса можно использовать регулярку
Ведущий слэш обязателен, т.к. неизвестно, с какого URL будет осуществлён запрос.
Методы HTTP
GET /:entity/:id — getById
В случае успеха сервер возвращает 200 OK с полями объекта в формате JSON в теле ответа (без дополнительного оборачивания в какой-либо объект)
В случае, если объект с такими id не существует, сервер возвращает 404 Not Found
В ответе обязательно должны быть заголовки, касающиеся политики кэширования, т.к. браузеры активно кешируют GET и HEAD запросы. При остутствии какой-либо политики управления кэшем должно быть:
GET /:entity[?param1=. ¶m2=. ] — списочный get
Простой случай: в случае успеха сервер возвращает 200 OK с массивом объектов в формате JSON в теле ответа (т.е. ответ начинается с [ и заканчивается ] ).
Если массив получился пустой, всё равно вовзращается 200 OK с пустым масивом [] в теле ответа.
Более сложный вариант: возвращается объект, в одном из полей которого — искомый массив. В остальных полях — данные о пагинации, фильтры, счётчики и пр. Только держите это консистентным по всем api.
HEAD /:entity[/:id] — запрос заголовков
Полный аналог GET с таким же URI, но не возвращает тело ответа, а только HTTP-заголовки.
Реализация поддержки HEAD запросов веб-сервером обязательна.
Активно используется браузерами в качестве автоматических pre-flight запросов перед выполнением потенциально опасных, по их мнению, операций. Например, браузер Chrome активно кидается head-запросами для получения политик CORS при кросс-доменных операциях (виджеты и пр). При этом ошибка обработки такого head-запроса приведёт к тому, что основной запрос вообще не будет выполнен браузером.
Может использоваться для проверки существования объекта без его передачи (например, для больших объектов типа мультимедиа-файлов).
POST /:entity — создаёт новый объект типа :entity
В теле запроса должны быть перечислены поля объекта в формате JSON без дополнительного заворачивания, т.е.
В случае успеха сервер должен возвращать 201 Created с пустым телом, но с дополнительным заголовком
указывающим на месторасположение созданного объекта.
Возвращать тело ответа чаще всего не требуется, так как у клиента есть все необходимые данные, а id созданного объекта он может получить из Location.
Также метод POST используется для удалённого вызова процедур (RPC), в этом случае ответ будет иметь статус 200 OK и результаты в теле. Вообще смешивать REST и RPC в одном api — идея сомнительная, но всякое бывает.
Единственный неидемпотентный некешируемый метод, т.е. повтор двух одинаковых POST запросов создаст два одинаковых объекта.
PUT /:entity/:id — изменяет объект целиком
В запросе должны содержаться все поля изменяемого объекта в формате JSON.
В случае успеха должен возвращать 204 No Data с пустым телом, т.к. у клиента есть все необходимые данные.
Идемпотентный запрос, т.е. повторный PUT с таким же телом не приводит к каким-либо изменениям в БД.
PATCH /:entity/:id — изменяет отдельные поля объекта
В запросе должны быть перечислены только поля, подлежащие изменению.
В случае успеха возвращает 200 OK с телом, аналогичным запросу getById, со всеми полями изменённого объекта.
Используется с осторожностью, т.к. два параллельных PATCH от двух разных клиентов могут привести объект в невалидное состояние.
DELETE /:entity/:id — удаляет объект, если он существует.
В случае успеха возвращает 204 No Data с пустым телом, т.к. возвращать уже нечего.
Идемпотентный запрос, т.е. повторный DELETE с таким же адресом не приводит к ошибке 404.
OPTIONS /:entity[/:id]
Получает список методов, доступных по данному URI.
Сервер должен ответить 200 OK с дополнительным заголовком
Некешиуремый необязательный метод.
Обработка ошибок
Возвращаемые ошибки передаются с сервера на клиент как ответы со статусами 4хх (ошибка клиента) или 5хх (ошибка сервера). При этом описание ошибки, если оно есть, приводится в теле ответа в формате text/plain (без всякого JSON). Соответственно, передаётся заголовок ответа
Использовать html для оформления сообщений об ошибках в api — так себе идея, будут проблемы журналированием и т.д. Предполагается, что клиент способен сам красиво оформить сообщение об ошибке для пользователя.
При выборе конкретных кодов ошибок не следует слишком увлекаться и пытаться применить существующие коды только потому, что название кажется подходящим. У многих кодов есть дополнительные требования к наличию определённых заголовков и специальная обработка браузерами. Например, код 401 запускает HTTP-аутентификацию, которая будет странно смотреться в каком-нибудь приложении на react или electron.
UPD по мотивам комментариев. Клиенты у вас будут разные: не только веб и мобильные приложения, но и такие штуки, как запускалка интеграционных тестов (CI), балансировщик нагрузки или система мониторинга у админов. Использование или неиспользование того или иного статуса ошибки определяется тем, будет ли он полезен хоть какому-то клиенту (т.е. этот клиент сможет предпринять какие-то действия конкретно по этому коду) и, наоборот, не будет ли проблем у какого-то из клиентов из-за неиспользования вами этого кода. Придумать реальный use-case, когда реакция клиента будет различаться в зависимости от 404 или 410, довольно сложно. При этом отличий 404 от 200 или 500 — вагон и телега.
400 Bad Request
Универсальный код ошибки, если серверу непонятен запрос от клиента.
403 Forbidden
Возвращается, если операция запрещена для текущего пользователя. Если у оператора есть учётка с более высокими правами, он должен перелогиниться самостоятельно. См. также 419
404 Not Found
Возвращается, если в запросе был указан неизвестный entity или id несуществующего объекта.
Списочные методы get не должны возвращать этот код при верном entity (см. выше).
Если запрос вообще не удалось разобрать, следует возвращать 418.
415 Unsupported Media Type
Возвращается при загрузке файлов на сервер, если фактический формат переданного файла не поддерживается. Также может возвращаться, если не удалось распарсить JSON запроса, или сам запрос пришёл не в формате JSON.
418 I’m a Teapot
Возвращается для неизвестных серверу запросов, которые не удалось даже разобрать. Обычно это указывает на ошибку в клиенте, типа ошибки при формировании URI, либо что версии протокола клиента и сервера не совпадают.
419 Authentication Timeout
Отправляется, если клиенту нужно пройти повторную авторизацию (например, протухли куки или CSRF токены). При этом на клиенте могут быть несохранённые данные, которые будут потеряны, если просто выкинуть клиента на страницу авторизации.
422 Unprocessable Entity
Запрос корректно разобран, но содержание запроса не прошло серверную валидацию.
Например, в теле запроса были указаны неизвестные серверу поля, или не были указаны обязательные, или с содержимым полей что-то не так.
Обычно это означает ошибку в введённых пользователем данных, но может также быть вызвано ошибкой на клиенте или несовпадением версий.
500 Internal Server Error
Возвращается, если на сервере вылетело необработанное исключение или произошла другая необработанная ошибка времени исполнения.
Всё, что может сделать клиент в этом случае — это уведомить пользователя и сделать console.error(err) для более продвинутых товарищей (админов, разработчиков и тестировщиков).
501 Not Implemented
Возвращается, если текущий метод неприменим (не реализован) к объекту запроса.
Ну вот, в общем-то, и всё. Спасибо за внимание!





