1
0
Fork 0
mirror of https://github.com/openstf/stf synced 2025-10-05 02:29:26 +02:00

Support installation from URLs.

This commit is contained in:
Simo Kinnunen 2014-04-03 22:50:51 +09:00
parent 7c3b180f8d
commit 97a042a54d
4 changed files with 132 additions and 65 deletions

View file

@ -427,10 +427,15 @@ program
, 'public ip for global access' , 'public ip for global access'
, String , String
, ip()) , ip())
.option('--save-dir <dir>'
, 'where to save files'
, String
, os.tmpdir())
.action(function(options) { .action(function(options) {
require('./roles/storage/temp')({ require('./roles/storage/temp')({
port: options.port port: options.port
, publicIp: options.publicIp , publicIp: options.publicIp
, saveDir: options.saveDir
}) })
}) })

View file

@ -64,6 +64,20 @@ module.exports = function(options) {
secret: options.secret secret: options.secret
, authUrl: options.authUrl , authUrl: options.authUrl
})) }))
// Proxied requests must come before any body parsers
app.post('/api/v1/resources', function(req, res) {
proxy.web(req, res, {
target: options.storageUrl
})
})
app.get('/api/v1/resources/:id', function(req, res) {
proxy.web(req, res, {
target: options.storageUrl
})
})
app.use(express.json()) app.use(express.json())
app.use(express.urlencoded()) app.use(express.urlencoded())
app.use(express.csrf()) app.use(express.csrf())
@ -187,18 +201,6 @@ module.exports = function(options) {
}) })
}) })
app.post('/api/v1/resources', function(req, res) {
proxy.web(req, res, {
target: options.storageUrl
})
})
app.get('/api/v1/resources/:id', function(req, res) {
proxy.web(req, res, {
target: options.storageUrl
})
})
io.set('authorization', (function() { io.set('authorization', (function() {
var parse = Promise.promisify(express.cookieParser(options.secret)) var parse = Promise.promisify(express.cookieParser(options.secret))
return function(handshake, accept) { return function(handshake, accept) {

View file

@ -1,12 +1,16 @@
var http = require('http') var http = require('http')
var util = require('util') var util = require('util')
var fs = require('fs')
var express = require('express') var express = require('express')
var formidable = require('formidable') var formidable = require('formidable')
var Promise = require('bluebird') var Promise = require('bluebird')
var ApkReader = require('adbkit-apkreader') var ApkReader = require('adbkit-apkreader')
var request = require('request')
var temp = require('temp')
var logger = require('../../util/logger') var logger = require('../../util/logger')
var requtil = require('../../util/requtil')
var Storage = require('../../util/storage') var Storage = require('../../util/storage')
module.exports = function(options) { module.exports = function(options) {
@ -19,45 +23,85 @@ module.exports = function(options) {
app.set('case sensitive routing', true) app.set('case sensitive routing', true)
app.set('trust proxy', true) app.set('trust proxy', true)
app.use(express.json())
app.use(express.urlencoded())
storage.on('timeout', function(id) { storage.on('timeout', function(id) {
log.info('Cleaning up inactive resource "%s"', id) log.info('Cleaning up inactive resource "%s"', id)
}) })
app.post('/api/v1/resources', function(req, res) { function process(file) {
var form = Promise.promisifyAll(new formidable.IncomingForm()) log.info('Processing "%s"', file.path)
form.parseAsync(req)
.spread(function(fields, files) { var reader = ApkReader.readFile(file.path)
if (files.file) {
try {
var reader = ApkReader.readFile(files.file.path)
var manifest = reader.readManifestSync() var manifest = reader.readManifestSync()
var id = storage.store(files.file) var id = storage.store(file)
res.json(201, {
success: true return {
, url: util.format( url: util.format(
'http://%s:%s/api/v1/resources/%s' 'http://%s:%s/api/v1/resources/%s'
, options.publicIp , options.publicIp
, options.port , options.port
, id , id
) )
, manifest: manifest , manifest: manifest
}
}
function download(url) {
var resolver = Promise.defer()
var path = temp.path({
dir: options.saveDir
}) })
log.info('Downloading "%s" to "%s"', url, path)
function errorListener(err) {
resolver.reject(err)
}
function closeListener() {
resolver.resolve({
path: path
})
}
try {
var dl = request(url)
.pipe(fs.createWriteStream(path))
.on('error', errorListener)
.on('close', closeListener)
} }
catch (err) { catch (err) {
log.error('ApkReader had an error', err.stack) resolver.reject(err)
res.json(500, { }
success: false
return resolver.promise.finally(function() {
dl.removeListener('error', errorListener)
dl.removeListener('end', closeListener)
}) })
} }
app.post('/api/v1/resources', function(req, res) {
var form = Promise.promisifyAll(new formidable.IncomingForm())
form.parseAsync(req)
.spread(function(fields, files) {
if (files.file) {
return process(files.file)
}
else if (fields.url) {
return download(fields.url).then(process)
} }
else { else {
throw new requtil.ValidationError('"file" or "url" is required')
}
})
.then(function(data) {
data.success = true
res.json(201, data)
})
.catch(requtil.ValidationError, function() {
res.json(400, { res.json(400, {
success: false success: false
, error: 'ValidationError'
}) })
}
}) })
.catch(function(err) { .catch(function(err) {
log.error('Failed to save resource: ', err.stack) log.error('Failed to save resource: ', err.stack)

View file

@ -1,6 +1,7 @@
module.exports = function ControlServiceFactory( module.exports = function ControlServiceFactory(
$rootScope $rootScope
, $upload , $upload
, $http
, socket , socket
, TransactionService , TransactionService
) { ) {
@ -108,35 +109,50 @@ module.exports = function ControlServiceFactory(
return tx return tx
} }
function install(options) {
var app = options.manifest.application
var tx = TransactionService.create(target)
var params = {
url: options.url
}
if (app.launcherActivities.length) {
var activity = app.launcherActivities[0]
params.launchActivity = {
action: 'android.intent.action.MAIN'
, component: options.manifest.package + '/' + activity.name
, category: ['android.intent.category.LAUNCHER']
, flags: 0x10200000
}
}
socket.emit('device.install', channel, tx.channel, params)
tx.manifest = options.manifest
return tx
}
this.install = function(files) { this.install = function(files) {
if (typeof files === 'string') {
return $http({
url: '/api/v1/resources'
, method: 'POST'
, data: {
url: files
}
})
.then(function(response) {
return install(response.data)
})
}
else {
return $upload.upload({ return $upload.upload({
url: '/api/v1/resources' url: '/api/v1/resources'
, method: 'POST' , method: 'POST'
, file: files[0] , file: files[0]
}) })
.then(function(response) { .then(function(response) {
var manifest = response.data.manifest return install(response.data)
var app = manifest.application
var tx = TransactionService.create(target)
console.log('resp',response)
console.log(manifest)
var params = {
url: response.data.url
}
if (app.launcherActivities.length) {
var activity = app.launcherActivities[0]
params.launchActivity = {
action: 'android.intent.action.MAIN'
, component: manifest.package + '/' + activity.name
, category: ['android.intent.category.LAUNCHER']
, flags: 0x10200000
}
}
socket.emit('device.install', channel, tx.channel, params)
tx.manifest = manifest
return tx
}) })
} }
}
this.uninstall = function(pkg) { this.uninstall = function(pkg) {
var tx = TransactionService.create(target) var tx = TransactionService.create(target)