request-context.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. import {Errorf} from '@e22m4u/js-format';
  2. import {isReadableStream} from './utils/index.js';
  3. import {isWritableStream} from './utils/index.js';
  4. import {ServiceContainer} from '@e22m4u/js-service';
  5. import {getRequestPathname} from './utils/index.js';
  6. import {isServiceContainer} from '@e22m4u/js-service';
  7. /**
  8. * Request context.
  9. */
  10. export class RequestContext {
  11. /**
  12. * Service container.
  13. *
  14. * @type {import('@e22m4u/js-service').ServiceContainer}
  15. */
  16. container;
  17. /**
  18. * Request.
  19. *
  20. * @type {import('http').IncomingMessage}
  21. */
  22. req;
  23. /**
  24. * Response.
  25. *
  26. * @type {import('http').ServerResponse}
  27. */
  28. res;
  29. /**
  30. * Query.
  31. *
  32. * @type {object}
  33. */
  34. query = {};
  35. /**
  36. * Path parameters.
  37. *
  38. * @type {object}
  39. */
  40. params = {};
  41. /**
  42. * Headers.
  43. *
  44. * @type {object}
  45. */
  46. headers = {};
  47. /**
  48. * Parsed cookies.
  49. *
  50. * @type {object}
  51. */
  52. cookies = {};
  53. /**
  54. * Parsed body.
  55. *
  56. * @type {*}
  57. */
  58. body;
  59. /**
  60. * Method.
  61. *
  62. * @returns {string}
  63. */
  64. get method() {
  65. return this.req.method.toUpperCase();
  66. }
  67. /**
  68. * Path.
  69. *
  70. * @returns {string}
  71. */
  72. get path() {
  73. return this.req.url;
  74. }
  75. /**
  76. * Pathname.
  77. *
  78. * @type {string|undefined}
  79. * @private
  80. */
  81. _pathname = undefined;
  82. /**
  83. * Pathname.
  84. *
  85. * @returns {string}
  86. */
  87. get pathname() {
  88. if (this._pathname != null) return this._pathname;
  89. this._pathname = getRequestPathname(this.req);
  90. return this._pathname;
  91. }
  92. /**
  93. * Constructor.
  94. *
  95. * @param {ServiceContainer} container
  96. * @param {import('http').IncomingMessage} request
  97. * @param {import('http').ServerResponse} response
  98. */
  99. constructor(container, request, response) {
  100. if (!isServiceContainer(container))
  101. throw new Errorf(
  102. 'The parameter "container" of RequestContext.constructor ' +
  103. 'should be an instance of ServiceContainer, but %v was given.',
  104. container,
  105. );
  106. this.container = container;
  107. if (
  108. !request ||
  109. typeof request !== 'object' ||
  110. Array.isArray(request) ||
  111. !isReadableStream(request)
  112. ) {
  113. throw new Errorf(
  114. 'The parameter "request" of RequestContext.constructor ' +
  115. 'should be an instance of IncomingMessage, but %v was given.',
  116. request,
  117. );
  118. }
  119. this.req = request;
  120. if (
  121. !response ||
  122. typeof response !== 'object' ||
  123. Array.isArray(response) ||
  124. !isWritableStream(response)
  125. ) {
  126. throw new Errorf(
  127. 'The parameter "response" of RequestContext.constructor ' +
  128. 'should be an instance of ServerResponse, but %v was given.',
  129. response,
  130. );
  131. }
  132. this.res = response;
  133. }
  134. }