API call when tab closing angular 5 - angular5

I'm working on angular 5 project. So that I want to call API when closing tab. How can use "beforeunload" or any Technic to this.

'beforeunload' would be trigger when refreshing pages, closing tab, or closing the browser.
#HostListener('window:beforeunload', ['$event'])
beforeUnload(e: Event) {
e.returnValue = false;
}
You can set 'e.returnValue = false;' or 'return false;' to show a confirm dialogue from browser. But You can not show the customized message by return string since April 2016.
refer to https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en#remove_custom_messages_in_onbeforeunload_dialogs
You can set 'navigator.sendBeacon()' in beforeunload event to send a POST API.
However 'navigator.sendBeacon()' can only POST API, and it can't set customized header like token. (refer to Navigator.sendBeacon() to pass header information)
Some document recommend using fetch with attribute 'keepalive':
const token = localStorage.getItem('token');
fetch(url, {
headers: {
'content-type': 'application/json',
'authorization': token
},
method: 'POST',
body: JSON.stringify(data),
credentials: 'include',
mode: 'no-cors',
keepalive: true,
})
But keepalive is not working now in chrome M78, which is reported but not fixed.(refer to https://bugs.chromium.org/p/chromium/issues/detail?id=835821)

Related

VueJS - Localhost API requests not working on Android Chromium

I am running a vue-project on Chromium 72 on Android v4.4.4 and an API is also running on localhost:8225.
So with the click of a button, I am making a post request using Axios to this localhost API in the project.
var axiosConfig = {
method: "post",
url: "http://localhost:8225/info/update",
data: {},
timeout: 3000,
contentType: "application/json",
headers: {
Authorization: "Basic " + btoa(apiUser + ":" + apiPassword),
},
};
return new Promise(function (resolve, reject) {
axios(axiosConfig)
.then(function (response) {
var result = response;
resolve(result);
console.log("Response", response);
})
.catch(function (error) {
console.log("Error", error);
reject(error);
});
});
But the problem is when I click the button it doesn't hit the API method. It gives Error: timeout of 3000ms exceeded and when I removed the timeout and checked the network tab the request remains in a pending state.
I don't think there is a structural error in the code because the same request works from another application running on the device. When the button is clicked the information gets updated.
Also, I tried all the chromium version till v80 same issue exists. So is there any setting that needs to be changed or enabled on Chromium to handle API requests?
UPDATE:
The API gets hit but when I checked the value of the User(username and password) on HttpListenerContext object, it shows null. I have cross-checked multiple times and I believe the request structure is correct. I am not sure if Chromium is putting some restrictions while sending the requests or the problem is with the backend like CORS issue or maybe something else.

Why does the browser ask me to log in with ASP.NET Core 3.1

I've created a website in ASP.NET Core 3.1, MVC, with API. There are 2 parts to the website. An classic static website (with a home, about, contact page etc) and a SPA app. You need to login to use the SPA application.
I believe my approach to auth is quite 'standard'. (There are no different permissions or roles).
The user logs in, and an HTTP Only cookie is created. They are redirected to the Web API part of the website
Any API calls to the C# Web Api, and the front end reviews the return status code (such as code 200 or 500 etc).
If the return is 401, it will assume the JWT has expired or has never been created. The front end then makes another call to the Web Api to retrieve a new Json Web Token. If the JWT is returned, the program attempts the original request again, with the valid JWT. Otherwise, it deals with the situation by alerting the user about the issue
The ajax code looks like
function toDatabase(type, url, data, successDelegate, failDelegate, errorDelegate, tryAgainIfUnathorized) {
$.ajax({
type: type.toUpperCase(),
url: url,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + bearerToken.get()
},
data: data,
dataType: "json",
success: function (response) {
successDelegate(response);
},
error: function (e) {
if (e.status === 401 && tryAgainIfUnathorized) {
const callback = function () {
toDatabase(type, url, data, successDelegate, failDelegate, errorDelegate, false, false);
};
bearerToken.refresh(callback);//try to get the updated token, then retry the original request
}
else {
if (e.status !== 200)
errorDelegate(e.statusText);
console.log("Error in ajaxCall.js. Expand for call stack:");
console.log(e);
}
}
});
This works fine on my local computer.
The problem is, seemingly randomly and not that often, on my production site, Google Chrome occasionally presents a log in dialog. My code does not create this dialog. I don't even know the javascript to create it :)
I don't understand. If I click cancel, then I can continue as I'd like (meaning I am authenticated).
I read up, and it seems that this happens because the browser detects the 401 and tries to be helpful!
I've tried to get round this issue by returning a 499 instead of a 401 but that caused even more headaches with this code
jwtBearerOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = context =>
{
context.Response.OnStarting(() =>
{
context.Response.StatusCode = 499;
return Task.CompletedTask;
});
return Task.CompletedTask;
}
};
How do I prevent this dialog from showing (or is my approach to using JWT incorrect)

