Letysite.ru

IT Новости с интернет пространства
0 просмотров
Рейтинг статьи
1 звезда2 звезды3 звезды4 звезды5 звезд
Загрузка...

Access control allow origin fetch

Что такое CORS

Многие из нас встречались с подобной ошибкой:

Access to XMLHttpRequest at ‘XXXX’ from origin ‘YYYY’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource..

Эта статья рассказывает что означает эта ошибка и как от нее избавиться.

Создадим тестовый сайт на Node.js с открытым API и запустим его по адресу http://127.0.0.1:3000.

Пусть там будет примерно такая функция получения GET запроса:

Пусть там будет простая функция входа в систему, где пользователи вводят общее секретное слово secret и им затем ему устанавливается cookie, идентифицируя их как аутентифицированных:

И пусть у нас будет некое приватное API для каких нибудь личных данных в /private, только для аутентифицированных пользователей.

Запрос нашего API через AJAX из других доменов

И допустим у нас есть какое-нибудь клиентское приложение работающее с нашим API. Но учтем что, наше API находится по адресу http://127.0.0.1:3000/public, а наш клиент размещен на http://127.0.0.1:8000, и на клиенте есть следующий код:

И это не будет работать!

Если мы посмотрим на вкладку network в консоле Хрома при обращение c http://127.0.0.1:8000 к http://127.0.0.1:3000 то там не будет ошибок:

Сам по себе запрос был успешным, но результат оказался не доступен. Описание причины можно найти в консоли JavaScript:

Ага! Нам не хватает заголовка Access-Control-Allow-Origin. Но зачем он нам и для чего он вообще нужен?

Same-Origin Policy

Причиной, по которой мы не получим ответ в JavaScript, является Same-Origin Policy. Эта ограничительная мера была придумана разработчиками браузеров что бы веб-сайт не мог получить ответ на сгенерированный AJAX запрос к другому веб-сайту находящемуся по другому адресу .

Например: если вы заходите на sample.org, вы бы не хотели, чтобы этот веб-сайт отправлял запрос к примеру на ваш банковский веб-сайт и получал баланс вашего счета и транзакции.

Same-Origin Policy предотвращает именно это.

«источник (origin)» в этом случае состоит из

  • протокол (например http )
  • хост (например example.com )
  • порт (например 8000 )

Так что http://sample.org и http://www.sample.org и http://sample.org:3000 – это три разных источника.

Пару слов о CSRF

Обратите внимание, что существует класс атак, называемый подделкой межсайтовых запросов (Cross Site Request Forgerycsrf ), от которых не защищает Same-Origin Policy.

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

Так же обратите внимание, что, несмотря на то, что действует Same-Origin Policy, наш пример запроса с сайта secondparty.com на сайте 127.0.0.1:3000 будет успешно выполнен – мы просто не соможем получить доступ к результатам. Но для CSRF нам не нужен результат …

Например, API, которое позволяет отправлять электронные письма, выполняя POST запрос, отправит электронное письмо, если мы предоставим ему правильные данные. Злоумышленнику не нужно заботится о результате, его забота это отправляемое электронное письмо, которое он получит независимо от возможности видеть ответ от API.

Включение CORS для нашего публичного API

Допустим нам нужно разрешить работу JavaScript на сторонних сайтах (например, 127.0.0.1:8000) что бы получать доступ к нашим ответам API. Для этого нам нужно включить CORS в заголовок ответа от сервера. Это делается на стороне сервера:

Здесь мы устанавливаем заголовку Access-Control-Allow-Origin значение *, что означает: что любому хосту разрешен доступ к этому URL и ответу в браузере:

Непростые запросы и предварительные запросы (preflights)

Предыдущий пример был так называемым простым запросом. Простые запросы – это:

  • Запросы: GET,POST
  • Тип содержимого следующего:
    • text/plain
    • application/x-www-form-urlencoded
    • multipart/form-data

Допустим теперь 127.0.0.1:8000 немного меняет реализацию, и теперь он обрабатывает запросы в формате JSON:

Но это снова все ломает!
На этот раз консоль показывает другую ошибку:

Любой заголовок, который не разрешен для простых запросов, требует предварительного запроса (preflight request).

Этот механизм позволяет веб-серверам решать, хотят ли они разрешить фактический запрос. Браузер устанавливает заголовки Access-Control-Request-Headers и Access-Control-Request-Method, чтобы сообщить серверу, какой запрос ожидать, и сервер должен ответить соответствующими заголовками.

