• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

chimurai / http-proxy-middleware / 14246826731

03 Apr 2025 03:26PM CUT coverage: 97.33% (+0.05%) from 97.284%
14246826731

Pull #823

github

web-flow
Merge ef93655f0 into e94087e8d
Pull Request #823: fix(websocket): handle errors in handleUpgrade

137 of 142 branches covered (96.48%)

16 of 16 new or added lines in 2 files covered. (100.0%)

401 of 412 relevant lines covered (97.33%)

24.93 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.1
/src/plugins/default/logger-plugin.ts
1
import { URL } from 'url';
12✔
2
import { Plugin } from '../../types';
3
import { getLogger } from '../../logger';
12✔
4
import type { IncomingMessage } from 'node:http';
5
import { getPort } from '../../utils/logger-plugin';
12✔
6

7
type ExpressRequest = {
8
  /** Express req.baseUrl */
9
  baseUrl?: string;
10
};
11

12
type BrowserSyncRequest = {
13
  /** BrowserSync req.originalUrl */
14
  originalUrl?: string;
15
};
16

17
/** Request Types from different server libs */
18
type FrameworkRequest = IncomingMessage & ExpressRequest & BrowserSyncRequest;
19

20
export const loggerPlugin: Plugin = (proxyServer, options) => {
12✔
21
  const logger = getLogger(options);
75✔
22

23
  proxyServer.on('error', (err, req, res, target?) => {
75✔
24
    const hostname = req?.headers?.host;
6✔
25
    const requestHref = `${hostname}${req?.url}`;
6✔
26
    const targetHref = `${(target as unknown as any)?.href}`; // target is undefined when websocket errors
6✔
27

28
    const errorMessage = '[HPM] Error occurred while proxying request %s to %s [%s] (%s)';
6✔
29
    const errReference = 'https://nodejs.org/api/errors.html#errors_common_system_errors'; // link to Node Common Systems Errors page
6✔
30

31
    logger.error(errorMessage, requestHref, targetHref, (err as any).code || err, errReference);
6✔
32
  });
33

34
  /**
35
   * Log request and response
36
   * @example
37
   * ```shell
38
   * [HPM] GET /users/ -> http://jsonplaceholder.typicode.com/users/ [304]
39
   * ```
40
   */
41
  proxyServer.on('proxyRes', (proxyRes: any, req: FrameworkRequest, res) => {
75✔
42
    // BrowserSync uses req.originalUrl
43
    // Next.js doesn't have req.baseUrl
44
    const originalUrl = req.originalUrl ?? `${req.baseUrl || ''}${req.url}`;
43✔
45

46
    // construct targetUrl
47
    let target: URL;
48

49
    try {
43✔
50
      const port = getPort(proxyRes.req?.agent?.sockets);
43✔
51

52
      const obj = {
43✔
53
        protocol: proxyRes.req.protocol,
54
        host: proxyRes.req.host,
55
        pathname: proxyRes.req.path,
56
      } as URL;
57

58
      target = new URL(`${obj.protocol}//${obj.host}${obj.pathname}`);
43✔
59

60
      if (port) {
43✔
61
        target.port = port;
43✔
62
      }
63
      // eslint-disable-next-line @typescript-eslint/no-unused-vars
64
    } catch (err) {
65
      // nock issue (https://github.com/chimurai/http-proxy-middleware/issues/1035)
66
      // fallback to old implementation (less correct - without port)
67
      target = new URL(options.target as URL);
×
68
      target.pathname = proxyRes.req.path;
×
69
    }
70

71
    const targetUrl = target.toString();
43✔
72

73
    const exchange = `[HPM] ${req.method} ${originalUrl} -> ${targetUrl} [${proxyRes.statusCode}]`;
43✔
74
    logger.info(exchange);
43✔
75
  });
76

77
  /**
78
   * When client opens WebSocket connection
79
   */
80
  proxyServer.on('open', (socket) => {
75✔
81
    logger.info('[HPM] Client connected: %o', socket.address());
3✔
82
  });
83

84
  /**
85
   * When client closes WebSocket connection
86
   */
87
  proxyServer.on('close', (req, proxySocket, proxyHead) => {
75✔
88
    logger.info('[HPM] Client disconnected: %o', proxySocket.address());
3✔
89
  });
90
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc