1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | import Headers from './headers.js';
|
8 | import Body, {clone, extractContentType} from './body.js';
|
9 | import {isRedirect} from './utils/is-redirect.js';
|
10 |
|
11 | const INTERNALS = Symbol('Response internals');
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | export default class Response extends Body {
|
23 | constructor(body = null, options = {}) {
|
24 | super(body, options);
|
25 |
|
26 |
|
27 | const status = options.status != null ? options.status : 200;
|
28 |
|
29 | const headers = new Headers(options.headers);
|
30 |
|
31 | if (body !== null && !headers.has('Content-Type')) {
|
32 | const contentType = extractContentType(body, this);
|
33 | if (contentType) {
|
34 | headers.append('Content-Type', contentType);
|
35 | }
|
36 | }
|
37 |
|
38 | this[INTERNALS] = {
|
39 | type: 'default',
|
40 | url: options.url,
|
41 | status,
|
42 | statusText: options.statusText || '',
|
43 | headers,
|
44 | counter: options.counter,
|
45 | highWaterMark: options.highWaterMark
|
46 | };
|
47 | }
|
48 |
|
49 | get type() {
|
50 | return this[INTERNALS].type;
|
51 | }
|
52 |
|
53 | get url() {
|
54 | return this[INTERNALS].url || '';
|
55 | }
|
56 |
|
57 | get status() {
|
58 | return this[INTERNALS].status;
|
59 | }
|
60 |
|
61 | |
62 |
|
63 |
|
64 | get ok() {
|
65 | return this[INTERNALS].status >= 200 && this[INTERNALS].status < 300;
|
66 | }
|
67 |
|
68 | get redirected() {
|
69 | return this[INTERNALS].counter > 0;
|
70 | }
|
71 |
|
72 | get statusText() {
|
73 | return this[INTERNALS].statusText;
|
74 | }
|
75 |
|
76 | get headers() {
|
77 | return this[INTERNALS].headers;
|
78 | }
|
79 |
|
80 | get highWaterMark() {
|
81 | return this[INTERNALS].highWaterMark;
|
82 | }
|
83 |
|
84 | |
85 |
|
86 |
|
87 |
|
88 |
|
89 | clone() {
|
90 | return new Response(clone(this, this.highWaterMark), {
|
91 | type: this.type,
|
92 | url: this.url,
|
93 | status: this.status,
|
94 | statusText: this.statusText,
|
95 | headers: this.headers,
|
96 | ok: this.ok,
|
97 | redirected: this.redirected,
|
98 | size: this.size,
|
99 | highWaterMark: this.highWaterMark
|
100 | });
|
101 | }
|
102 |
|
103 | |
104 |
|
105 |
|
106 |
|
107 |
|
108 | static redirect(url, status = 302) {
|
109 | if (!isRedirect(status)) {
|
110 | throw new RangeError('Failed to execute "redirect" on "response": Invalid status code');
|
111 | }
|
112 |
|
113 | return new Response(null, {
|
114 | headers: {
|
115 | location: new URL(url).toString()
|
116 | },
|
117 | status
|
118 | });
|
119 | }
|
120 |
|
121 | static error() {
|
122 | const response = new Response(null, {status: 0, statusText: ''});
|
123 | response[INTERNALS].type = 'error';
|
124 | return response;
|
125 | }
|
126 |
|
127 | get [Symbol.toStringTag]() {
|
128 | return 'Response';
|
129 | }
|
130 | }
|
131 |
|
132 | Object.defineProperties(Response.prototype, {
|
133 | type: {enumerable: true},
|
134 | url: {enumerable: true},
|
135 | status: {enumerable: true},
|
136 | ok: {enumerable: true},
|
137 | redirected: {enumerable: true},
|
138 | statusText: {enumerable: true},
|
139 | headers: {enumerable: true},
|
140 | clone: {enumerable: true}
|
141 | });
|