Loading Data from Behance API in React Component

I am trying to load Behance project data via their API. Whether its localhost or prod, I am getting the following error --
Fetch API cannot load XXX. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:5000' is therefore not allowed access. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
Not sure how to solve for this.
My code in the Portfolio component below --
getPortfolio = () => {
const USER_ID = `XXX`,
PROJECT_ID = `XXX`,
API_KEY = `XXX`;
const BEHANCE_URL = `https://api.behance.net/v2/users/${USER_ID}/projects?client_id=${API_KEY}`;
console.log(BEHANCE_URL);
fetch(BEHANCE_URL, {
method: 'get',
dataType: 'jsonp',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
}
}).then((response) => {
return response.json();
}).then((responseData) => {
return responseData;
}).catch((err) => {
return err;
});
}
UPDATE: Instead of fetch, using jQuery ajax works. --
$.ajax({
url: BEHANCE_URL,
type: "get",
data: {projects: {}},
dataType: "jsonp"
}).done((response) => {
this.setState({
portfolioData: response['projects']
});
}).fail((error) => {
console.log("Ajax request fails")
console.log(error);
});
This seems to have do less with React and more with Behance. What you are getting is a CORS error as you probably figured out. The short explanation is that CORS is a security measure put in on the browser so that websites cannot request other websites from the browser to appear to be the second website. It is a safety measure in place to protect from some phishing attacks.
CORS can be disabled by the server (in this case, Behance) but they decide not to, for legitimate reasons.
Behance would probably allow you to make the request you are trying to make from a server instead. Once you do that, you will need to get the information from your server to your React application, and you will be good to go!

Testing external API's using Angular 2 & Apache

I am trying to make an HTTP requeset to an external API using the following request:
let headers = new Headers({
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': 'application/x-www-form-urlencoded',
'Access-Control-Allow-Origin': "*"
});
let options = new RequestOptions({ headers: headers });
let body = JSON.stringify({
test: test
comments: "test"
});
this.http.post("EXTERNAL_API_URL", body, options)
.map(res => res.json())
.subscribe((data) => {
console.log(data);
});
When I am making the API call from Chrome Postman plugin, the API works without any problem.
When I'm trying to make this call from my angular 2 app, the call is not working and returns the following error:
XMLHttpRequest cannot load MY_API_URL. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.
I know that I can access bypass it using the no web-security chrome:
Chrome.exe --disable-web-security
But I wish to make it work without it...
I also tried to add Header set Access-Control-Allow-Origin "*" in my http.conf as described here.
Any ideas?

CORS with Sencha Touch 2

I'm developing an application which need CORS, I did some google but could not understand that. My application is running on localhost:8000 while I'm making a ajax request to localhost:9090. Below is my Ajax request code...
Ext.Ajax.request({
url : 'http://localhost:9090/by-api',
method: 'POST',
jsonData : api_no,
disableCaching: false,
withCredentials: true,
useDefaultXhrHeader: false,
headers: {
"Content-Type":"text/plain",
'Access-Control-Allow-Orgin':'*',
'Access-Control-Headers': 'x-requested-with'
},
success: function(response){
console.log(response.responseText)
},
failure: function(response){
console.log(response.responseText)
}
});
Also I want to do a Basic Authentication so I tried putting 'Authentication' in headers but nothing is working..
The directive
'Access-Control-Allow-Orgin':'*'
must be included server side in the response header, not in the client request.
Follow this document to reference W3-CORS