Но наш сервер еще не отвечает с этими заголовками, поэтому нам нужно добавить их:

Теперь мы снова может получить доступ к ответу.

Credentials и CORS

Теперь давайте предположим, что нам нужно залогинится на 127.0.0.1:3000 что бы получить доступ к /private с конфиденциальной информацией.

При всех наших настройках CORS может ли другой сайт так же получить эту конфиденциальную информацию?

Мы пропустили код реализации входа в на сервер так как он не обязателен для объяснения материала.

Независимо от того, попытаемся ли мы залогинится на 127.0.0.1:3000 или нет, мы увидим «Please login first».

Причина в том, что cookie от 127.0.0.1:3000 не будут отправляться, когда запрос поступает из другого источника. Мы можем попросить браузер отправить файлы cookie клиенту, даже если запрос с других доменов:

Но опять это не будет работать в браузере. И это хорошая новость, на самом деле.

Итак, мы не хотим, чтобы злоумышленник имел доступ к приватным данным, но что, если мы хотим, чтобы 127.0.0.1:8000 имел доступ к /private?
В этом случае нам нужно установить для заголовка Access-Control-Allow-Credentials значение true:

Но это все равно пока еще не сработает. Это опасная практика – разрешать любые аутентифицированные запросы с других источников.

Браузер не позволит нам так легко совершить ошибку.

Если мы хотим разрешить 127.0.0.1:8000 доступ к /private, нам нужно указать точный источник в заголовке:

Теперь http://127.0.0.1:8000 также имеет доступ к приватным данным, в то время как запрос с любого другого сайта будет заблокирован.

Разрешить множественные источники (origin)

Теперь мы разрешили одному источнику делать запросы к другому источнику с данными аутентификации. Но что, если у нас есть несколько других источников?

В этом случае мы, вероятно, хотим использовать белый список:

Опять же: не отправляйте напрямую req.headers.origin в качестве разрешенного заголовка CORS. Это позволит любому веб-сайту получить доступ к приватным данным.
Из этого правила могут быть исключения, но, по крайней мере, дважды подумайте, прежде чем внедрять CORS с учетными данными без белого списка.

Заключение

В этой статье мы рассмотрели Same-Origin Policy и то, как мы можем использовать CORS, чтобы разрешать запросы между источниками, когда это необходимо.

Это требует настройки на стороне сервера и на стороне клиента и в зависимости от запроса вызовет предварительный (preflight) запрос.

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

Выводы

  • Браузер использует Same-origin policy, чтобы не обрабатывать AJAX ответы от веб-сайтов расположенных на адресах отличных от адреса с которого была загружена веб страница.
  • Same-origin policy не запрещает генерировать запросы к другим сайтам, но запрещает обрабатывать от них ответ.
  • CORS (Cross-Origin Resource Sharing) механизм, который использует дополнительные заголовки HTTP, чтобы дать браузерам указание предоставить веб-приложению, работающему в одном источнике, доступ к ответу на запрос к ресурсам из другого источника.
  • CORS вместе с credentials (с данными аутентификации) требует осторожности.
  • CORS это браузерная политика. Другие приложения не затрагиваются этим понятием.

Fetch и CORS. Пример на ReactJS и другие

Йо-йо! Недавно я столкнулся с задачей — создать сайт на котором отображаются бонусы клиента. Бонусы я получаю с web-сервиса из 1С, он отдаёт мне json с данными, но предварительно там я должен авторизоваться.

Для создания этого сайта я решил использовать reactjs. Сайт довольно простой и многого там не будет, но нужно сделать авторизацию. Авторизация происходила с помощью передачи заголовка Authorization примерно вот так:

Но как только я сделать fetch и запросить данные я столкнулся с множеством проблем в том числе CORS. Я решил эти проблемы и теперь хочу поделиться своим опытом.

Fetch и авторизация

Чтобы fetch мог передавать данные для авторизации нужно явно «сказать» ему, что в нём передаются данные для авторизации с помощью credentials. Пример

В этом случае всё пройдёт гладко и вы успешно пройдёте авторизацию.

Fetch и CORS

CORS сильно портит жизнь веб-мастеру, но зато защищает нас. Чтобы описать описать взаимодействие fecth и сервера в корсcдоменных запросах я приведу несколько примеров из спецификации fetch.

