mirror of
https://github.com/puppeteer/puppeteer
synced 2024-06-14 14:02:48 +00:00
[api] Implement page.authenticate method (#729)
This patch implements `page.authenticate` which should cover all cases of HTTP authentication. Fixes #426.
This commit is contained in:
@@ -73,6 +73,8 @@ class SimpleServer {
|
||||
|
||||
/** @type {!Map<string, function(!IncomingMessage, !ServerResponse)>} */
|
||||
this._routes = new Map();
|
||||
/** @type {!Map<string, !{username:string, password:string}>} */
|
||||
this._auths = new Map();
|
||||
/** @type {!Map<string, !Promise>} */
|
||||
this._requestSubscribers = new Map();
|
||||
}
|
||||
@@ -88,6 +90,15 @@ class SimpleServer {
|
||||
socket.once('close', () => this._sockets.delete(socket));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} path
|
||||
* @param {string} username
|
||||
* @param {string} password
|
||||
*/
|
||||
setAuth(path, username, password) {
|
||||
this._auths.set(path, {username, password});
|
||||
}
|
||||
|
||||
async stop() {
|
||||
this.reset();
|
||||
for (const socket of this._sockets)
|
||||
@@ -136,6 +147,7 @@ class SimpleServer {
|
||||
|
||||
reset() {
|
||||
this._routes.clear();
|
||||
this._auths.clear();
|
||||
const error = new Error('Static Server has been reset');
|
||||
for (const subscriber of this._requestSubscribers.values())
|
||||
subscriber[rejectSymbol].call(null, error);
|
||||
@@ -150,6 +162,15 @@ class SimpleServer {
|
||||
throw error;
|
||||
});
|
||||
const pathName = url.parse(request.url).path;
|
||||
if (this._auths.has(pathName)) {
|
||||
const auth = this._auths.get(pathName);
|
||||
const credentials = new Buffer((request.headers.authorization || '').split(' ')[1] || '', 'base64').toString();
|
||||
if (credentials !== `${auth.username}:${auth.password}`) {
|
||||
response.writeHead(401, { 'WWW-Authenticate': 'Basic realm="Secure Area"' });
|
||||
response.end('HTTP Error 401 Unauthorized: Access is denied');
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Notify request subscriber.
|
||||
if (this._requestSubscribers.has(pathName))
|
||||
this._requestSubscribers.get(pathName)[fulfillSymbol].call(null, request);
|
||||
|
||||
37
test/test.js
37
test/test.js
@@ -1570,6 +1570,43 @@ describe('Page', function() {
|
||||
expect(request.headers['foo']).toBe('bar');
|
||||
}));
|
||||
});
|
||||
describe('Page.authenticate', function() {
|
||||
it('should work', SX(async function() {
|
||||
server.setAuth('/empty.html', 'user', 'pass');
|
||||
let response = await page.goto(EMPTY_PAGE);
|
||||
expect(response.status).toBe(401);
|
||||
await page.authenticate({
|
||||
username: 'user',
|
||||
password: 'pass'
|
||||
});
|
||||
response = await page.reload();
|
||||
expect(response.status).toBe(200);
|
||||
}));
|
||||
it('should fail if wrong credentials', SX(async function() {
|
||||
// Use unique user/password since Chrome caches credentials per origin.
|
||||
server.setAuth('/empty.html', 'user2', 'pass2');
|
||||
await page.authenticate({
|
||||
username: 'foo',
|
||||
password: 'bar'
|
||||
});
|
||||
const response = await page.goto(EMPTY_PAGE);
|
||||
expect(response.status).toBe(401);
|
||||
}));
|
||||
it('should allow disable authentication', SX(async function() {
|
||||
// Use unique user/password since Chrome caches credentials per origin.
|
||||
server.setAuth('/empty.html', 'user3', 'pass3');
|
||||
await page.authenticate({
|
||||
username: 'user3',
|
||||
password: 'pass3'
|
||||
});
|
||||
let response = await page.goto(EMPTY_PAGE);
|
||||
expect(response.status).toBe(200);
|
||||
await page.authenticate(null);
|
||||
// Navigate to a different origin to bust Chrome's credential caching.
|
||||
response = await page.goto(CROSS_PROCESS_PREFIX + '/empty.html');
|
||||
expect(response.status).toBe(401);
|
||||
}));
|
||||
});
|
||||
describe('Page.setContent', function() {
|
||||
const expectedOutput = '<html><head></head><body><div>hello</div></body></html>';
|
||||
it('should work', SX(async function() {
|
||||
|
||||
Reference in New Issue
Block a user