Return to site

Fetch Catch

broken image


In this tutorial, I will show you how to fetch and display data from a JSON file using vanilla JavaScript. So how will we achieve this? First, we will fetch the JSON data by using the fetch API. This will return a promise with our JSON data. Then we will append the data dynamically. Fetch requests are controlled by the connect-src directive of Content Security Policy rather than the directive of the resources it's retrieving. Supplying request options. The fetch method can optionally accept a second parameter, an init object that allows you to control a number of different settings. See fetch for the full options available, and more details. When using promises, the catch block is usually used after the then block to handle errors. That's why it can be used for the native fetch API. That's why it can be used for the native fetch API. Class App extends Component.

If we send a fetch request to another web-site, it will probably fail.

For instance, let's try fetching http://example.com:

Fetch fails, as expected.

The core concept here is origin – a domain/port/protocol triplet.

Cross-origin requests – those sent to another domain (even a subdomain) or protocol or port – require special headers from the remote side.

That policy is called 'CORS': Cross-Origin Resource Sharing.

Fetch catch error

Why is CORS needed? A brief history

CORS exists to protect the internet from evil hackers.

Seriously. Let's make a very brief historical digression.

For many years a script from one site could not access the content of another site.

That simple, yet powerful rule was a foundation of the internet security. E.g. an evil script from website hacker.com could not access user's mailbox at website gmail.com. People felt safe.

JavaScript also did not have any special methods to perform network requests at that time. It was a toy language to decorate a web page.

But web developers demanded more power. A variety of tricks were invented to work around the limitation and make requests to other websites.

Using forms

One way to communicate with another server was to submit a