Пример 1

Скрипт на https: //foo.invalid/ хочет получить некоторые данные с https: //bar.invalid/. (Ни учетные данные, ни доступ к заголовку ответа не важны.)

Читать еще:  База данных access охранная служба

При этом будет использоваться протокол CORS, хотя он полностью прозрачен для разработчика из foo.invalid. Как часть протокола CORS, пользовательский агент будет включать заголовок Origin в запрос:

Получив ответ от bar.invalid, пользовательский агент проверит заголовок ответа «Access-Control-Allow-Origin». Если его значение равно https: // foo.invalid или *, пользовательский агент вызовет успешный обратный (success) вызов. Если оно имеет какое-либо другое значение или отсутствует, пользовательский агент вызовет failure.

Пример 2

Разработчик foo.invalid вернулся и теперь хочет получить некоторые данные из bar.invalid, одновременно обращаясь к заголовку ответа.

bar.invalid предоставляет правильный заголовок ответа Access-Control-Allow-Origin в соответствии с предыдущим примером. Значения hsts и csp будут зависеть от заголовка ответа «Access-Control-Expose-Headers». Например, если в ответ включены следующие заголовки

тогда hsts будет нулевым, а csp будет «default-src ‘self», даже если ответ включает оба заголовка. Это связано с тем, что bar.invalid должен явно разделять каждый заголовок, перечисляя их имена в заголовке ответа Access-Control-Expose-Headers.

В качестве альтернативы, если bar.invalid хочет совместно использовать все свои заголовки ответа, для запросов, которые не включают учетные данные, он может использовать ‘*’ в качестве значения для заголовка ответа Access-Control-Expose-Headers. Если бы запрос включал учетные данные, имена заголовков ответов должны были бы быть перечислены явно, и ‘*’ не мог бы использоваться.

Пример 3. С передачей учётных данных (пароля)

Разработчик foo.invalid извлекает некоторые данные из bar.invalid, включая учетные данные. На этот раз протокол CORS больше не прозрачен для разработчика, поскольку учетные данные требуют явного согласия:

Это также делает все заголовки ответа Set-Cookie bar.invalid полностью функциональными (в противном случае они игнорируются).

Пользовательский агент обязательно включит в запрос все соответствующие учетные данные. Это также повысит требования к ответу. Мало того, что bar.invalid нужно будет перечислить https: // foo.invalid в качестве значения для заголовка Access-Control-Allow-Origin (‘*’ не допускается, когда задействованы учетные данные), Access-Control-Allow-Credentials заголовок также должен присутствовать:

Если ответ не включает эти два заголовка с этими значениями, будет вызван failure callback (в fetch). Однако любые заголовки ответа Set-Cookie будут соблюдены.

CORS, Fetch и сервер

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

HTTPS для ReactJS во время разработки

Я использовал статью с medium, она довольно простая.

GET преобразуется в OPTION

Во время кросс-доменных запросов get-запрос преобразуется в option в том случае если вы передаёте заголовки и в fetch’е установлено . В таком случае появляется ошибка » 405 method not allowed».

Options-запрос отправляется для того, чтобы браузер понял можно ли вообще передавать заголовки с этого домена и какие.

В том случае если вы передаёте в get-запросе, например заголовок «Authorization» то должны отдать «пачку» заголовков:

Когда fetch получит эти заголовки то автоматически отправит уже GET-запрос. Вы можете легко проверить это если посмотрите, например, в DevTools хрома (вкладка Network)

В том случае если заголовки не будут переданы то в status code от сервера вы увидите «405 method not allowed». Так же вы увидите это если не перечислите нужный метод в «Access-Control-Allow-Methods»

Если вы не понимаете, что такое fetch предлагаю прочитать мою статью «fetch в reactjs«, возможно так же вам понадобиться статья про router в react

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

Поддержи Xakplant

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

In this article, we explain what Cross-Origin Resource Sharing (CORS) is and how to avoid errors associated with it and the Access-Control-Allow-Origin header. This includes describing it both from the viewpoint of the frontend and the backend.

CORS: Cross-Origin Resource Sharing

