1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 | import videojs from 'video.js';
|
13 |
|
14 | const {
|
15 | xhr: videojsXHR,
|
16 | mergeOptions
|
17 | } = videojs;
|
18 |
|
19 | const callbackWrapper = function(request, error, response, callback) {
|
20 | const reqResponse = request.responseType === 'arraybuffer' ? request.response : request.responseText;
|
21 |
|
22 | if (!error && reqResponse) {
|
23 | request.responseTime = Date.now();
|
24 | request.roundTripTime = request.responseTime - request.requestTime;
|
25 | request.bytesReceived = reqResponse.byteLength || reqResponse.length;
|
26 | if (!request.bandwidth) {
|
27 | request.bandwidth =
|
28 | Math.floor((request.bytesReceived / request.roundTripTime) * 8 * 1000);
|
29 | }
|
30 | }
|
31 |
|
32 | if (response.headers) {
|
33 | request.responseHeaders = response.headers;
|
34 | }
|
35 |
|
36 |
|
37 |
|
38 |
|
39 | if (error && error.code === 'ETIMEDOUT') {
|
40 | request.timedout = true;
|
41 | }
|
42 |
|
43 |
|
44 |
|
45 |
|
46 | if (!error &&
|
47 | !request.aborted &&
|
48 | response.statusCode !== 200 &&
|
49 | response.statusCode !== 206 &&
|
50 | response.statusCode !== 0) {
|
51 | error = new Error('XHR Failed with a response of: ' +
|
52 | (request && (reqResponse || request.responseText)));
|
53 | }
|
54 |
|
55 | callback(error, request);
|
56 | };
|
57 |
|
58 | const xhrFactory = function() {
|
59 | const xhr = function XhrFunction(options, callback) {
|
60 |
|
61 | options = mergeOptions({
|
62 | timeout: 45e3
|
63 | }, options);
|
64 |
|
65 |
|
66 |
|
67 | const beforeRequest = XhrFunction.beforeRequest || videojs.Vhs.xhr.beforeRequest;
|
68 |
|
69 | if (beforeRequest && typeof beforeRequest === 'function') {
|
70 | const newOptions = beforeRequest(options);
|
71 |
|
72 | if (newOptions) {
|
73 | options = newOptions;
|
74 | }
|
75 | }
|
76 |
|
77 |
|
78 |
|
79 | const xhrMethod = videojs.Vhs.xhr.original === true ? videojsXHR : videojs.Vhs.xhr;
|
80 |
|
81 | const request = xhrMethod(options, function(error, response) {
|
82 | return callbackWrapper(request, error, response, callback);
|
83 | });
|
84 | const originalAbort = request.abort;
|
85 |
|
86 | request.abort = function() {
|
87 | request.aborted = true;
|
88 | return originalAbort.apply(request, arguments);
|
89 | };
|
90 | request.uri = options.uri;
|
91 | request.requestTime = Date.now();
|
92 | return request;
|
93 | };
|
94 |
|
95 | xhr.original = true;
|
96 |
|
97 | return xhr;
|
98 | };
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | const byterangeStr = function(byterange) {
|
108 |
|
109 |
|
110 | const byterangeEnd = byterange.offset + byterange.length - 1;
|
111 | const byterangeStart = byterange.offset;
|
112 |
|
113 | return 'bytes=' + byterangeStart + '-' + byterangeEnd;
|
114 | };
|
115 |
|
116 |
|
117 |
|
118 |
|
119 |
|
120 |
|
121 |
|
122 | const segmentXhrHeaders = function(segment) {
|
123 | const headers = {};
|
124 |
|
125 | if (segment.byterange) {
|
126 | headers.Range = byterangeStr(segment.byterange);
|
127 | }
|
128 | return headers;
|
129 | };
|
130 |
|
131 | export {segmentXhrHeaders, callbackWrapper, xhrFactory};
|
132 |
|
133 | export default xhrFactory;
|