I need to catch error 401 Code of response so that I can retry after getting a new token from token endpoint. I am using fetch method get data from API.
const request: Request = new Request(url.toString(), {
headers: this.defaultRequestHeaders,
method: "get",
mode: "cors"
});
const headers: Headers = new Headers({
"Accept": "application/json",
"Content-Type": "application/json"
});
fetch(request)
.then(function(response)
{
///Logic code
})
.catch(function(error)
{
///if status code 401. Need help here
});
asked Apr 18, 2018 at 14:32
Vikrant SinghVikrant Singh
6421 gold badge5 silver badges17 bronze badges
15
You can check the status and if it’s not 200 (ok) throw an error
fetch("some-url")
.then(function(response)
{
if(response.status!==200)
{
throw new Error(response.status)
}
})
.catch(function(error)
{
///if status code 401...
});
answered Jan 9, 2019 at 21:22
3
Because 401
is actually a valid response to a request to a server, it will execute your valid response regardless. Only if security issues occur, or if the server is unresponsive or simply not available will the catch
clause be used. Just think of it like trying to talk to somebody. Even if they say «I am currently not available» or «I don’t have that information», your conversation was still successful. Only if a security guy comes in between you and stops you from talking to the recipient, or if the recipient is dead, will there be an actual failure in conversation and will you need to respond to that using a catch
.
Just separate out your error handling code so you can handle it in instances that the request was successful, but does not have the desired outcome, as well as when an actual error is being thrown:
function catchError( error ){
console.log( error );
}
request.then(response => {
if( !response.ok ){
catchError( response );
} else {
... Act on a successful response here ...
}
}).catch( catchError );
I am using the response.ok
suggested by @Noface in the comments, as it makes sense, but you could check for only the response.status === 401
if you want to.
answered Apr 18, 2018 at 15:34
somethingheresomethinghere
16.4k2 gold badges28 silver badges42 bronze badges
4
You can try this
fetch(request)
.then(function(response) {
if (response.status === 401) {
// do what you need to do here
}
})
.catch(function(error) {
console.log('DO WHAT YOU WANT')
});
answered Jul 31, 2018 at 12:42
You can check the status
of the response in then
:
fetch(request)
.then(function(response) {
if (response.status === 401) {
// do what you need to do here
}
})
.catch(function(error) {});
answered Apr 18, 2018 at 14:48
DarioDario
6,1609 gold badges39 silver badges50 bronze badges
4
fetch(url,{
method: 'GET',
headers,
body: JSON.stringify(aData)
}).then(response => {
if(response.ok){
return response.json();
}
return Promise.reject(response);
}).catch(e => {
if(e.status === 401){
// here you are able to do what you need
// refresh token ..., logout the user ...
console.log(e);
}
return Promise.reject(e.json());
});
answered Aug 26, 2020 at 1:43
2
(function () {
var originalFetch = fetch;
fetch = function() {
return originalFetch.apply(this, arguments).then(function(data) {
someFunctionToDoSomething();
return data;
});
};})();
source
Can one use the Fetch API as a Request Interceptor?
answered Jul 11, 2019 at 8:22
When you want to…
catch (error) {
console.dir(error) // error.response contains your response
}
answered Mar 31, 2020 at 10:09
When using the fetch method of JavaScript to make API calls, it is common to encounter errors such as the 401 error, which indicates that the user is not authorized to access the requested resource. In this guide, we will show you how to catch and handle the 401 error using the fetch method of JavaScript.
Step 1: Make the Fetch Request
To make a fetch request, you can use the following code:
fetch('https://example.com/data')
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => {
// Handle the response data
})
.catch(error => {
// Handle the error
});
Step 2: Check for the 401 Error
To catch the 401 error, you can add a check for the response status code in the first `then()` block. If the status code is 401, you can throw an error.
fetch('https://example.com/data')
.then(response => {
if (!response.ok) {
if (response.status === 401) {
throw Error('You are not authorized to access this resource.');
}
throw Error(response.statusText);
}
return response.json();
})
.then(data => {
// Handle the response data
})
.catch(error => {
// Handle the error
});
Step 3: Handle the 401 Error
In the `catch()` block, you can check for the error message and handle the 401 error accordingly.
fetch('https://example.com/data')
.then(response => {
if (!response.ok) {
if (response.status === 401) {
throw Error('You are not authorized to access this resource.');
}
throw Error(response.statusText);
}
return response.json();
})
.then(data => {
// Handle the response data
})
.catch(error => {
if (error.message === 'You are not authorized to access this resource.') {
// Handle the 401 error
} else {
// Handle other errors
}
});
That’s it! With these steps, you can catch and handle the 401 error using the fetch method of JavaScript.
Is there a way to catch a 401 error code? I first thought I could add it to the checkStatus
function but
it seems that a 401 does reject the promise.
But there is little to no information in the error object.
Am I missing something?
Curious, Fetch shouldn’t reject the promise on HTTP errors, maybe edit your issue and paste the code you’re using?
I should have mentioned that I’m using Chrome 47. So if I understand correctly it actually doesn’t use the fallback but just the standard spec. So it seems there’s some issue there…
The polyfill is not active in browsers that include a native implementation of window.fetch
, including Chrome and Firefox.
Here’s how you can detect and handle a 401 status code in the response from the server.
fetch('/').then(function(response) { if (response.status === 401) { // 401 returned from server } else { // another status code } })
@dgraham that’s not correct. Fetch seems to reject the promise on a 401. So you don’t have access to the response object
kelabang reacted with thumbs down emoji
@vdclouis I’ve just tested in Chrome 45 latest stable, and it does resolve the promise on 401. So the behavior you’re seeing in Chrome 47 prerelease with rejecting the promise might be a regression and I bet the Chromium dev team would like to know about that.
@vdclouis Actually if I try to replicate your experience on Chrome Canary 47, I still can’t. It behaves as expected. I added the /authfail
endpoint and this test:
test('resolves promise on 401 error', function() { return fetch('/authfail').then(function(response) { assert.equal(response.status, 401) assert.equal(response.ok, false) return response.text() }).then(function(body) { assert.equal(body, 'you need to auth') }) })
but it passes.
Hmm, maybe because I’m sending credentials and thus does a Options call first?
Is it a cross-site request?
The promise is supposed to be rejected if CORS doesn’t allow it. I just tested with Chrome 45 and Chrome 47 and the promise is rejected by default when «No ‘Access-Control-Allow-Origin’ header is present on the requested resource.»
However if I add the Access-Control-Allow-Origin: *
header to the 401 response from the other server, the 401 response is received just fine (promise is resolved) and its HTTP status is readable and correct.
Hmm, If this is a server setting I’m afraid I’m stuck…
gonzalad
added a commit
to gonzalad/iam-malta-2016
that referenced
this issue
Sep 29, 2016
Cors headers were not set when there was no security context (401) or authorizatin issue (403). This was a pb because Chrome didn't call fetch.then(xxx), but instead fetch.catch(xxx) and we didn't have access to statusCode in catch. See : * spring-projects/spring-boot#5834 * JakeChampion/fetch#201
@vdclouis Hey Louis, was you able to find a way to detect 401 code for rejected by CORS request?
I’m stuck with same problem, I need to catch 503 status code
@NeXTs any news? Could you get it to work?
I had to get the latest systemjs src and all was well. SystemJS v0.19.47 did the trick for me.
For anyone who will have this issue in the future
Fetch API fails only if it can’t make a request. And if it can, fetch
will be executed successfully even if it has a bad status. For example:
fetch('http://google.com') .then(response => { // response from server // here you can check status of response and handle it manually switch (response.status) { case 500: console.error('Some server error'); break; case 401: console.error('Unauthorized'); break; // ... } // or you can check if status in the range 200 to 299 if (response.ok) { return response; } else { // push error further for the next `catch`, like return Promise.reject(response); // or another way throw Error(response.statusText); } }) .catch(error => { // here you will get only Fetch API errors and those you threw or rejected above // in most cases Fetch API error will look like common Error object // { // name: "TypeError", // message: "Failed to fetch", // stack: ... // } });
And here are some (not all) of the errors from Fetch API:
- misspelled
url
likefetch('https::://hey.com')
–TypeError Failed to execute 'fetch' on 'Window': Failed to parse URL from https::://hey.com
; - nonexistent
url
likefetch('http://hey')
–TypeError: Failed to fetch (GET http://hey/ net::ERR_NAME_NOT_RESOLVED)
; - you don’t have an internet connection
fetch('https://google.com')
–TypeError: Failed to fetch (GET https://google.com/ net::ERR_NAME_RESOLUTION_FAILED)
- because of the Content Security Policy
fetch('https://google.com')
–TypeError: Failed to fetch (Refused to connect to 'https://google.com/' because it violates the following Content Security Policy directive: "connect-src 'self'...)
- because of the CORS
fetch('https://google.com')
–TypeError: Failed to fetch (Fetch API cannot load https://google.com/ has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource....)
The last two cases you can fix by adding (or editing) the appropriate headers on the server, if you have an access.
blackandcode, brandonhall, amalv, monish001, guzishiwo, gallaoro, and mayank23 reacted with hooray emoji
nickvoronin, eranimo, rokr97, riquito, sevenLee, MelisaIm, tom—, IkeLutra, blackandcode, 20hertz, and 13 more reacted with heart emoji
abby-ng
pushed a commit
to dsaidgovsg/lswagger-ui
that referenced
this issue
Jul 12, 2017
Is there a way to get those additional error messages to determine which error is occurring? For example (in Chrome 67), I’m running the following code:
fetch('https://fail').then(function(response){ console.log('Fetch was successful', response); }).catch(function(event){ console.log('Fetch failed', event); });
Which fails, but the only message in the console is TypeError: Failed to fetch
. This example is obvious what the problem is, but when I have an actual URL in the fetch that resolves via a standard request, but fails using fetch()
I cannot figure out what the specific problem is.
Edit: Thanks for the info below- in my situation error.response
is undefined
so it must be a network error like you described.
@chrisblakley You can inspect event.response
(your event
argument is actually an Error instance) in the catch
handler to access response.statusText
and other information about a failed HTTP response.
If there is no error.response
, then the fetch failed with what is usually a network error, and browsers don’t typically give us much information about those. See #562 (comment) for more context
This comment has been minimized.
going off that, i know it is not a network error 😂 but i also know my api server is running properly and there are no auth problems, because i checked Okta
@mislav got the core of the problem here I believe. Fetch response promise is not rejected because of 401 status code but because 401 responses don’t have the proper CORS headers.
In my case (Laravel), I had to add them manually on 401 error responses:
// app/Exceptions/Handler.php protected function prepareJsonResponse($request, AuthenticationException $e) { // ... $response = response()->json($data, $statusCode); $cors = app(Barryvdh\Cors\Stack\CorsService::class); if ($cors->isCorsRequest($request)) { $response = $cors->addActualRequestHeaders($response, $request); } return $response; }
either way, this spec desperately needs to be fixed
I’d say it works as expected, there is nothing to be fixed.
Repository owner
locked as resolved and limited conversation to collaborators
Nov 20, 2018
Hello everyone,
I am trying to pass access token to an API that returns data through fetch
from DATA_API but I am getting 401 unauthorized error
.
When I opened Network
Tab, I observed that the auth headers did not injected
and hence the 401 error is coming. The token is also getting fetched from ACCESS_TOKEN_API and its getting logged in the console.
Here is my code. Please suggest a workaround.
import React, { useState, useEffect } from "react";
import {Col } from 'antd';
import { Link } from "react-router-dom";
import AntDTable from '../shared/AntDTable';
import iInnerLoader from '../shared/iInnerLoader';
const columns = [
{
title: 'Account Name',
dataIndex: 'name',
render: (text, record) => (
<Link to={`/all-customers/tenants/?tenant_id=${record.id}&customer=${record.name}`}>{record.name.toUpperCase()}</Link>
),
},
{
title: 'Total Tenants',
dataIndex: 'tenantCount',
}
];
const useFetch = (url, headers) => {
const [data, setData] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(async () => {
const response = await fetch(url,headers)
const data = await response.json()
// console.log(data)
setData(data)
setLoading(false)
},[]);
return {data, loading};
}
export default function CreateTestcaseStep2() {
const [token, setToken] = useState([]);
useEffect(async () => {
const response = await fetch('ACCESS_TOKEN_API',{
method : 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/x-www-form-urlencoded'
},
body : 'body_part'
})
const data = await response.json()
// console.log(data)
setToken(data)
},[]);
console.log("token is ", token.access_token) // TOKEN IS GETTING PRINTED HERE
var api_headers={ method: 'GET',
headers: {'Authorization': `Bearer ${token.access_token}`,
"Access-Control-Allow-Origin" : "*",
"Access-Control-Allow-Credentials" : true },
}
console.log("headers ", api_headers)
const {data, loading} = useFetch('DATA_API', api_headers)
return (
<>
<Col md={24} sm={24} className="p-0">
<div className="customer-list">
<div className="customer-list-header">
Customer Accounts
</div>
<br/>
<div className="customer-list-content">
{loading? <iInnerLoader isDisplayLabel={true} label={"Loading Customers"} /> :
<AntDTable columns={columns} data={data.data} pagination={true} height={390}/>}
</div>
</div>
</Col>
</>
);
}
Enter fullscreen mode
Exit fullscreen mode
I am trying to prevent the need for deploying the code to the live domain and instead test the response on localhost. However, I am uncertain if this is feasible due to CORS. The absence of CORS headers from the response causes this issue.
Table of contents
- How do I resolve a cors error on a fetch or 401?
- Resolved fetch throws console error 401
- Getting 401 Error code while using fetch() with a custom header
- Does fetch throw a 404 error?
- What is the catch clause in a 401 request?
- What is the use of fetch()?
- How many network errors does fetch detect?
How do I resolve a cors error on a fetch or 401?
Question:
I have encountered
CORS error
and 401 errors. Despite using chrome plugins to enable cors, the issues persist. Upon disabling cors through the plugin, the resulting errors are as follows:
Access to fetch at 'https://api.playground.klarna.com/payments/v1/sessions' from origin 'https://localhost' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: It does not have HTTP ok status.
Failed to load resource: net::ERR_FAILED
Error: TypeError: Failed to fetch
Prior to activating the
CORS Chrome
Extension, I encountered an error message stating that Allow-Access-Control-Origin was not set on the first request. Additionally, on the network tab, a 401 Preflight error was displayed, indicating that I was unauthorized. Despite setting the correct credentials in
Authorization header
, I remain uncertain about the cause of the issue. My code is written using the php framework CodeIgniter.
I’m using Basic auth with:
var auth = 'Basic ' + btoa(username:password);
Here’s the code:
let postDataSession = {
"purchase_country" : bookingData.purchase_country,
"purchase_currency" : bookingData.purchase_currency,
"locale" : bookingData.locale,
"order_amount" : bookingData.order_amount,
"order_tax_amount" : 0,
"order_lines" : [{
//"type" : "physical",
"reference" : bookingData.order_lines.reference,
"name" : bookingData.item_name,
"quantity" : 1,
"unit_price" : bookingData.order_amount,
"tax_rate" : 0,
"total_amount" : bookingData.order_amount,
"total_discount_amount": 0,
"total_tax_amount" : 0
}]
};
fetch('https://api.playground.klarna.com/payments/v1/sessions', {
method: 'POST',
//mode: 'no-cors',
//Authorization: auth,
headers: {
'Content-Type': 'application/json',
'Authorization': auth,
//'Access-Control-Allow-Credentials' : true,
'Access-Control-Allow-Headers' : 'pm-u, pm-h0, pm-h1, pm-h3, pm-o0, pm-o1, pm-o2, pm-o3, authorization',
'Access-Control-Allow-Methods': 'POST',
'Access-Control-Allow-Origin': 'https://localhost',
'ACCESS-CONTROL-MAX-AGE' : 3600,
'referrer-policy': 'no-referrer-when-downgrade'
},
body: JSON.stringify(postDataSession),
})
.then(function(response) {
//The following method initializes the Klarna Payments JS library
//window.location.href = baseurl + "customer/klarna_checkout_page";
if (!response.ok) {
return response.text().then(result => Promise.reject(new Error(result)));
console.log(response.status);
}
console.log(response.json(), response);
return response.json();
})
// .then(function(session) {
// window.location.href = baseurl + "customer/klarna_checkout_page";
// })
.then(function(result) {
// If `redirectToCheckout` fails due to a browser or network
// error, you should display the localized error message to your
// customer using `error.message`.
if (result.error) {
alert(result.error.message);
}
console.log(result);
})
.catch(function(error) {
console.error('Error:', error);
});
Having attempted the no-cors mode, I encountered an identical response. Using postman resulted in a response being received. I am unsure if I am overlooking something and would appreciate a fresh perspective. Does anyone have suggestions on how to proceed with resolving this issue? I hope to avoid deploying the code to the live domain and instead test the response on localhost. However, I am unsure if this is feasible with cors.
Solution 1:
- Browser extensions are known to be ineffective in handling preflighted requests, and they will not be of any assistance in this case.
- The browser will not throw an exception in no-cors mode when CORS permission is required, but will silently fail instead. This mode is not useful in this case.
- Postman operates differently from a typical browser as it does not rely on website visits to initiate its requests. Moreover, it does not adhere to the Same Origin Policy and does not require CORS permission.
I’m receiving a 401 Preflight error that suggests lack of authorization. However, I’m supplying the Authorization header with the accurate credentials. Therefore, I’m uncertain about what is causing this issue.
The preflight request sent by the browser seeks permission to send a POST request along with credentials.
The preflight request received by the server lacks credentials, causing it to raise an error.
Either:
- To obtain permission in your development environment, switch to a server that permits OPTIONS requests without credentials.
- Employ a relay proxy to transmit your requests to the server.
Solution 2:
Have you implemented backend .net core web services? If yes, I have encountered a similar issue when UseCors is called after
useauthentication
in the pipeline. This results in a CORS error being thrown due to the need for an authenticated token to perform the preflight. To avoid this, move UseCors before UseAuthentication to prevent the CORS response from going through the Authentication middleware initially.
Javascript — 400 ( bad request ) using fetch to login, Hmm.. I would probably start putting some console.log() statements out the node terminal of req..See if you can also use info and user argument to see what happened authenticate function. Probably there is no exception which err carries but just something else might be invalid or valid. It will be good to check if …
Resolved fetch throws console error 401
Question:
Although
fetch
was resolved using
401 Unauthorized
, the console error logs still persist.
componentWillMount() {
this.setState({ isInitializing: true });
fetch('/api/users/getcurrent')
.then(resp => {
console.log('resolved');
if (resp.status == 200) {
// do stuff
}
this.setState({ isInitializing: false });
})
.catch(err => {
console.log('catched');
this.setState({ isInitializing: false });
});
}
Does the fetch function have a default behavior of throwing an error upon receiving a 401 response? I couldn’t find any information related to this on MDN or other sources. The console log indicates that an error did occur. It’s worth noting that I am not utilizing any external packages or polyfills for the
fetch
code. My current browser version is
63.0.3239.108
on Chrome.
Solution 1:
The process of fetching is not related to this. By default, the Chrome Dev tools record HTTP errors (status codes 4xx and 5xx) in the console, which is explained in the Additional Settings section. Therefore, even if the fetch promise is fulfilled, the browser log may still show up, but can be disabled.
Solution 2:
The server responded correctly, indicating that Fetch is functioning properly. However, this endpoint requires authorization and returned a response with status code
401
.
The fetch() Promise will not reject due to HTTP error status, such as 404 or 500. It will resolve as usual, with the ok status marked as false. However, it will only reject if there is a network failure or if something obstructed the request from finishing.
The Fetch API usage guide can be found on the Mozilla Developer Network website, while details on the 401 HTTP status code can also be found on the same website.
Solution 3:
Kindly specify the header in your code server.
res.header('Access-Control-Allow-Origin','*');
res.header('Access-Control-Allow-Headers', 'Authorization, X-API-KEY, Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Request-Method');
res.header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, DELETE');
res.header('Allow', 'GET, POST, OPTIONS, PUT, DELETE');
Solution 4:
The absence of CORS headers from the response causes this issue. To resolve it, I added the following and achieved the expected outcome.
@Component
public class CORSHeadersToUnauthorizedResponseFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
FilterChain filterChain) throws IOException, ServletException {
filterChain.doFilter(httpServletRequest, httpServletResponse);
if(httpServletResponse.getStatus() == HttpStatus.UNAUTHORIZED.value() ) {
httpServletResponse.addHeader("Access-Control-Allow-Credentials", "true");
httpServletResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("origin"));
}
}
}
Javascript — React axios 401 unauthorized, I get a 401 error, when trying to authenticate a user. Just to give context, React is using an Express server, and using Passport for authentication. React has a port of 8001, and the Express server has the port of 8000. GET /api/users/user 401 2.167 ms — 59. Other get requests Do work. For example. React
Question:
===
Using
AWS API Gateway
, I created a personalized API that includes a method with authorization checks performed by a Lambda function. To enable this feature, I had to include the key,
Key: authorizationToken Value: allow
.
After using Postman to test it, I can confirm that the POST is functioning properly and producing a response.
As a beginner in Javascript, I utilized the code that was provided in Postman to get started. See below for the code snippet.
function getData(event){
var myHeaders = new Headers();
myHeaders.set("authorizationToken", "allow");
var requestOptions = {
method: 'POST',
mode: 'no-cors'
};
fetch("https://[THE_URL_OF_MY_API]/prod/counter", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
}
I’m encountering an error message in the console.
script.js:49 POST https://[THE_URL_OF_MY_API]/prod/counter
net::ERR_ABORTED 401 (Unauthorized)
getData @ script.js:49
To diagnose the issue, I examined the records of AWS’s API Gateway.
- It appears that my fetch is being blocked before it is sent as I am unable to locate any logs.
- Upon inspecting the headers of the API call that was successful via Postman, I observed that there were no headers present apart from the ones that were generated automatically by the application and the ones that belonged to me.
What am I doing wrong ?
I suspect my header is incorrectly set as I am using comparable code for another endpoint that operates without authorization and is successful.
Thanks !
Solution:
I would like to express my gratitude to CRice, Salmin Skenderovic, and Jaromanda X for their valuable feedback.
After realizing that the absence of myHeaders was due to a typographical error, I promptly rectified the mistake. Following a suggestion in the comments regarding ‘no-cors’, I investigated the matter and proceeded to enable CORS. Additionally, I granted authorization for my particular header in Access-Control-Allow-Headers.
And now it’s working fine.
My amended code:
var myHeaders = new Headers();
myHeaders.set("authorizationToken", "allow");
var requestOptions = {
method: 'POST',
redirect: 'follow',
headers : myHeaders
};
fetch("https://[URL_OF_MY_API_ENDPOINT]/prod/counter", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));
The setup of my API Gateway.
Javascript — I am facing an error net::ERR_ABORTED 401, Fetch in ReactJS with Basic Auth return 401 (Unauthorized). Preflight request doesn’t pass access control check Preflight …
Read other technology post:
Spring Security SAML