Cross-Origin Resource Sharing (CORS) is a mechanism allowing (or disallowing) the resources to be requested from another origin than it is served on. It is built into the browsers and uses HTTP headers to determine whether or not it is safe to allow a cross-origin request. When a web application requests a source with a different origin (origin includes a domain, a protocol, and a port) it is cross-origin. Browsers restrict such requests unless the response from the other origin includes the right headers.

Let’s jump straight into coding. We use a simple Express app here:

This, when running locally, opens the http : //localhost:8080/posts endpoint.

So far so good. Now try to use Postman to perform a GET request.

A success! Let’s modify our app a little and add an additional endpoint:

This will give us an empty document at the http : //localhost:8080 address. Let’s open it in the browser, and in DevTools execute:

Works fine as well!

In this example, we run our request in the same origin, but this is often not the case. Imagine creating a frontend app that runs in a different origin, for example on a different port. To create such a situation, let’s run an additional express app on a different port.

Now, let’s open our second app at the address http : //localhost:4200 and try to perform the same fetch request.

This results in an error:

Access to fetch at ‘http://localhost:8080/posts’ from origin ‘http://localhost:4200’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

As you can see, the request itself was successful, but the browser blocked it.

Conclusions

  • The first example includes us using Postman, so the CORS mechanism wasn’t involved
  • In the second example, we perform a request from the same origin, so the CORS mechanism didn’t block our request
  • The third example is a Cross-Origin request and therefore it is blocked.
    This does not need to be the case. As the error states, we can set the Access-Control-Allow-Origin header. You need to attach it to the response that the browser receives from the server.

Access-Control-Allow-Origin header

To specify what origins have access to the resource, you need to add the Access-Control-Allow-Origin header to your response. It will be interpreted by the browser of the visitor of your site.

While using Express there are a few ways to do that. The simplest one is to attach the header straight in the handler:

This will tell the browser that it is safe to request a resource from that origin.

It works! But that means that you would have to call setHeader in the every one of your handlers. This is where you can use middleware:

If you call the use function, the callback you provide will be executed every time a request is sent to the server. It results in attaching the Access-Control-Allow-Origin header to all your responses.

Possible values

One of the possibilities is to specify an exact origin as we did in the previous example. If you choose to be specific, you need to all the way: browsers do not support multiple Access-Control-Allow-Origin headers. On the other hand, you can use a wildcard:

res . setHeader ( ‘Access-Control-Allow-Origin’ , ‘*’ ) ;

This value tells the browser that the given resource can be shared with any origin. There is one catch though: when using a wildcard, you can’t send or receive cookies. If you try to do so, the browser throws an error.

Other ways to bypass the CORS policy

One way to override the CORS policy is to install an extension such as Allow-Control-Allow-Origin: *. It Adds the Allow — Control — Allow — Origin : * header to the all the responses that your browser receives. As mentioned above, it disrupts the way that cookies are sent and received, so keep that in mind.

Another thing you can do is to specify in your request, that you want to bypass the CORS secure mechanism. You can do it if you use Fetch API by setting the mode parameter to no-cors:

Читать еще:  Формы в access используются для

This will work regardless of the Access-Control-Allow-Origin header. There is no equivalent of that in the XMLHttpRequest, unfortunately.

If you would like to know more about Fetch API and XMLHttpRequest, check out Comparing working with JSON using the XHR and the Fetch API

Summary

In this article, we explained what the Cross-Origin Resource Sharing (CORS) is, and how can we deal with it in terms of the origin access control. It included creating a simple backend express app and sending requests both from Postman and the browser to illustrate how the CORS works. Aside from that, the article provided tips on how to deal with this error by setting the Access-Control-Allow-Origin header, using browser extensions and an additional parameter that you can set in the Fetch API request. This can help you design both your frontend and backend while keeping the CORS mechanism in mind.

Thanks to that, you can avoid errors like that one:

No ‘Access-Control-Allow-Origin’ header is present on the requested resource.

Как работает заголовок Access-Control-Allow-Origin?

видимо, я совершенно неправильно понял его слова. Я подумал о чем-то подобном:—1—>

  1. клиент загружает код javascript MyCode.js от http://siteA —источник.
  2. заголовок ответа MyCode.Яш содержит Access-Control-Allow-Origin: http://siteB, что, как я думал, означало этот Микод.js было разрешено делать перекрестные ссылки на сайт B.
  3. клиент запускает некоторые функции Mycode в.js, которые в свою очередь делают запросы http://siteB, что должно быть хорошо, несмотря на запросы перекрестного происхождения.