there. People submitted it into </code>, just to stay on the current page, like this:</p><p>So, it was possible to make a GET/POST request to another site, even without networking methods, as forms can send data anywhere. But as it's forbidden to access the content of an <code><iframe></code> from another site, it wasn't possible to read the response.</p><p>To be precise, there were actually tricks for that, they required special scripts at both the iframe and the page. So the communication with the iframe was technically possible. Right now there's no point to go into details, let these dinosaurs rest in peace.</p><h3>Using scripts</h3><p>Another trick was to use a <code>script</code> tag. A script could have any <code>src</code>, with any domain, like <code><script src='http://another.com/…'></code>. It's possible to execute a script from any website.</p><h3 id='fetch-catch-404'>Fetch Catch 404</h3><p>If a website, e.g. <code>another.com</code> intended to expose data for this kind of access, then a so-called 'JSONP (JSON with padding)' protocol was used.</p><p>Here's how it worked.</p><p>Let's say we, at our site, need to get the data from <code>http://another.com</code>, such as the weather:</p><ol><li><p>First, in advance, we declare a global function to accept the data, e.g. <code>gotWeather</code>.</p></li><li><p>Then we make a <code><script></code> tag with <code>src='http://another.com/weather.json?callback=gotWeather'</code>, using the name of our function as the <code>callback</code> URL-parameter.</p></li><li><p>The remote server <code>another.com</code> dynamically generates a script that calls <code>gotWeather(..)</code> with the data it wants us to receive.</p></li><li><p>When the remote script loads and executes, <code>gotWeather</code> runs, and, as it's our function, we have the data.</p></li></ol><p>That works, and doesn't violate security, because both sides agreed to pass the data this way. And, when both sides agree, it's definitely not a hack. There are still services that provide such access, as it works even for very old browsers.</p><p>After a while, networking methods appeared in browser JavaScript.</p><p>At first, cross-origin requests were forbidden. But as a result of long discussions, cross-origin requests were allowed, but with any new capabilities requiring an explicit allowance by the server, expressed in special headers.</p><h2>Simple requests</h2><p><a href='https://worldofdownload.mystrikingly.com/blog/filechute-4-5-6'>Filechute 4 5 6</a>. There are two types of cross-origin requests:</p><ol><li>Simple requests.</li><li>All the others.</li></ol><p>Simple Requests are, well, simpler to make, so let's start with them.</p><p>A simple request is a request that satisfies two conditions:</p><ol><li>Simple method: GET, POST or HEAD</li><li>Simple headers – the only allowed custom headers are:<ul><li><code>Accept</code>,</li><li><code>Accept-Language</code>,</li><li><code>Content-Language</code>,</li><li><code>Content-Type</code> with the value <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code> or <code>text/plain</code>.</li></ul></li></ol><p>Any other request is considered 'non-simple'. For instance, a request with <code>PUT</code> method or with an <code>API-Key</code> HTTP-header does not fit the limitations.</p><p><strong>The essential difference is that a 'simple request' can be made with a <code><form></code> or a <code><script></code>, without any special methods.</strong></p><p>So, even a very old server should be ready to accept a simple request.</p><p>Contrary to that, requests with non-standard headers or e.g. method <code>DELETE</code> can't be created this way. For a long time JavaScript was unable to do such requests. So an old server may assume that such requests come from a privileged source, 'because a webpage is unable to send them'.</p><p>When we try to make a non-simple request, the browser sends a special 'preflight' request that asks the server – does it agree to accept such cross-origin requests, or not?</p><p>And, unless the server explicitly confirms that with headers, a non-simple request is not sent.</p><p>Now we'll go into details.</p><h3 id='fetch-catch-400'>Fetch Catch 400</h3><h2>CORS for simple requests</h2><p>If a request is cross-origin, the browser always adds <code>Origin</code> header to it.</p><p>For instance, if we request <code>https://anywhere.com/request</code> from <code>https://javascript.info/page</code>, the headers will be like:</p><p>As you can see, <code>Origin</code> header contains exactly the origin (domain/protocol/port), without a path.</p><p>The server can inspect the <code>Origin</code> and, if it agrees to accept such a request, adds a special header <code>Access-Control-Allow-Origin</code> to the response. That header should contain the allowed origin (in our case <code>https://javascript.info</code>), or a star <code>*</code>. Then the response is successful, otherwise an error.</p><p>The browser plays the role of a trusted mediator here:</p><ol><li>It ensures that the correct <code>Origin</code> is sent with a cross-origin request.</li><li>It checks for permitting <code>Access-Control-Allow-Origin</code> in the response, if it exists, then JavaScript is allowed to access the response, otherwise it fails with an error.</li></ol><p>Here's an example of a permissive server response:</p><h2>Response headers</h2><p>For cross-origin request, by default JavaScript may only access so-called 'simple' response headers:</p><ul><li><code>Cache-Control</code></li><li><code>Content-Language</code></li><li><code>Content-Type</code></li><li><code>Expires</code></li><li><code>Last-Modified</code></li><li><code>Pragma</code></li></ul><p>Accessing any other response header causes an error.</p><p>There's no <code>Content-Length</code> header in the list!</p><p>This header contains the full response length. So, if we're downloading something and would like to track the percentage of progress, then an additional permission is required to access that header (see below).</p><p>To grant JavaScript access to any other response header, the server must send <code>Access-Control-Expose-Headers</code> header. It contains a comma-separated list of non-simple header names that should be made accessible.</p><p>For example:</p><p>With such <code>Access-Control-Expose-Headers</code> header, the script is allowed to read <code>Content-Length</code> and <code>API-Key</code> headers of the response.</p><h2>'Non-simple' requests</h2><p>We can use any HTTP-method: not just <code>GET/POST</code>, but also <code>PATCH</code>, <code>DELETE</code> and others.</p><p>Some time ago no one could even imagine that a webpage could make such requests. So there may still exist webservices that treat a non-standard method as a signal: 'That's not a browser'. They can take it into account when checking access rights.</p><p>So, to avoid misunderstandings, any 'non-simple' request – that couldn't be done in the old times, the browser does not make such requests right away. Before it sends a preliminary, so-called 'preflight' request, asking for permission.</p><p>A preflight request uses method <code>OPTIONS</code>, no body and two headers:</p><ul><li><code>Access-Control-Request-Method</code> header has the method of the non-simple request.</li><li><code>Access-Control-Request-Headers</code> header provides a comma-separated list of its non-simple HTTP-headers.</li></ul><p>If the server agrees to serve the requests, then it should respond with empty body, status 200 and headers:</p><ul><li><code>Access-Control-Allow-Origin</code> must be either <code>*</code> or the requesting origin, such as <code>https://javascript.info</code>, to allow it.</li><li><code>Access-Control-Allow-Methods</code> must have the allowed method.</li><li><code>Access-Control-Allow-Headers</code> must have a list of allowed headers.</li><li>Additionally, the header <code>Access-Control-Max-Age</code> may specify a number of seconds to cache the permissions. So the browser won't have to send a preflight for subsequent requests that satisfy given permissions.</li></ul><p>Let's see how it works step-by-step on example, for a cross-origin <code>PATCH</code> request (this method is often used to update data):</p><p>There are three reasons why the request is not simple (one is enough):</p><ul><li>Method <code>PATCH</code></li><li><code>Content-Type</code> is not one of: <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code>, <code>text/plain</code>.</li><li>'Non-simple' <code>API-Key</code> header.</li></ul><h3>Step 1 (preflight request)</h3><p>Prior to sending such request, the browser, on its own, sends a preflight request that looks like this:</p><ul><li>Method: <code>OPTIONS</code>.</li><li>The path – exactly the same as the main request: <code>/service.json</code>.</li><li>Cross-origin special headers:<ul><li><code>Origin</code> – the source origin.</li><li><code>Access-Control-Request-Method</code> – requested method.</li><li><code>Access-Control-Request-Headers</code> – a comma-separated list of 'non-simple' headers.</li></ul></li></ul><h3>Step 2 (preflight response)</h3><p>The server should respond with status 200 and headers:</p><ul><li><code>Access-Control-Allow-Origin: https://javascript.info</code></li><li><code>Access-Control-Allow-Methods: PATCH</code></li><li><code>Access-Control-Allow-Headers: Content-Type,API-Key</code>.</li></ul><p>That allows future communication, otherwise an error is triggered.</p><p>If the server expects other methods and headers in the future, it makes sense to allow them in advance by adding to the list.</p><p>For example, this response also allows <code>PUT</code>, <code>DELETE</code> and additional headers:</p><p>Now the browser can see that <code>PATCH</code> is in <code>Access-Control-Allow-Methods</code> and <code>Content-Type,API-Key</code> are in the list <code>Access-Control-Allow-Headers</code>, so it sends out the main request.</p><p>If there's header <code>Access-Control-Max-Age</code> with a number of seconds, then the preflight permissions are cached for the given time. The response above will be cached for 86400 seconds (one day). Within this timeframe, subsequent requests will not cause a preflight. Assuming that they fit the cached allowances, they will be sent directly.</p><h3>Step 3 (actual request)</h3><p>When the preflight is successful, the browser now makes the main request. The algorithm here is the same as for simple requests.</p><p>The main request has <code>Origin</code> header (because it's cross-origin):</p><h3>Step 4 (actual response)</h3><p>The server should not forget to add <code>Access-Control-Allow-Origin</code> <a href='https://worldofdownload.mystrikingly.com/blog/corelcad-2020-20-0-0-1074-powerful-cad-solution'>Corelcad 2020 20 0 0 1074 – powerful cad solution</a>. to the main response. A successful preflight does not relieve from that:</p><p>Then JavaScript is able to read the main server response.</p><p>Preflight request occurs 'behind the scenes', it's invisible to JavaScript.</p><p><a href='https://worldofdownload.mystrikingly.com/blog/3dweather-2-1-1' title='3dweather 2 1 1'>3dweather 2 1 1</a>. JavaScript only gets the response to the main request or an error if there's no server permission.</p><h2>Credentials</h2><p>A cross-origin request initiated by JavaScript code by default does not bring any credentials (cookies or HTTP authentication).</p><p>That's uncommon for HTTP-requests. Usually, a request to <code>http://site.com</code> is accompanied by all cookies from that domain. But cross-origin requests made by JavaScript methods are an exception.</p><p>For example, <code>fetch('http://another.com')</code> does not send any cookies, even those (!) that belong to <code>another.com</code> domain.</p><p>Why?</p><p>That's because a request with credentials is much more powerful than without them. If allowed, it grants JavaScript the full power to act on behalf of the user and access sensitive information using their credentials.</p><p>Does the server really trust the script that much? Then it must explicitly allow requests with credentials with an additional header.</p><p>To send credentials in <code>fetch</code>, we need to add the option <code>credentials: 'include'</code>, like this:</p><p>Now <code>fetch</code> sends cookies originating from <code>another.com</code> with request to that site.</p><p>If the server agrees to accept the request <em>with credentials</em>, it should add a header <code>Access-Control-Allow-Credentials: true</code> to the response, in addition to <code>Access-Control-Allow-Origin</code>.</p><p>For example:</p><p>Please note: <code>Access-Control-Allow-Origin</code> is prohibited from using a star <code>*</code> for requests with credentials. Like shown above, it must provide the exact origin there. That's an additional safety measure, to ensure that the server really knows who it trusts to make such requests.</p><h2>Summary</h2><p>From the browser point of view, there are two kinds of cross-origin requests: 'simple' and all the others.</p><p>Simple requests must satisfy the following conditions:</p><ul><li>Method: GET, POST or HEAD.</li><li>Headers – we can set only:<ul><li><code>Accept</code></li><li><code>Accept-Language</code></li><li><code>Content-Language</code></li><li><code>Content-Type</code> to the value <code>application/x-www-form-urlencoded</code>, <code>multipart/form-data</code> or <code>text/plain</code>.</li></ul></li></ul><p>The essential difference is that simple requests were doable since ancient times using <code><form></code> or <code><script></code> tags, while non-simple were impossible for browsers for a long time.</p><p>So, the practical difference is that simple requests are sent right away, with <code>Origin</code> header, while for the other ones the browser makes a preliminary 'preflight' request, asking for permission.</p><p><strong>For simple requests:</strong></p><ul><li>→ The browser sends <code>Origin</code> header with the origin.</li><li>← For requests without credentials (not sent default), the server should set:<ul><li><code>Access-Control-Allow-Origin</code> to <code>*</code> or same value as <code>Origin</code></li></ul></li><li>← For requests with credentials, the server should set:<ul><li><code>Access-Control-Allow-Origin</code> to same value as <code>Origin</code></li><li><code>Access-Control-Allow-Credentials</code> to <code>true</code></li></ul></li></ul><h3 id='fetch-catch-error'>Fetch Catch Error</h3><p>Additionally, to grant JavaScript access to any response headers except <code>Cache-Control</code>, <code>Content-Language</code>, <code>Content-Type</code>, <code>Expires</code>, <code>Last-Modified</code> or <code>Pragma</code>, the server should list the allowed ones in <code>Access-Control-Expose-Headers</code> header.</p><p><strong>For non-simple requests, a preliminary 'preflight' request is issued before the requested one:</strong></p><ul><li>→ The browser sends <code>OPTIONS</code> request to the same URL, with headers:<ul><li><code>Access-Control-Request-Method</code> has requested method.</li><li><code>Access-Control-Request-Headers</code> lists non-simple requested headers.</li></ul></li><li>← The server should respond with status 200 and headers:<ul><li><code>Access-Control-Allow-Methods</code> with a list of allowed methods,</li><li><code>Access-Control-Allow-Headers</code> with a list of allowed headers,</li><li><code>Access-Control-Max-Age</code> with a number of seconds to cache permissions.</li></ul></li><li>Then the actual request is sent, the previous 'simple' scheme is applied.</li></ul><p>Fetch n' Catch is a locally owned and operated pet care facility founded in 2012. Cousins Dan and Mallory Poirier decided to open Fetch n' Catch shortly after Dan graduated college and Mallory moved back to Buffalo, her hometown. They have grown their business to a team of over 30 dedicated staff members, and offer a variety of services including dog daycare, boarding, grooming, and obedience training! Dan and Mallory are both Professional Certified Animal Care Providers, by the Professional Animal Care Certification Council. They were the first individuals in New York State with this distinction.</p><p><em>Our purpose is to provide a safe, fun, and interactive experience for the dogs in our community. We create a family atmosphere and deliver peace of mind.</em></p><h3>View our virtual tour below!</h3><br><br><br><br>
broken image