Proxy requests.
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
{stringify: $formatQueryString} = require 'querystring'
|
||||
|
||||
$findWhere = require 'lodash.find'
|
||||
$forEach = require 'lodash.foreach'
|
||||
$isArray = require 'lodash.isarray'
|
||||
@@ -691,7 +689,6 @@ exports.revert.params = {
|
||||
id: { type: 'string' }
|
||||
}
|
||||
|
||||
# export a VM
|
||||
exports.export = ({id, compress}) ->
|
||||
compress ?= true
|
||||
try
|
||||
@@ -700,7 +697,7 @@ exports.export = ({id, compress}) ->
|
||||
@throw 'NO_SUCH_OBJECT'
|
||||
|
||||
host = @getObject VM.$container
|
||||
do (type = host.type) ->
|
||||
do (type = host.type) =>
|
||||
if type is 'pool'
|
||||
host = @getObject host.master, 'host'
|
||||
else unless type is 'host'
|
||||
@@ -708,43 +705,48 @@ exports.export = ({id, compress}) ->
|
||||
|
||||
{sessionId} = @getXAPI host
|
||||
|
||||
return @registerProxyRequest {
|
||||
url = $wait @registerProxyRequest {
|
||||
method: 'get'
|
||||
hostname: host.address
|
||||
path: '/export/?' + $formatQueryString {
|
||||
pathname: '/export/'
|
||||
query: {
|
||||
session_id: sessionId
|
||||
ref: VM.ref
|
||||
use_compression: if compress then 'true' else false
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
$getFrom: url
|
||||
}
|
||||
exports.export.permission = 'admin'
|
||||
exports.export.params = {
|
||||
id: { type: 'string' }
|
||||
compress: { type: 'boolean', optional: true }
|
||||
}
|
||||
|
||||
# import a VM
|
||||
exports.import = ({id, file}) ->
|
||||
# FIXME
|
||||
exports.import = ({host}) ->
|
||||
try
|
||||
VM = @getObject id, 'VM'
|
||||
host = @getObject host, 'host'
|
||||
catch
|
||||
@throw 'NO_SUCH_OBJECT'
|
||||
|
||||
host = @getObject VM.$container
|
||||
do (type = host.type) ->
|
||||
if type is 'pool'
|
||||
host = @getObject host.master, 'host'
|
||||
else unless type is 'host'
|
||||
throw new Error "unexpected type: got #{type} instead of host"
|
||||
|
||||
{sessionId} = @getXAPI host
|
||||
|
||||
return @registerProxyRequest {
|
||||
url = $wait @registerProxyRequest {
|
||||
method: 'post'
|
||||
hostname: host.address
|
||||
path: '/import/' + $formatQueryString session_id: sessionId
|
||||
pathname: '/import/'
|
||||
query: {
|
||||
session_id: sessionId
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
$sendTo: url
|
||||
}
|
||||
exports.import.permission = 'admin'
|
||||
exports.import.params = {
|
||||
id: { type: 'string' }
|
||||
host: { type: 'string' }
|
||||
}
|
||||
|
||||
100
src/proxy-request.js
Normal file
100
src/proxy-request.js
Normal file
@@ -0,0 +1,100 @@
|
||||
'use strict';
|
||||
|
||||
//====================================================================
|
||||
|
||||
var formatQueryString = require('querystring').stringify;
|
||||
var httpRequest = require('http').request;
|
||||
var httpsRequest = require('https').request;
|
||||
var parseUrl = require('url').parse;
|
||||
|
||||
var assign = require('lodash.assign');
|
||||
var debug = require('debug')('xo:proxyRequest');
|
||||
var forEach = require('lodash.foreach');
|
||||
var isString = require('lodash.isstring');
|
||||
|
||||
//====================================================================
|
||||
|
||||
var DEFAULTS = {
|
||||
method: 'GET',
|
||||
};
|
||||
|
||||
var HTTP_RE = /^http(s?):?$/;
|
||||
|
||||
//====================================================================
|
||||
|
||||
function proxyRequest(opts, upReq, upRes) {
|
||||
if (isString(opts)) {
|
||||
debug('parsing URL %s', opts);
|
||||
|
||||
opts = parseUrl(opts);
|
||||
}
|
||||
|
||||
// Merges options with defaults.
|
||||
opts = assign({}, DEFAULTS, opts);
|
||||
|
||||
opts.headers = assign({},
|
||||
DEFAULTS.headers,
|
||||
upReq.headers,
|
||||
{
|
||||
connection: 'close',
|
||||
host: opts.hostname || opts.host,
|
||||
},
|
||||
opts.headers
|
||||
);
|
||||
|
||||
// `http(s).request()` does not understand pathname, query and
|
||||
// search.
|
||||
if (!opts.path) {
|
||||
var path = opts.pathname || '/';
|
||||
var query;
|
||||
|
||||
if (opts.search) {
|
||||
path += opts.search;
|
||||
} else if ((query = opts.query)) {
|
||||
if (!isString(query)) {
|
||||
query = formatQueryString(query);
|
||||
}
|
||||
|
||||
path += '?' + query;
|
||||
}
|
||||
|
||||
opts.path = path;
|
||||
}
|
||||
|
||||
var matches;
|
||||
var isSecure = !!(
|
||||
opts.protocol &&
|
||||
(matches = opts.protocol.match(HTTP_RE)) &&
|
||||
matches[1]
|
||||
);
|
||||
delete opts.protocol;
|
||||
|
||||
debug('proxying HTTP%s request', isSecure ? 's' : '');
|
||||
|
||||
var request = isSecure ? httpsRequest : httpRequest;
|
||||
|
||||
var downReq = request(opts, function onResponse(downRes) {
|
||||
debug('response received');
|
||||
|
||||
forEach(downRes.headers, function forwardResponseHeaderUp(value, name) {
|
||||
upRes.setHeader(name, value);
|
||||
});
|
||||
|
||||
downRes.pipe(upRes);
|
||||
|
||||
downRes.on('error', function forwardResponseErrorUp(error) {
|
||||
upRes.emit('error', error);
|
||||
});
|
||||
});
|
||||
upReq.pipe(downReq);
|
||||
|
||||
downReq.on('error', function forwardRequestErrorUp(error) {
|
||||
upReq.emit('error', error);
|
||||
});
|
||||
|
||||
upReq.on('close', function forwardRequestAbortionDown() {
|
||||
downReq.abort();
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = proxyRequest;
|
||||
@@ -1,4 +1,5 @@
|
||||
{EventEmitter: $EventEmitter} = require 'events'
|
||||
{format: $formatUrl, parse: $parseUrl} = require 'url'
|
||||
|
||||
$Bluebird = require 'bluebird'
|
||||
$debug = (require 'debug') 'xo:xo'
|
||||
@@ -16,6 +17,7 @@ $Promise = require 'bluebird'
|
||||
|
||||
$Connection = require './connection'
|
||||
$Model = require './model'
|
||||
$proxyRequest = require './proxy-request'
|
||||
$RedisCollection = require './collection/redis'
|
||||
$spec = require './spec'
|
||||
$XAPI = require './xapi'
|
||||
@@ -408,27 +410,29 @@ class $XO extends $EventEmitter
|
||||
|
||||
return connection
|
||||
|
||||
registerProxyRequest: (opts) ->
|
||||
registerProxyRequest: $coroutine (opts) ->
|
||||
url = "/#{$wait $generateToken()}"
|
||||
|
||||
protocol = opts.protocol ? 'http'
|
||||
if $isString opts
|
||||
opts = $parseUrl opts
|
||||
opts.method = if opts.method?
|
||||
opts.method.toUpperCase()
|
||||
else
|
||||
'GET'
|
||||
opts.createdAt = Date.now()
|
||||
|
||||
@_proxyRequests[url] =
|
||||
host: opts.host
|
||||
method: opts.method ? 'get'
|
||||
port: opts.port ? if protocol is 'https' then 443 else 80
|
||||
protocol: protocol
|
||||
@_proxyRequests[url] = opts
|
||||
|
||||
return url
|
||||
|
||||
handleProxyRequest: (req, res, next) ->
|
||||
unless req.method is 'get' and (request = @_proxyRequests[req.url])
|
||||
unless (
|
||||
(request = @_proxyRequests[req.url]) and
|
||||
req.method is request.method
|
||||
)
|
||||
return next()
|
||||
|
||||
console.log request
|
||||
next()
|
||||
|
||||
# TODO
|
||||
$proxyRequest request, req, res
|
||||
|
||||
return
|
||||
|
||||
|
||||
Reference in New Issue
Block a user