одно точно — я все еще не понимаю, как я должен использовать этот заголовок.

У меня есть полный контроль сайт A и сайт B. Как включить код javascript, загруженный с сайта A, для доступа к ресурсам на сайте B с помощью этого заголовка?

Я не хочу использовать JSONP.

11 ответов

когда сайт A пытается получить контент с сайта B, сайт B может отправить Access-Control-Allow-Origin заголовок ответа, чтобы сообщить браузеру, что содержимое этой страницы доступна в определенное происхождение. (An происхождения это домен, плюс схема и номер порта.) По умолчанию страницы сайта B имеют значение недоступно для любого другого источника; через Access-Control-Allow-Origin заголовок открывает дверь для доступа cross-origin специфическим запрашивая происхождением.

для каждого ресурса / страницы, которую сайт B хочет сделать доступной для сайта A, сайт B должен обслуживать свои страницы с заголовком ответа:

современные браузеры не будут блокировать междоменные запросы напрямую. Если сайт A запрашивает страницу с сайта B, браузер фактически получит запрошенную страницу на сетевом уровне и проверьте, разрешен ли сайт списка заголовков ответов A как разрешенный домен отправителя. Если сайт B не указал, что сайту A разрешен доступ к этой странице, браузер запустит XMLHttpRequest ‘ s error event и запретить данные ответа на запрос кода JavaScript.

не простые запросы

что происходит на сетевом уровне может быть немного сложнее, чем описано выше. Если запрос «не простой» запрос, браузер сначала отправляет запрос параметров» preflight » без данных, чтобы убедитесь, что сервер примет запрос. Запрос не является простым, когда либо (или оба):

  • использование HTTP-глагола, отличного от GET или POST (например, PUT, DELETE)
  • используя не простой заголовков запроса; только простые запросы заголовки:
    • Accept
    • Accept-Language
    • Content-Language
    • Content-Type (это просто, только когда его значение application/x-www-form-urlencoded , multipart/form-data , или text/plain )

если сервер отвечает на параметры preflight с соответствующими заголовками ответов ( Access-Control-Allow-Headers для не простых заголовков, Access-Control-Allow-Methods для не-простых глаголов), которые соответствуют не-простому глаголу и / или не-простым заголовкам, затем браузер отправляет фактический запрос.

предположим, что сайт A хочет отправить запрос PUT для /somePage С не-простой Content-Type стоимостью application/json , браузер сначала отправит предполетный запрос:

отметим, что Access-Control-Request-Method и Access-Control-Request-Headers добавляются браузером автоматически; вам не нужно добавлять их. Эта опция preflight получает успешные заголовки ответов:

при отправке фактического запроса (после завершения предполетной подготовки) поведение идентично тому, как обрабатывается простой запрос. Другими словами, не простой запрос, префлайт которого успешен, обрабатывается так же, как простой запрос (т. е. сервер все равно должен отправить Access-Control-Allow-Origin снова для фактического ответа).

браузеры отправляют фактический запрос:

и сервер отправляет обратно Access-Control-Allow-Origin так же, как и для простого запроса:

посмотреть понимание XMLHttpRequest над CORS для получения дополнительной информации о не простых запросах.

Совместное Использование Запросов Cross-Origin — CORS (A. K. A. Междоменный запрос AJAX)-это проблема, с которой может столкнуться большинство веб-разработчиков, в соответствии с политикой того же происхождения, браузеры ограничивают клиентский JavaScript в песочнице безопасности, обычно JS не может напрямую связываться с удаленным сервером из другого домена. В прошлом разработчики создали много сложных способов достижения междоменного запроса ресурсов, чаще всего используя следующие способы:

  1. использование Flash/Silverlight или на стороне сервера как «прокси» общаться с пульта дистанционного управления.
  2. JSON с прокладкой (JSONP).
  3. встраивает удаленный сервер в iframe и взаимодействует через фрагмент или окно.имя, refer здесь.

эти сложные способы имеют более или менее некоторые проблемы, например, JSONP может привести к дыре в безопасности, если разработчики просто «eval» его, и #3 выше, хотя он работает, оба домена должны строить строгий контракт между собой, это ни гибкий и элегантный IMHO:)

W3C ввела совместное использование ресурсов (CORS) в качестве стандартного решения для обеспечения безопасного, гибкого и рекомендуемого стандартного способа решения этой проблемы.

