plugin-utils.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. import { RequestHandler } from 'express';
  2. import proxy from 'http-proxy-middleware';
  3. import { Logger, VendureConfig } from '../config';
  4. /**
  5. * @description
  6. * Creates a proxy middleware which proxies the given route to the given port.
  7. * Useful for plugins which start their own servers but should be accessible
  8. * via the main Vendure url.
  9. *
  10. * @example
  11. * ```ts
  12. * // Example usage in the `configuration` method of a VendurePlugin.
  13. * // Imagine that we have started a Node server on port 5678
  14. * // running some service which we want to access via the `/my-plugin/`
  15. * // route of the main Vendure server.
  16. * \@VendurePlugin({
  17. * configure: (config: Required<VendureConfig>) => {
  18. * config.middleware.push({
  19. * handler: createProxyHandler({
  20. * label: 'Admin UI',
  21. * route: 'my-plugin',
  22. * port: 5678,
  23. * }),
  24. * route: 'my-plugin',
  25. * });
  26. * return config;
  27. * }
  28. * })
  29. * export class MyPlugin {}
  30. * ```
  31. *
  32. * @docsCategory Plugin
  33. * @docsPage Plugin Utilities
  34. */
  35. export function createProxyHandler(options: ProxyOptions): RequestHandler {
  36. const route = options.route.charAt(0) === '/' ? options.route : '/' + options.route;
  37. const proxyHostname = options.hostname || 'localhost';
  38. const middleware = proxy({
  39. // TODO: how do we detect https?
  40. target: `http://${proxyHostname}:${options.port}`,
  41. pathRewrite: {
  42. [`^${route}`]: `/` + (options.basePath || ''),
  43. },
  44. logProvider(provider: proxy.LogProvider): proxy.LogProvider {
  45. return {
  46. log(message: string) {
  47. Logger.debug(message, options.label);
  48. },
  49. debug(message: string) {
  50. Logger.debug(message, options.label);
  51. },
  52. info(message: string) {
  53. Logger.debug(message, options.label);
  54. },
  55. warn(message: string) {
  56. Logger.warn(message, options.label);
  57. },
  58. error(message: string) {
  59. Logger.error(message, options.label);
  60. },
  61. };
  62. },
  63. });
  64. // Attach the options to the middleware function to allow
  65. // the info to be logged after bootstrap.
  66. (middleware as any).proxyMiddleware = options;
  67. return middleware;
  68. }
  69. /**
  70. * @description
  71. * Options to configure proxy middleware via {@link createProxyHandler}.
  72. *
  73. * @docsCategory Plugin
  74. * @docsPage Plugin Utilities
  75. */
  76. export interface ProxyOptions {
  77. /**
  78. * @description
  79. * A human-readable label for the service which is being proxied. Used to
  80. * generate more informative logs.
  81. */
  82. label: string;
  83. /**
  84. * @description
  85. * The route of the Vendure server which will act as the proxy url.
  86. */
  87. route: string;
  88. /**
  89. * @description
  90. * The port on which the service being proxied is running.
  91. */
  92. port: number;
  93. /**
  94. * @description
  95. * The hostname of the server on which the service being proxied is running.
  96. *
  97. * @default 'localhost'
  98. */
  99. hostname?: string;
  100. /**
  101. * @description
  102. * An optional base path on the proxied server.
  103. */
  104. basePath?: string;
  105. }
  106. /**
  107. * If any proxy middleware has been set up using the createProxyHandler function, log this information.
  108. */
  109. export function logProxyMiddlewares(config: VendureConfig) {
  110. for (const middleware of config.middleware || []) {
  111. if ((middleware.handler as any).proxyMiddleware) {
  112. const { port, hostname, label, route, basePath } = (middleware.handler as any)
  113. .proxyMiddleware as ProxyOptions;
  114. Logger.info(
  115. `${label}: http://${config.hostname || 'localhost'}:${
  116. config.port
  117. }/${route}/ -> http://${hostname || 'localhost'}:${port}${basePath ? `/${basePath}` : ''}`,
  118. );
  119. }
  120. }
  121. }