Spaces:
Sleeping
Sleeping
; | |
module.exports = exports; | |
const url = require('url'); | |
const fs = require('fs'); | |
const path = require('path'); | |
module.exports.detect = function(opts, config) { | |
const to = opts.hosted_path; | |
const uri = url.parse(to); | |
config.prefix = (!uri.pathname || uri.pathname === '/') ? '' : uri.pathname.replace('/', ''); | |
if (opts.bucket && opts.region) { | |
config.bucket = opts.bucket; | |
config.region = opts.region; | |
config.endpoint = opts.host; | |
config.s3ForcePathStyle = opts.s3ForcePathStyle; | |
} else { | |
const parts = uri.hostname.split('.s3'); | |
const bucket = parts[0]; | |
if (!bucket) { | |
return; | |
} | |
if (!config.bucket) { | |
config.bucket = bucket; | |
} | |
if (!config.region) { | |
const region = parts[1].slice(1).split('.')[0]; | |
if (region === 'amazonaws') { | |
config.region = 'us-east-1'; | |
} else { | |
config.region = region; | |
} | |
} | |
} | |
}; | |
module.exports.get_s3 = function(config) { | |
if (process.env.node_pre_gyp_mock_s3) { | |
// here we're mocking. node_pre_gyp_mock_s3 is the scratch directory | |
// for the mock code. | |
const AWSMock = require('mock-aws-s3'); | |
const os = require('os'); | |
AWSMock.config.basePath = `${os.tmpdir()}/mock`; | |
const s3 = AWSMock.S3(); | |
// wrapped callback maker. fs calls return code of ENOENT but AWS.S3 returns | |
// NotFound. | |
const wcb = (fn) => (err, ...args) => { | |
if (err && err.code === 'ENOENT') { | |
err.code = 'NotFound'; | |
} | |
return fn(err, ...args); | |
}; | |
return { | |
listObjects(params, callback) { | |
return s3.listObjects(params, wcb(callback)); | |
}, | |
headObject(params, callback) { | |
return s3.headObject(params, wcb(callback)); | |
}, | |
deleteObject(params, callback) { | |
return s3.deleteObject(params, wcb(callback)); | |
}, | |
putObject(params, callback) { | |
return s3.putObject(params, wcb(callback)); | |
} | |
}; | |
} | |
// if not mocking then setup real s3. | |
const AWS = require('aws-sdk'); | |
AWS.config.update(config); | |
const s3 = new AWS.S3(); | |
// need to change if additional options need to be specified. | |
return { | |
listObjects(params, callback) { | |
return s3.listObjects(params, callback); | |
}, | |
headObject(params, callback) { | |
return s3.headObject(params, callback); | |
}, | |
deleteObject(params, callback) { | |
return s3.deleteObject(params, callback); | |
}, | |
putObject(params, callback) { | |
return s3.putObject(params, callback); | |
} | |
}; | |
}; | |
// | |
// function to get the mocking control function. if not mocking it returns a no-op. | |
// | |
// if mocking it sets up the mock http interceptors that use the mocked s3 file system | |
// to fulfill reponses. | |
module.exports.get_mockS3Http = function() { | |
let mock_s3 = false; | |
if (!process.env.node_pre_gyp_mock_s3) { | |
return () => mock_s3; | |
} | |
const nock = require('nock'); | |
// the bucket used for testing, as addressed by https. | |
const host = 'https://mapbox-node-pre-gyp-public-testing-bucket.s3.us-east-1.amazonaws.com'; | |
const mockDir = process.env.node_pre_gyp_mock_s3 + '/mapbox-node-pre-gyp-public-testing-bucket'; | |
// function to setup interceptors. they are "turned off" by setting mock_s3 to false. | |
const mock_http = () => { | |
// eslint-disable-next-line no-unused-vars | |
function get(uri, requestBody) { | |
const filepath = path.join(mockDir, uri.replace('%2B', '+')); | |
try { | |
fs.accessSync(filepath, fs.constants.R_OK); | |
} catch (e) { | |
return [404, 'not found\n']; | |
} | |
// the mock s3 functions just write to disk, so just read from it. | |
return [200, fs.createReadStream(filepath)]; | |
} | |
// eslint-disable-next-line no-unused-vars | |
return nock(host) | |
.persist() | |
.get(() => mock_s3) // mock any uri for s3 when true | |
.reply(get); | |
}; | |
// setup interceptors. they check the mock_s3 flag to determine whether to intercept. | |
mock_http(nock, host, mockDir); | |
// function to turn matching all requests to s3 on/off. | |
const mockS3Http = (action) => { | |
const previous = mock_s3; | |
if (action === 'off') { | |
mock_s3 = false; | |
} else if (action === 'on') { | |
mock_s3 = true; | |
} else if (action !== 'get') { | |
throw new Error(`illegal action for setMockHttp ${action}`); | |
} | |
return previous; | |
}; | |
// call mockS3Http with the argument | |
// - 'on' - turn it on | |
// - 'off' - turn it off (used by fetch.test.js so it doesn't interfere with redirects) | |
// - 'get' - return true or false for 'on' or 'off' | |
return mockS3Http; | |
}; | |