Can I control the HTTP headers sent by window.open (cross browser)?
No
If not, can I somehow window.open a page that then issues my request with custom headers inside its popped-up window?
- You can request a URL that triggers a server side program which makes the request with arbitrary headers and then returns the response
- You can run JavaScript (probably saying goodbye to Progressive Enhancement) that uses XHR to make the request with arbitrary headers (assuming the URL fits within the Same Origin Policy) and then process the result in JS.
I need some cunning hacks...
It might help if you described the problem instead of asking if possible solutions would work.
Answer from Quentin on Stack OverflowCan I control the HTTP headers sent by window.open (cross browser)?
No
If not, can I somehow window.open a page that then issues my request with custom headers inside its popped-up window?
- You can request a URL that triggers a server side program which makes the request with arbitrary headers and then returns the response
- You can run JavaScript (probably saying goodbye to Progressive Enhancement) that uses XHR to make the request with arbitrary headers (assuming the URL fits within the Same Origin Policy) and then process the result in JS.
I need some cunning hacks...
It might help if you described the problem instead of asking if possible solutions would work.
Sadly you can't control headers when doing window.open()
Nice and easy, how I managed to open a file with custom headers:
const viewFile = async (url) => {
// Change this to use your HTTP client
fetch(url, {/*YOUR CUSTOM HEADER*/} ) // FETCH BLOB FROM IT
.then((response) => response.blob())
.then((blob) => { // RETRIEVE THE BLOB AND CREATE LOCAL URL
var _url = window.URL.createObjectURL(blob);
window.open(_url, "_blank").focus(); // window.open + focus
}).catch((err) => {
console.log(err);
});
};
- Download file to cache
- window.open to cache
Add support to the window.open function for the Accept header.
How to open a link in new window with a header? - CSS-Tricks
angularjs - how to add authentication header to $window.open - Stack Overflow
angularjs - is that possible to send header information in $window.open(url) method - Stack Overflow
Videos
I think I should update this old question with a correct and secure answer.
You can not add any headers in the HTTP GET request performed by window.open.
The secure way to make an authenticated request is to set the authentication token into a request header, and avoid exposing it into the URL, as my previous answer suggested (I have learned a some things since then).
To download a PDF (or any other binary data) from an authenticated server with AngularJS you should:
- Make an HTTP GET request to the resource sending the authentication token in a header, setting its responseType to a binary data type, for example blob or arraybuffer.
- Download the binary data in a file using the "Save As" dialog from the browser, usually creating a download link for the binary data and clicking it.
I hope this answer to clear doubts on this question and provides a secure way to download a resource from an authenticated REST API.
I think you can add this authentication parameters in URL and do a GET in your server side
//Add authentication headers as params
var params = {
access_token: 'An access_token',
other_header: 'other_header'
};
//Add authentication headers in URL
var url = [url_generating_pdf, $.param(params)].join('?');
//Open window
window.open(url);
No - It is not possible to send headers in straight way using $window.open
Yes - Its is possible but not straight way, If you've got server-side control then you can set header value in query string and get it parsed from query string on the back-end.
I don't suggest to pass params with window.open.
BUT you can use window.open like this.
var params = {
access_token: 'An access_token',
other_header: 'other_header'
};
//Add authentication headers in URL
var url = [url_generating_pdf, $.param(params)].join('?');
//Open window
window.open(url);
Please check the details info here
In more recent browsers, you might be able to use blobs:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<button onclick="tryit();">PDF</button>
<script>
function tryit() {
var win = window.open('_blank');
downloadFile('/pdf', function(blob) {
var url = URL.createObjectURL(blob);
win.location = url;
});
}
function downloadFile(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader("Authorization", "Basic " + btoa("username:password"));
xhr.responseType = "blob";
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (success) success(xhr.response);
}
};
xhr.send(null);
}
</script>
</body>
</html>
In IE, ask the user:
window.navigator.msSaveOrOpenBlob(blob, 'readme.pdf');
P.S. You can test the backend in Node:
router.get('/pdf', function(req, res) {
if(req.headers.authorization !== 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=') return res.status(403).send('Not allowed');
res.sendFile(path.join(__dirname, 'public', 'render.pdf'));
});
router.get('/', function(req, res) {
res.render('index');
});
I think this is what you are looking for... Or correct me if i am wrong.
https://developer.mozilla.org/en/docs/Setting_HTTP_request_headers
