1'use strict'
2const http = require('http')
3const { STATUS_CODES } = http
4
5const Headers = require('./headers.js')
6const Body = require('./body.js')
7const { clone, extractContentType } = Body
8
9const INTERNALS = Symbol('Response internals')
10
11class Response extends Body {
12  constructor (body = null, opts = {}) {
13    super(body, opts)
14
15    const status = opts.status || 200
16    const headers = new Headers(opts.headers)
17
18    if (body !== null && body !== undefined && !headers.has('Content-Type')) {
19      const contentType = extractContentType(body)
20      if (contentType) {
21        headers.append('Content-Type', contentType)
22      }
23    }
24
25    this[INTERNALS] = {
26      url: opts.url,
27      status,
28      statusText: opts.statusText || STATUS_CODES[status],
29      headers,
30      counter: opts.counter,
31      trailer: Promise.resolve(opts.trailer || new Headers()),
32    }
33  }
34
35  get trailer () {
36    return this[INTERNALS].trailer
37  }
38
39  get url () {
40    return this[INTERNALS].url || ''
41  }
42
43  get status () {
44    return this[INTERNALS].status
45  }
46
47  get ok () {
48    return this[INTERNALS].status >= 200 && this[INTERNALS].status < 300
49  }
50
51  get redirected () {
52    return this[INTERNALS].counter > 0
53  }
54
55  get statusText () {
56    return this[INTERNALS].statusText
57  }
58
59  get headers () {
60    return this[INTERNALS].headers
61  }
62
63  clone () {
64    return new Response(clone(this), {
65      url: this.url,
66      status: this.status,
67      statusText: this.statusText,
68      headers: this.headers,
69      ok: this.ok,
70      redirected: this.redirected,
71      trailer: this.trailer,
72    })
73  }
74
75  get [Symbol.toStringTag] () {
76    return 'Response'
77  }
78}
79
80module.exports = Response
81
82Object.defineProperties(Response.prototype, {
83  url: { enumerable: true },
84  status: { enumerable: true },
85  ok: { enumerable: true },
86  redirected: { enumerable: true },
87  statusText: { enumerable: true },
88  headers: { enumerable: true },
89  clone: { enumerable: true },
90})
91