Механизм

С высокого уровня мы можем просто считать, что CORS-это контракт между клиентским AJAX-вызовом из домена A и страницей, размещенной в домене B, типичным запросом/ответом Кросс-происхождения будет:

запрос AJAX DomainA заголовки

заголовки ответов DomainB

синие части, отмеченные выше, были ядровыми фактами, заголовок запроса» Origin «указывает, откуда исходит запрос кросс-происхождения или запрос предполетной подготовки», заголовок ответа «Access-Control-Allow-Origin» указывает, что эта страница разрешает удаленный запрос от DomainA (если значение * указывает, разрешает удаленные запросы из любого домена).

как я уже упоминал выше, W3 рекомендуемый браузер для реализации «предварительный запрос » перед отправкой фактически перекрестного HTTP-запроса, в двух словах это HTTP OPTIONS запрос:

если Foo.aspx поддерживает параметры http-глагола, он может возвращать ответ, как показано ниже:

только если ответ содержит «Access-Control-Allow-Origin» и его значение » * » или содержит домен, который отправил запрос CORS, удовлетворяя этому условию mandtory браузер будет отправьте фактический Междоменный запрос и кэшируйте результат в «Предварительный Результат-Кэш«.

Я написал в блоге о CORS три года назад:AJAX перекрестный HTTP-запрос

Working with the Fetch API

We’re in the process of restructuring our PWA training resources.

You can use the materials linked to from this page, but some of the content may be out of date.

We’re still working on updating written materials, but check out our new codelabs and videos.

What is fetch?

The Fetch API is a simple interface for fetching resources. Fetch makes it easier to make web requests and handle responses than with the older XMLHttpRequest, which often requires additional logic (for example, for handling redirects).

Note: Fetch supports the Cross Origin Resource Sharing (CORS). Testing generally requires running a local server. Note that although fetch does not require HTTPS, service workers do and so using fetch in a service worker requires HTTPS. Local servers are exempt from this.

You can check for browser support of fetch in the window interface. For example:

main.js

There is a polyfill for browsers that are not currently supported (but see the readme for important caveats.).

The fetch() method takes the path to a resource as input. The method returns a promise that resolves to the Response of that request.

Making a request

Let’s look at a simple example of fetching a JSON file:

main.js

We pass the path for the resource we want to retrieve as a parameter to fetch. In this case this is examples/example.json. The fetch call returns a promise that resolves to a response object.

When the promise resolves, the response is passed to .then . This is where the response could be used. If the request does not complete, .catch takes over and is passed the corresponding error.

Response objects represent the response to a request. They contain the requested resource and useful properties and methods. For example, response.ok , response.status , and response.statusText can all be used to evaluate the status of the response.

Evaluating the success of responses is particularly important when using fetch because bad responses (like 404s) still resolve. The only time a fetch promise will reject is if the request was unable to complete. The previous code segment would only fall back to . catch if there was no network connection, but not if the response was bad (like a 404). If the previous code were updated to validate responses it would look like:

Читать еще:  Access remote pc

main.js

Now if the response object’s ok property is false (indicating a non 200-299 response), the function throws an error containing response.statusText that triggers the .catch block. This prevents bad responses from propagating down the fetch chain.

Reading the response object

Responses must be read in order to access the body of the response. Response objects have methods for doing this. For example, Response.json() reads the response and returns a promise that resolves to JSON. Adding this step to the current example updates the code to:

main.js

This code will be cleaner and easier to understand if it’s abstracted into functions:

main.js

To summarize what’s happening:

Step 1. Fetch is called on a resource, examples/example.json. Fetch returns a promise that will resolve to a response object. When the promise resolves, the response object is passed to validateResponse .

Step 2. validateResponse checks if the response is valid (is it a 200-299?). If it isn’t, an error is thrown, skipping the rest of the then blocks and triggering the catch block. This is particularly important. Without this check bad responses are passed down the chain and could break later code that may rely on receiving a valid response. If the response is valid, it is passed to readResponseAsJSON .

Step 3. readResponseAsJSON reads the body of the response using the Response.json() method. This method returns a promise that resolves to JSON. Once this promise resolves, the JSON data is passed to logResult . (Can you think of what would happen if the promise from response.json() rejects?)

Step 4. Finally, the JSON data from the original request to examples/example.json is logged by logResult .

