-
Notifications
You must be signed in to change notification settings - Fork 473
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adding support to Media Converter extension
- Loading branch information
1 parent
d1376e0
commit 70ccad7
Showing
9 changed files
with
403 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
'use strict'; | ||
var url = require('url'); | ||
var assert = require('assert'); | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
njjetsfan
via email
|
||
var http = require('http'); | ||
var https = require('https'); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
var Writable = require('stream').Writable; | ||
|
||
var nativeProtocols = {'http:': http, 'https:': https}; | ||
This comment has been minimized.
Sorry, something went wrong. |
||
var schemes = {}; | ||
var exports = module.exports = { | ||
maxRedirects: 21 | ||
}; | ||
// RFC7231§4.2.1: Of the request methods defined by this specification, | ||
// the GET, HEAD, OPTIONS, and TRACE methods are defined to be safe. | ||
var safeMethods = {GET: true, HEAD: true, OPTIONS: true, TRACE: true}; | ||
|
||
// Create handlers that pass events from native requests | ||
var eventHandlers = Object.create(null); | ||
['abort', 'aborted', 'error', 'socket'].forEach(function (event) { | ||
eventHandlers[event] = function (arg) { | ||
this._redirectable.emit(event, arg); | ||
}; | ||
}); | ||
|
||
// An HTTP(S) request that can be redirected | ||
function RedirectableRequest(options, responseCallback) { | ||
// Initialize the request | ||
Writable.call(this); | ||
this._options = options; | ||
this._redirectCount = 0; | ||
this._bufferedWrites = []; | ||
|
||
// Attach a callback if passed | ||
if (responseCallback) { | ||
this.on('response', responseCallback); | ||
} | ||
|
||
// React to responses of native requests | ||
var self = this; | ||
this._onNativeResponse = function (response) { | ||
self._processResponse(response); | ||
}; | ||
|
||
// Perform the first request | ||
this._performRequest(); | ||
} | ||
RedirectableRequest.prototype = Object.create(Writable.prototype); | ||
|
||
// Executes the next native request (initial or redirect) | ||
RedirectableRequest.prototype._performRequest = function () { | ||
// If specified, use the agent corresponding to the protocol | ||
// (HTTP and HTTPS use different types of agents) | ||
var protocol = this._options.protocol; | ||
if (this._options.agents) { | ||
this._options.agent = this._options.agents[schemes[protocol]]; | ||
} | ||
|
||
// Create the native request | ||
var nativeProtocol = nativeProtocols[this._options.protocol]; | ||
var request = this._currentRequest = | ||
nativeProtocol.request(this._options, this._onNativeResponse); | ||
this._currentUrl = url.format(this._options); | ||
|
||
// Set up event handlers | ||
request._redirectable = this; | ||
for (var event in eventHandlers) { | ||
if (event) { | ||
request.on(event, eventHandlers[event]); | ||
} | ||
} | ||
|
||
// End a redirected request | ||
// (The first request must be ended explicitly with RedirectableRequest#end) | ||
if (this._currentResponse) { | ||
// If no body was written to the original request, or the method was changed to GET, | ||
// end the redirected request (without writing a body). | ||
var bufferedWrites = this._bufferedWrites; | ||
if (bufferedWrites.length === 0 || this._options.method === 'GET') { | ||
request.end(); | ||
// The body of the original request must be added to the redirected request. | ||
} else { | ||
var i = 0; | ||
(function writeNext() { | ||
if (i < bufferedWrites.length) { | ||
var bufferedWrite = bufferedWrites[i++]; | ||
request.write(bufferedWrite.data, bufferedWrite.encoding, writeNext); | ||
} else { | ||
request.end(); | ||
} | ||
})(); | ||
} | ||
} | ||
}; | ||
|
||
// Processes a response from the current native request | ||
RedirectableRequest.prototype._processResponse = function (response) { | ||
// RFC7231§6.4: The 3xx (Redirection) class of status code indicates | ||
// that further action needs to be taken by the user agent in order to | ||
// fulfill the request. If a Location header field is provided, | ||
// the user agent MAY automatically redirect its request to the URI | ||
// referenced by the Location field value, | ||
// even if the specific status code is not understood. | ||
var location = response.headers.location; | ||
if (location && this._options.followRedirects !== false && | ||
response.statusCode >= 300 && response.statusCode < 400) { | ||
// RFC7231§6.4: A client SHOULD detect and intervene | ||
// in cyclical redirections (i.e., "infinite" redirection loops). | ||
if (++this._redirectCount > this._options.maxRedirects) { | ||
return this.emit('error', new Error('Max redirects exceeded.')); | ||
} | ||
|
||
// RFC7231§6.4.7: The 307 (Temporary Redirect) status code indicates | ||
// that the target resource resides temporarily under a different URI | ||
// and the user agent MUST NOT change the request method | ||
// if it performs an automatic redirection to that URI. | ||
if (response.statusCode !== 307) { | ||
// RFC7231§6.4: Automatic redirection needs to done with | ||
// care for methods not known to be safe […], | ||
// since the user might not wish to redirect an unsafe request. | ||
if (!(this._options.method in safeMethods)) { | ||
this._options.method = 'GET'; | ||
} | ||
} | ||
|
||
// Perform the redirected request | ||
var redirectUrl = url.resolve(this._currentUrl, location); | ||
Object.assign(this._options, url.parse(redirectUrl)); | ||
this._currentResponse = response; | ||
this._performRequest(); | ||
} else { | ||
// The response is not a redirect; return it as-is | ||
response.responseUrl = this._currentUrl; | ||
this.emit('response', response); | ||
|
||
// Clean up | ||
delete this._options; | ||
delete this._bufferedWrites; | ||
} | ||
}; | ||
|
||
// Aborts the current native request | ||
RedirectableRequest.prototype.abort = function () { | ||
this._currentRequest.abort(); | ||
}; | ||
|
||
// Flushes the headers of the current native request | ||
RedirectableRequest.prototype.flushHeaders = function () { | ||
this._currentRequest.flushHeaders(); | ||
}; | ||
|
||
// Sets the noDelay option of the current native request | ||
RedirectableRequest.prototype.setNoDelay = function (noDelay) { | ||
this._currentRequest.setNoDelay(noDelay); | ||
}; | ||
|
||
// Sets the socketKeepAlive option of the current native request | ||
RedirectableRequest.prototype.setSocketKeepAlive = function (enable, initialDelay) { | ||
this._currentRequest.setSocketKeepAlive(enable, initialDelay); | ||
}; | ||
|
||
// Sets the timeout option of the current native request | ||
RedirectableRequest.prototype.setTimeout = function (timeout, callback) { | ||
this._currentRequest.setTimeout(timeout, callback); | ||
}; | ||
|
||
// Writes buffered data to the current native request | ||
RedirectableRequest.prototype._write = function (data, encoding, callback) { | ||
this._currentRequest.write(data, encoding, callback); | ||
this._bufferedWrites.push({data: data, encoding: encoding}); | ||
}; | ||
|
||
// Ends the current native request | ||
RedirectableRequest.prototype.end = function (data, encoding, callback) { | ||
this._currentRequest.end(data, encoding, callback); | ||
if (data) { | ||
this._bufferedWrites.push({data: data, encoding: encoding}); | ||
} | ||
}; | ||
|
||
// Export a redirecting wrapper for each native protocol | ||
Object.keys(nativeProtocols).forEach(function (protocol) { | ||
var scheme = schemes[protocol] = protocol.substr(0, protocol.length - 1); | ||
var nativeProtocol = nativeProtocols[protocol]; | ||
var wrappedProtocol = exports[scheme] = Object.create(nativeProtocol); | ||
|
||
// Executes an HTTP request, following redirects | ||
wrappedProtocol.request = function (options, callback) { | ||
if (typeof options === 'string') { | ||
options = url.parse(options); | ||
options.maxRedirects = exports.maxRedirects; | ||
} else { | ||
options = Object.assign({ | ||
maxRedirects: exports.maxRedirects, | ||
protocol: protocol | ||
}, options); | ||
} | ||
assert.equal(options.protocol, protocol, 'protocol mismatch'); | ||
|
||
return new RedirectableRequest(options, callback); | ||
}; | ||
|
||
// Executes a GET request, following redirects | ||
wrappedProtocol.get = function (options, callback) { | ||
var request = wrappedProtocol.request(options, callback); | ||
request.end(); | ||
return request; | ||
}; | ||
}); |
Oops, something went wrong.
'lmeddoobegbaiopohmpmmobpnpjifpii'