Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


SSL network.spec.ts   Sprache: unbekannt

 
/**
 * @license
 * Copyright 2018 Google Inc.
 * SPDX-License-Identifier: Apache-2.0
 */

import fs from 'fs';
import type {ServerResponse} from 'http';
import path from 'path';

import expect from 'expect';
import type {HTTPRequest} from 'puppeteer-core/internal/api/HTTPRequest.js';
import type {HTTPResponse} from 'puppeteer-core/internal/api/HTTPResponse.js';

import {getTestState, launch, setupTestBrowserHooks} from './mocha-utils.js';
import {attachFrame, isFavicon, waitEvent} from './utils.js';

describe('network', function () {
  setupTestBrowserHooks();

  describe('Page.Events.Request', function () {
    it('should fire for navigation requests', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(requests).toHaveLength(1);
    });
    it('should fire for iframes', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      await attachFrame(page, 'frame1', server.EMPTY_PAGE);
      expect(requests).toHaveLength(2);
    });
    it('should fire for fetches', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      await page.evaluate(() => {
        return fetch('/empty.html');
      });
      expect(requests).toHaveLength(2);
    });
  });
  describe('Request.frame', function () {
    it('should work for main frame navigation request', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(requests).toHaveLength(1);
      expect(requests[0]!.frame()).toBe(page.mainFrame());
    });
    it('should work for subframe navigation request', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.EMPTY_PAGE);
      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await attachFrame(page, 'frame1', server.EMPTY_PAGE);
      expect(requests).toHaveLength(1);
      expect(requests[0]!.frame()).toBe(page.frames()[1]);
    });
    it('should work for fetch requests', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.EMPTY_PAGE);
      let requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.evaluate(() => {
        return fetch('/digits/1.png');
      });
      requests = requests.filter(request => {
        return !request.url().includes('favicon');
      });
      expect(requests).toHaveLength(1);
      expect(requests[0]!.frame()).toBe(page.mainFrame());
    });
  });

  describe('Request.headers', function () {
    it('should define Browser in user agent header', async () => {
      const {page, server, isChrome} = await getTestState();
      const response = (await page.goto(server.EMPTY_PAGE))!;
      const userAgent = response.request().headers()['user-agent'];

      if (isChrome) {
        expect(userAgent).toContain('Chrome');
      } else {
        expect(userAgent).toContain('Firefox');
      }
    });
  });

  describe('Response.headers', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      server.setRoute('/empty.html', (_req, res) => {
        res.setHeader('foo', 'bar');
        res.end();
      });
      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.headers()['foo']).toBe('bar');
    });
  });

  describe('Request.initiator', () => {
    it('should return the initiator', async () => {
      const {page, server} = await getTestState();

      const initiators = new Map();
      page.on('request', request => {
        return initiators.set(
          request.url().split('/').pop(),
          request.initiator(),
        );
      });
      await page.goto(server.PREFIX + '/initiator.html');

      expect(initiators.get('initiator.html').type).toBe('other');
      expect(initiators.get('initiator.js').type).toBe('parser');
      expect(initiators.get('initiator.js').url).toBe(
        server.PREFIX + '/initiator.html',
      );
      expect(initiators.get('frame.html').type).toBe('parser');
      expect(initiators.get('frame.html').url).toBe(
        server.PREFIX + '/initiator.html',
      );
      expect(initiators.get('script.js').type).toBe('parser');
      expect(initiators.get('script.js').url).toBe(
        server.PREFIX + '/frames/frame.html',
      );
      expect(initiators.get('style.css').type).toBe('parser');
      expect(initiators.get('style.css').url).toBe(
        server.PREFIX + '/frames/frame.html',
      );
      expect(initiators.get('initiator.js').type).toBe('parser');
      expect(initiators.get('injectedfile.js').type).toBe('script');
      expect(initiators.get('injectedfile.js').stack.callFrames[0]!.url).toBe(
        server.PREFIX + '/initiator.js',
      );
      expect(initiators.get('injectedstyle.css').type).toBe('script');
      expect(initiators.get('injectedstyle.css').stack.callFrames[0]!.url).toBe(
        server.PREFIX + '/initiator.js',
      );
      expect(initiators.get('initiator.js').url).toBe(
        server.PREFIX + '/initiator.html',
      );
    });
  });

  describe('Response.fromCache', function () {
    it('should return |false| for non-cached content', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.fromCache()).toBe(false);
    });

    // Run this cache test both with a stylesheet and a script.
    // Firefox currently does not handle network events for cached CSS files.
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1879438
    for (const {html, resource, type} of [
      {html: 'one-style.html', resource: 'one-style.css', type: 'stylesheet'},
      {html: 'one-script.html', resource: 'one-script.js', type: 'script'},
    ]) {
      it(`should work for ${type}`, async () => {
        const {page, server} = await getTestState();

        const responses = new Map();
        page.on('response', r => {
          return (
            !isFavicon(r.request()) &&
            responses.set(r.url().split('/').pop(), r)
          );
        });

        // Load and re-load to make sure it's cached.
        await page.goto(server.PREFIX + '/cached/' + html);
        await page.reload();

        expect(responses.size).toBe(2);
        expect(responses.get(resource).status()).toBe(200);
        expect(responses.get(resource).fromCache()).toBe(true);
        expect(responses.get(html).status()).toBe(304);
        expect(responses.get(html).fromCache()).toBe(false);
      });
    }
  });

  describe('Response.fromServiceWorker', function () {
    it('should return |false| for non-service-worker content', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.fromServiceWorker()).toBe(false);
    });

    it('Response.fromServiceWorker', async () => {
      const {page, server} = await getTestState();

      const responses = new Map();
      page.on('response', r => {
        return !isFavicon(r) && responses.set(r.url().split('/').pop(), r);
      });

      // Load and re-load to make sure serviceworker is installed and running.
      await page.goto(server.PREFIX + '/serviceworkers/fetch/sw.html', {
        waitUntil: 'networkidle2',
      });
      await page.evaluate(async () => {
        return (globalThis as any).activationPromise;
      });
      await page.reload();

      expect(responses.size).toBe(2);
      expect(responses.get('sw.html').status()).toBe(200);
      expect(responses.get('sw.html').fromServiceWorker()).toBe(true);
      expect(responses.get('style.css').status()).toBe(200);
      expect(responses.get('style.css').fromServiceWorker()).toBe(true);
    });
  });

  describe('Request.postData', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.EMPTY_PAGE);
      server.setRoute('/post', (_req, res) => {
        return res.end();
      });

      const [request] = await Promise.all([
        waitEvent<HTTPRequest>(page, 'request', r => {
          return !isFavicon(r);
        }),
        page.evaluate(() => {
          return fetch('./post', {
            method: 'POST',
            body: JSON.stringify({foo: 'bar'}),
          });
        }),
      ]);

      expect(request).toBeTruthy();
      expect(request.postData()).toBe('{"foo":"bar"}');
    });

    it('should be |undefined| when there is no post data', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.request().postData()).toBe(undefined);
    });

    it('should work with blobs', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.EMPTY_PAGE);
      server.setRoute('/post', (_req, res) => {
        return res.end();
      });

      const [request] = await Promise.all([
        waitEvent<HTTPRequest>(page, 'request', r => {
          return !isFavicon(r);
        }),
        page.evaluate(() => {
          return fetch('./post', {
            method: 'POST',
            body: new Blob([JSON.stringify({foo: 'bar'})], {
              type: 'application/json',
            }),
          });
        }),
      ]);

      expect(request).toBeTruthy();
      expect(request.postData()).toBe(undefined);
      expect(request.hasPostData()).toBe(true);
      expect(await request.fetchPostData()).toBe('{"foo":"bar"}');
    });
  });

  describe('Response.text', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.PREFIX + '/simple.json'))!;
      const responseText = (await response.text()).trimEnd();
      expect(responseText).toBe('{"foo": "bar"}');
    });
    it('should return uncompressed text', async () => {
      const {page, server} = await getTestState();

      server.enableGzip('/simple.json');
      const response = (await page.goto(server.PREFIX + '/simple.json'))!;
      expect(response.headers()['content-encoding']).toBe('gzip');
      const responseText = (await response.text()).trimEnd();
      expect(responseText).toBe('{"foo": "bar"}');
    });
    it('should throw when requesting body of redirected response', async () => {
      const {page, server} = await getTestState();

      server.setRedirect('/foo.html', '/empty.html');
      const response = (await page.goto(server.PREFIX + '/foo.html'))!;
      const redirectChain = response.request().redirectChain();
      expect(redirectChain).toHaveLength(1);
      const redirected = redirectChain[0]!.response()!;
      expect(redirected.status()).toBe(302);
      let error!: Error;
      await redirected.text().catch(error_ => {
        return (error = error_);
      });
      expect(error.message).toContain(
        'Response body is unavailable for redirect responses',
      );
    });
    it('should wait until response completes', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.EMPTY_PAGE);
      // Setup server to trap request.
      let serverResponse!: ServerResponse;
      server.setRoute('/get', (_req, res) => {
        serverResponse = res;
        // In Firefox, |fetch| will be hanging until it receives |Content-Type| header
        // from server.
        res.setHeader('Content-Type', 'text/plain; charset=utf-8');
        res.write('hello ');
      });
      // Setup page to trap response.
      let requestFinished = false;
      page.on('requestfinished', r => {
        return (requestFinished = requestFinished || r.url().includes('/get'));
      });
      // send request and wait for server response
      const [pageResponse] = await Promise.all([
        page.waitForResponse(r => {
          return !isFavicon(r.request());
        }),
        page.evaluate(() => {
          return fetch('./get', {method: 'GET'});
        }),
        server.waitForRequest('/get'),
      ]);

      expect(serverResponse).toBeTruthy();
      expect(pageResponse).toBeTruthy();
      expect(pageResponse.status()).toBe(200);
      expect(requestFinished).toBe(false);

      const responseText = pageResponse.text();
      // Write part of the response and wait for it to be flushed.
      await new Promise(x => {
        return serverResponse.write('wor', x);
      });
      // Finish response.
      await new Promise<void>(x => {
        serverResponse.end('ld!', () => {
          return x();
        });
      });
      expect(await responseText).toBe('hello world!');
    });
  });

  describe('Response.json', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.PREFIX + '/simple.json'))!;
      expect(await response.json()).toEqual({foo: 'bar'});
    });
  });

  describe('Response.buffer', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.PREFIX + '/pptr.png'))!;
      const imageBuffer = fs.readFileSync(
        path.join(__dirname, '../assets', 'pptr.png'),
      );
      const responseBuffer = await response.buffer();

      expect(Buffer.from(responseBuffer).equals(imageBuffer)).toBe(true);
    });
    it('should work with compression', async () => {
      const {page, server} = await getTestState();

      server.enableGzip('/pptr.png');
      const response = (await page.goto(server.PREFIX + '/pptr.png'))!;
      const imageBuffer = fs.readFileSync(
        path.join(__dirname, '../assets', 'pptr.png'),
      );
      const responseBuffer = await response.buffer();
      expect(Buffer.from(responseBuffer).equals(imageBuffer)).toBe(true);
    });
    it('should throw if the response does not have a body', async () => {
      const {page, server} = await getTestState();

      await page.goto(server.PREFIX + '/empty.html');

      server.setRoute('/test.html', (_req, res) => {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Headers', 'x-ping');
        res.end('Hello World');
      });
      const url = server.CROSS_PROCESS_PREFIX + '/test.html';
      const responsePromise = waitEvent<HTTPResponse>(
        page,
        'response',
        response => {
          // Get the preflight response.
          return (
            response.request().method() === 'OPTIONS' && response.url() === url
          );
        },
      );

      // Trigger a request with a preflight.
      await page.evaluate(async src => {
        const response = await fetch(src, {
          method: 'POST',
          headers: {'x-ping': 'pong'},
        });
        return response;
      }, url);

      const response = await responsePromise;
      await expect(response.buffer()).rejects.toThrowError(
        'Could not load body for this request. This might happen if the request is a preflight request.',
      );
    });
  });

  describe('Response.statusText', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      server.setRoute('/cool', (_req, res) => {
        res.writeHead(200, 'cool!');
        res.end();
      });
      const response = (await page.goto(server.PREFIX + '/cool'))!;
      expect(response.statusText()).toBe('cool!');
    });

    it('handles missing status text', async () => {
      const {page, server} = await getTestState();

      server.setRoute('/nostatus', (_req, res) => {
        res.writeHead(200, '');
        res.end();
      });
      const response = (await page.goto(server.PREFIX + '/nostatus'))!;
      expect(response.statusText()).toBe('');
    });
  });

  describe('Response.timing', function () {
    it('returns timing information', async () => {
      const {page, server} = await getTestState();
      const responses: HTTPResponse[] = [];
      page.on('response', response => {
        if (isFavicon(response)) {
          return;
        }
        return responses.push(response);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(responses).toHaveLength(1);
      expect(responses[0]!.timing()!.receiveHeadersEnd).toBeGreaterThan(0);
    });
  });

  describe('Network Events', function () {
    it('Page.Events.Request', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('request', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(requests).toHaveLength(1);
      const request = requests[0]!;
      expect(request.url()).toBe(server.EMPTY_PAGE);
      expect(request.method()).toBe('GET');
      expect(request.response()).toBeTruthy();
      expect(request.frame() === page.mainFrame()).toBe(true);
      expect(request.frame()!.url()).toBe(server.EMPTY_PAGE);
    });

    // Run this cache test both with a stylesheet and a script.
    // Firefox currently does not handle network events for cached CSS files.
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1879438
    for (const {html, resource, type} of [
      {html: 'one-style.html', resource: 'one-style.css', type: 'stylesheet'},
      {html: 'one-script.html', resource: 'one-script.js', type: 'script'},
    ]) {
      it(`Page.Events.RequestServedFromCache for ${type}`, async () => {
        const {page, server} = await getTestState();

        const cached: string[] = [];
        page.on('requestservedfromcache', r => {
          return !isFavicon(r) && cached.push(r.url().split('/').pop()!);
        });

        await page.goto(server.PREFIX + '/cached/' + html);
        expect(cached).toEqual([]);
        await new Promise(res => {
          setTimeout(res, 1000);
        });
        await page.reload();
        expect(cached).toEqual([resource]);
      });
    }
    it('Page.Events.Response', async () => {
      const {page, server} = await getTestState();

      const responses: HTTPResponse[] = [];
      page.on('response', response => {
        return !isFavicon(response) && responses.push(response);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(responses).toHaveLength(1);
      const response = responses[0]!;
      expect(response.url()).toBe(server.EMPTY_PAGE);
      expect(response.status()).toBe(200);
      expect(response.ok()).toBe(true);
      expect(response.request()).toBeTruthy();
    });

    it('Page.Events.RequestFailed', async () => {
      const {page, server, isChrome} = await getTestState();

      await page.setRequestInterception(true);
      page.on('request', request => {
        if (request.url().endsWith('css')) {
          void request.abort();
        } else {
          void request.continue();
        }
      });
      const failedRequests: HTTPRequest[] = [];
      page.on('requestfailed', request => {
        return failedRequests.push(request);
      });
      await page.goto(server.PREFIX + '/one-style.html');
      expect(failedRequests).toHaveLength(1);
      const failedRequest = failedRequests[0]!;
      expect(failedRequest.url()).toContain('one-style.css');
      expect(failedRequest.response()).toBe(null);
      expect(failedRequest.frame()).toBeTruthy();
      if (isChrome) {
        expect(failedRequest.failure()!.errorText).toBe('net::ERR_FAILED');
      } else {
        expect(failedRequest.failure()!.errorText).toBe('NS_ERROR_ABORT');
      }
    });
    it('Page.Events.RequestFinished', async () => {
      const {page, server} = await getTestState();

      const requests: HTTPRequest[] = [];
      page.on('requestfinished', request => {
        return !isFavicon(request) && requests.push(request);
      });
      await page.goto(server.EMPTY_PAGE);
      expect(requests).toHaveLength(1);
      const request = requests[0]!;
      expect(request.url()).toBe(server.EMPTY_PAGE);
      expect(request.response()).toBeTruthy();
      expect(request.frame() === page.mainFrame()).toBe(true);
      expect(request.frame()!.url()).toBe(server.EMPTY_PAGE);
    });
    it('should fire events in proper order', async () => {
      const {page, server} = await getTestState();

      const events: string[] = [];
      page.on('request', () => {
        return events.push('request');
      });
      page.on('response', () => {
        return events.push('response');
      });
      page.on('requestfinished', () => {
        return events.push('requestfinished');
      });
      await page.goto(server.EMPTY_PAGE);
      // Events can sneak in after the page has navigate
      expect(events.slice(0, 3)).toEqual([
        'request',
        'response',
        'requestfinished',
      ]);
    });
    it('should support redirects', async () => {
      const {page, server} = await getTestState();

      const events: string[] = [];
      page.on('request', request => {
        if (!isFavicon(request)) {
          events.push(`${request.method()} ${request.url()}`);
        }
      });
      page.on('response', response => {
        if (!isFavicon(response)) {
          events.push(`${response.status()} ${response.url()}`);
        }
      });
      page.on('requestfinished', request => {
        if (!isFavicon(request)) {
          events.push(`DONE ${request.url()}`);
        }
      });
      page.on('requestfailed', request => {
        if (!isFavicon(request)) {
          events.push(`FAIL ${request.url()}`);
        }
      });
      server.setRedirect('/foo.html', '/empty.html');
      const FOO_URL = server.PREFIX + '/foo.html';
      const response = (await page.goto(FOO_URL))!;
      expect(events).toEqual([
        `GET ${FOO_URL}`,
        `302 ${FOO_URL}`,
        `DONE ${FOO_URL}`,
        `GET ${server.EMPTY_PAGE}`,
        `200 ${server.EMPTY_PAGE}`,
        `DONE ${server.EMPTY_PAGE}`,
      ]);

      // Check redirect chain
      const redirectChain = response.request().redirectChain();
      expect(redirectChain).toHaveLength(1);
      expect(redirectChain[0]!.url()).toContain('/foo.html');
    });
  });

  describe('Request.isNavigationRequest', () => {
    it('should work', async () => {
      const {page, server} = await getTestState();

      const requests = new Map();
      page.on('request', request => {
        return requests.set(request.url().split('/').pop(), request);
      });
      server.setRedirect('/rrredirect', '/frames/one-frame.html');
      await page.goto(server.PREFIX + '/rrredirect');
      expect(requests.get('rrredirect').isNavigationRequest()).toBe(true);
      expect(requests.get('one-frame.html').isNavigationRequest()).toBe(true);
      expect(requests.get('frame.html').isNavigationRequest()).toBe(true);
      expect(requests.get('script.js').isNavigationRequest()).toBe(false);
      expect(requests.get('style.css').isNavigationRequest()).toBe(false);
    });
    it('should work with request interception', async () => {
      const {page, server} = await getTestState();

      const requests = new Map();
      page.on('request', request => {
        requests.set(request.url().split('/').pop(), request);
        void request.continue();
      });
      await page.setRequestInterception(true);
      server.setRedirect('/rrredirect', '/frames/one-frame.html');
      await page.goto(server.PREFIX + '/rrredirect');
      expect(requests.get('rrredirect').isNavigationRequest()).toBe(true);
      expect(requests.get('one-frame.html').isNavigationRequest()).toBe(true);
      expect(requests.get('frame.html').isNavigationRequest()).toBe(true);
      expect(requests.get('script.js').isNavigationRequest()).toBe(false);
      expect(requests.get('style.css').isNavigationRequest()).toBe(false);
    });
    it('should work when navigating to image', async () => {
      const {page, server} = await getTestState();

      const [request] = await Promise.all([
        waitEvent<HTTPRequest>(page, 'request'),
        page.goto(server.PREFIX + '/pptr.png'),
      ]);
      expect(request.isNavigationRequest()).toBe(true);
    });
  });

  describe('Page.setExtraHTTPHeaders', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();

      await page.setExtraHTTPHeaders({
        foo: 'bar',
      });
      const [request] = await Promise.all([
        server.waitForRequest('/empty.html'),
        page.goto(server.EMPTY_PAGE),
      ]);
      expect(request.headers['foo']).toBe('bar');
    });
    it('should throw for non-string header values', async () => {
      const {page} = await getTestState();

      let error!: Error;
      try {
        // @ts-expect-error purposeful bad input
        await page.setExtraHTTPHeaders({foo: 1});
      } catch (error_) {
        error = error_ as Error;
      }
      expect(error.message).toBe(
        'Expected value of header "foo" to be String, but "number" is found.',
      );
    });
  });

  describe('Page.authenticate', function () {
    it('should work', async () => {
      const {page, server} = await getTestState();
      server.setAuth('/empty.html', 'user', 'pass');
      await page.authenticate({
        username: 'user',
        password: 'pass',
      });
      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.status()).toBe(200);
    });

    it('should error if authentication is required but not enabled', async () => {
      const {page, server} = await getTestState();

      server.setAuth('/empty.html', 'user', 'pass');
      let response;
      try {
        response = (await page.goto(server.EMPTY_PAGE))!;
        expect(response.status()).toBe(401);
      } catch (error) {
        // In headful, an error is thrown instead of 401.
        if (
          !(error as Error).message?.includes(
            'net::ERR_INVALID_AUTH_CREDENTIALS',
          )
        ) {
          throw error;
        }
      }
      await page.authenticate({
        username: 'user',
        password: 'pass',
      });
      response = (await page.reload())!;
      expect(response.status()).toBe(200);
    });
    it('should fail if wrong credentials', async () => {
      const {page, server} = await getTestState();

      // 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(server.EMPTY_PAGE))!;
      expect(response.status()).toBe(401);
    });
    it('should allow disable authentication', async () => {
      const {page, server} = await getTestState();

      // 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(server.EMPTY_PAGE))!;
      expect(response.status()).toBe(200);
      await page.authenticate(null);
      // Navigate to a different origin to bust Chrome's credential caching.
      try {
        response = (await page.goto(
          server.CROSS_PROCESS_PREFIX + '/empty.html',
        ))!;
        expect(response.status()).toBe(401);
      } catch (error) {
        // In headful, an error is thrown instead of 401.
        if (
          !(error as Error).message?.includes(
            'net::ERR_INVALID_AUTH_CREDENTIALS',
          )
        ) {
          throw error;
        }
      }
    });

    // Run this cache test both with a stylesheet and a script.
    // Firefox currently does not handle network events for cached CSS files.
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1879438
    for (const {html, resource, type} of [
      {html: 'one-style.html', resource: 'one-style.css', type: 'stylesheet'},
      {html: 'one-script.html', resource: 'one-script.js', type: 'script'},
    ]) {
      it(`should not disable caching for ${type}`, async () => {
        const {page, server} = await getTestState();

        // Use unique user/password since Chrome caches credentials per origin.
        const user = `user4-${type};`;
        const pass = `pass4-${type};`;
        server.setAuth('/cached/' + resource, user, pass);
        server.setAuth('/cached/' + html, user, pass);
        await page.authenticate({
          username: user,
          password: pass,
        });

        const responses = new Map();
        page.on('response', r => {
          return responses.set(r.url().split('/').pop(), r);
        });

        // Load and re-load to make sure it's cached.
        await page.goto(server.PREFIX + '/cached/' + html);
        await page.reload();

        expect(responses.get(resource).status()).toBe(200);
        expect(responses.get(resource).fromCache()).toBe(true);
        expect(responses.get(html).status()).toBe(304);
        expect(responses.get(html).fromCache()).toBe(false);
      });
    }
  });

  describe('raw network headers', () => {
    it('Same-origin set-cookie navigation', async () => {
      const {page, server} = await getTestState();

      const setCookieString = 'foo=bar';
      server.setRoute('/empty.html', (_req, res) => {
        res.setHeader('set-cookie', setCookieString);
        res.end('hello world');
      });
      const response = (await page.goto(server.EMPTY_PAGE))!;
      expect(response.headers()['set-cookie']).toBe(setCookieString);
    });

    it('Same-origin set-cookie subresource', async () => {
      const {page, server} = await getTestState();
      await page.goto(server.EMPTY_PAGE);

      const setCookieString = 'foo=bar';
      server.setRoute('/foo', (_req, res) => {
        res.setHeader('set-cookie', setCookieString);
        res.end('hello world');
      });

      const [response] = await Promise.all([
        waitEvent<HTTPResponse>(page, 'response', res => {
          return !isFavicon(res);
        }),
        page.evaluate(() => {
          const xhr = new XMLHttpRequest();
          xhr.open('GET', '/foo');
          xhr.send();
        }),
      ]);
      expect(response.headers()['set-cookie']).toBe(setCookieString);
    });

    it('Cross-origin set-cookie', async () => {
      const {page, httpsServer, close} = await launch(
        {
          acceptInsecureCerts: true,
        },
        {
          createContext: true,
        },
      );
      try {
        await page.goto(httpsServer.PREFIX + '/empty.html');

        const setCookieString = 'hello=world';
        httpsServer.setRoute('/setcookie.html', (_req, res) => {
          res.setHeader('Access-Control-Allow-Origin', '*');
          res.setHeader('set-cookie', setCookieString);
          res.end();
        });
        await page.goto(httpsServer.PREFIX + '/setcookie.html');
        const url = httpsServer.CROSS_PROCESS_PREFIX + '/setcookie.html';
        const [response] = await Promise.all([
          waitEvent<HTTPResponse>(page, 'response', response => {
            return response.url() === url;
          }),
          page.evaluate(src => {
            const xhr = new XMLHttpRequest();
            xhr.open('GET', src);
            xhr.send();
          }, url),
        ]);
        expect(response.headers()['set-cookie']).toBe(setCookieString);
      } finally {
        await close();
      }
    });
  });

  describe('Page.setBypassServiceWorker', () => {
    it('bypass for network', async () => {
      const {page, server} = await getTestState();

      const responses = new Map();
      page.on('response', r => {
        return !isFavicon(r) && responses.set(r.url().split('/').pop(), r);
      });

      // Load and re-load to make sure serviceworker is installed and running.
      await page.goto(server.PREFIX + '/serviceworkers/fetch/sw.html', {
        waitUntil: 'networkidle2',
      });
      await page.evaluate(async () => {
        return (globalThis as any).activationPromise;
      });
      await page.reload({
        waitUntil: 'networkidle2',
      });

      expect(page.isServiceWorkerBypassed()).toBe(false);
      expect(responses.size).toBe(2);
      expect(responses.get('sw.html').status()).toBe(200);
      expect(responses.get('sw.html').fromServiceWorker()).toBe(true);
      expect(responses.get('style.css').status()).toBe(200);
      expect(responses.get('style.css').fromServiceWorker()).toBe(true);

      await page.setBypassServiceWorker(true);
      await page.reload({
        waitUntil: 'networkidle2',
      });

      expect(page.isServiceWorkerBypassed()).toBe(true);
      expect(responses.get('sw.html').status()).toBe(200);
      expect(responses.get('sw.html').fromServiceWorker()).toBe(false);
      expect(responses.get('style.css').status()).toBe(200);
      expect(responses.get('style.css').fromServiceWorker()).toBe(false);
    });
  });

  describe('Request.resourceType', () => {
    it('should work for document type', async () => {
      const {page, server} = await getTestState();

      const response = await page.goto(server.EMPTY_PAGE);
      const request = response!.request();
      expect(request.resourceType()).toBe('document');
    });

    it('should work for stylesheets', async () => {
      const {page, server} = await getTestState();

      const cssRequests: HTTPRequest[] = [];
      page.on('request', request => {
        if (request.url().endsWith('css')) {
          cssRequests.push(request);
        }
      });
      await page.goto(server.PREFIX + '/one-style.html');
      expect(cssRequests).toHaveLength(1);
      const request = cssRequests[0]!;
      expect(request.url()).toContain('one-style.css');
      expect(request.resourceType()).toBe('stylesheet');
    });
  });

  describe('Response.remoteAddress', () => {
    it('should work', async () => {
      const {page, server} = await getTestState();

      const response = (await page.goto(server.EMPTY_PAGE))!;
      const remoteAddress = response.remoteAddress();
      // Either IPv6 or IPv4, depending on environment.
      expect(
        remoteAddress.ip!.includes('::1') || remoteAddress.ip === '127.0.0.1',
      ).toBe(true);
      expect(remoteAddress.port).toBe(server.PORT);
    });

    it('should support redirects', async () => {
      const {page, server} = await getTestState();

      server.setRedirect('/foo.html', '/empty.html');
      const FOO_URL = server.PREFIX + '/foo.html';
      const response = (await page.goto(FOO_URL))!;

      // Check redirect chain
      const redirectChain = response.request().redirectChain();
      expect(redirectChain).toHaveLength(1);
      expect(redirectChain[0]!.url()).toContain('/foo.html');
      expect(redirectChain[0]!.response()!.remoteAddress().port).toBe(
        server.PORT,
      );
    });
  });
});

[ Verzeichnis aufwärts0.57unsichere Verbindung  Übersetzung europäischer Sprachen durch Browser  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge