http.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import http from 'http';
  2. import https from 'https';
  3. import urlMod from 'url';
  4. import { BaseClient, BaseResponse } from './base.js';
  5. import { AbortError } from '../../utils.js';
  6. class HttpResponse extends BaseResponse {
  7. /**
  8. * BaseResponse facade for node HTTP/HTTPS API Response
  9. * @param {http.ServerResponse} response
  10. */
  11. constructor(response, dataPromise) {
  12. super();
  13. this.response = response;
  14. this.dataPromise = dataPromise;
  15. }
  16. get status() {
  17. return this.response.statusCode;
  18. }
  19. getHeader(name) {
  20. return this.response.headers[name];
  21. }
  22. async getData() {
  23. const data = await this.dataPromise;
  24. return data;
  25. }
  26. }
  27. export class HttpClient extends BaseClient {
  28. constructor(url) {
  29. super(url);
  30. this.parsedUrl = urlMod.parse(this.url);
  31. this.httpApi = (this.parsedUrl.protocol === 'http:' ? http : https);
  32. }
  33. constructRequest(headers, signal) {
  34. return new Promise((resolve, reject) => {
  35. const request = this.httpApi.get(
  36. {
  37. ...this.parsedUrl,
  38. headers,
  39. },
  40. (response) => {
  41. const dataPromise = new Promise((resolveData) => {
  42. const chunks = [];
  43. // collect chunks
  44. response.on('data', (chunk) => {
  45. chunks.push(chunk);
  46. });
  47. // concatenate all chunks and resolve the promise with the resulting buffer
  48. response.on('end', () => {
  49. const data = Buffer.concat(chunks).buffer;
  50. resolveData(data);
  51. });
  52. response.on('error', reject);
  53. });
  54. resolve(new HttpResponse(response, dataPromise));
  55. },
  56. );
  57. request.on('error', reject);
  58. if (signal) {
  59. if (signal.aborted) {
  60. request.destroy(new AbortError('Request aborted'));
  61. }
  62. signal.addEventListener('abort', () => request.destroy(new AbortError('Request aborted')));
  63. }
  64. });
  65. }
  66. async request({ headers, signal } = {}) {
  67. const response = await this.constructRequest(headers, signal);
  68. return response;
  69. }
  70. }