For more information

Example: fetching images

Let’s look at an example of fetching an image and appending it to a web page.

main.js

In this example an image (examples/kitten.jpg) is fetched. As in the previous example, the response is validated with validateResponse . The response is then read as a Blob (instead of as JSON), and an image element is created and appended to the page, and the image’s src attribute is set to a data URL representing the Blob.

Note: The URL object’s createObjectURL() method is used to generate a data URL representing the Blob. This is important to note as you cannot set an image’s source directly to a Blob. The Blob must first be converted into a data URL.

For more information

Example: fetching text

Let’s look at another example, this time fetching some text and inserting it into the page.

main.js

In this example a text file is being fetched, examples/words.txt. Like the previous two exercises, the response is validated with validateResponse . Then the response is read as text, and appended to the page.

For more information

  • Response.text()

Note: For completeness, the methods we have used are actually methods of Body, a Fetch API mixin that is implemented in the Response object.

Making custom requests

fetch() can also receive a second optional parameter, init , that allows you to create custom settings for the request, such as the request method, cache mode, credentials, and more.

Example: HEAD requests

By default fetch uses the GET method, which retrieves a specific resource, but other request HTTP methods can also be used.

HEAD requests are just like GET requests except the body of the response is empty. You can use this kind of request when all you want the file’s metadata, and you want or need the file’s data to be transported.

To call an API with a HEAD request, set the method in the init parameter. For example:

main.js

This will make a HEAD request for examples/words.txt.

You could use a HEAD request to check the size of a resource. For example:

main.js

Here the HEAD method is used to request the size (in bytes) of a resource (represented in the content-length header) without actually loading the resource itself. In practice this could be used to determine if the full resource should be requested (or even how to request it).

Example: POST requests

Fetch can also send data to an API with POST requests. The following code sends a «title» and «message» (as a string) to someurl/comment:

main.js

The method is again specified with the init parameter. This is also where the body of the request is set, which represents the data to be sent (in this case the title and message).

The body data could also be extracted from a form using the FormData interface. For example, the above code could be updated to:

main.js

Custom headers

The init parameter can be used with the Headers interface to perform various actions on HTTP request and response headers, including retrieving, setting, adding, and removing them. An example of reading response headers was shown in a previous section. The following code demonstrates how a custom Headers object can be created and used with a fetch request:

main.js

Here we are creating a Headers object where the Content-Type header has the value of text/plain and a custom X-Custom-Header header has the value of hello world .

Custom headers on cross-origin requests must be supported by the server from which the resource is requested. The server in this example would need to be configured to accept the X-Custom-Header header in order for the fetch to succeed. When a custom header is set, the browser performs a preflight check. This means that the browser first sends an OPTIONS request to the server to determine what HTTP methods and headers are allowed by the server. If the server is configured to accept the method and headers of the original request, then it is sent. Otherwise, an error is thrown.

For more information

Cross-origin requests

Fetch (and XMLHttpRequest) follow the same-origin policy. This means that browsers restrict cross-origin HTTP requests from within scripts. A cross-origin request occurs when one domain (for example http:// foo.com/) requests a resource from a separate domain (for example http:// bar.com/). This code shows a simple example of a cross-origin request:

main.js

There have been attempts to work around the same-origin policy (such as JSONP). The Cross Origin Resource Sharing (CORS) mechanism has enabled a standardized means of retrieving cross-origin resources. The CORS mechanism lets you specify in a request that you want to retrieve a cross-origin resource (in fetch this is enabled by default). The browser adds an Origin header to the request, and then requests the appropriate resource. The browser only returns the response if the server returns an Access-Control-Allow-Origin header specifying that the origin has permission to request the resource. In practice, servers that expect a variety of parties to request their resources (such as 3rd party APIs) set a wildcard value for the Access-Control-Allow-Origin header, allowing anyone to access that resource.

If the server you are requesting from doesn’t support CORS, you should get an error in the console indicating that the cross-origin request is blocked due to the CORS Access-Control-Allow-Origin header being missing.

You can use no-cors mode to request opaque resources. Opaque responses can’t be accessed with JavaScript but the response can still be served or cached by a service worker. Using no-cors mode with fetch is relatively simple. To update the above example with no-cors , we pass in the init object with mode set to no-cors :

main.js

For more information

Further reading

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

Ссылка на основную публикацию
Adblock
detector