17

If we do window.location = "http://MyApi.com/Pdf";, browser does a GET of the URL http://MyApi.com/Pdf. But if we want to set authentication header of the request before doing GET of the URL because the server is a REST server and it doesn't support cookies. How to do this?

In all of the cases, I'm using $.ajax to call service but this time I need to show the response in a new window. Response is a PDF file content.

Thanks in advance.

6 Answers 6

11

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');
});
Sign up to request clarification or add additional context in comments.

2 Comments

Yes, with Chrome 48 -> Node 0.12 Mark it up? :)
supported by major latest browsers. But still in draft. developer.mozilla.org/en/docs/Web/API/URL/…
2

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

1 Comment

Link broken, use web.archive.org/web/20191021004044/https://… instead. However some of the information here is probably outdated anyway...
1

If you don't care about hiding or obfuscating the user credentials then just use plain GET authentification: use http://username:[email protected]/ instead of http://MyApi.com/

1 Comment

Thanks v much for replying. I have a custom authentication mechanism. :(. So the value of authorization header looks something like CompanyNameToken <hashOfToken>. I wouldn't mind including the token in the URL if there is some quirk possible like this one.
1

Does it have to be a GET?

The reason I am asking is that you could just have a POST form (to a target="_BLANK") that posts whatever but shows an embedded file in a new window. Of course this wouldn't solve the issue with your custom headers, but then since you can also POST using jquery.ajax - which does allow you to set your own headers - you'd have the best of both worlds.

Here's a jQuery plugin that creates such a form dynamically in order to download whichever file. You could use this as a reference...

Hope this helps

Comments

0

You may consider setting the header in beforeunload or onunload event handler

1 Comment

Please provide some working code example to support your answer?
-2

You should configure $.ajax using beforeSend. Below an example, but of course I don't know if the exact setup will work for you without any code to look at.

$.ajax( {
    url : '/model/user.json',
    dataType : 'json',
    'beforeSend' : function(xhr) {
            var bytes = Crypto.charenc.Binary.stringToBytes(username + ":" + password);
            var base64 = Crypto.util.bytesToBase64(bytes);
            xhr.setRequestHeader("Authorization", "Basic " + base64);
    },
    error : function(xhr, ajaxOptions, thrownError) {
        reset();
        onError('Invalid username or password. Please try again.');
        $('#loginform #user_login').focus();
    },
    success : function(model) {
        cookies();
            ...
    }
});

For this to work you need crypto-js.

2 Comments

Doesn't quite answer the question I believe, the response is a PDF document to be rendered by the browser.
Let me clarify again. I don't need to set header for ajax request. I want to set header for full GET request of the page. I'm already using the beforeSend to set the header for all ajax request.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.