You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					164 lines
				
				4.5 KiB
			
		
		
			
		
	
	
					164 lines
				
				4.5 KiB
			| 
											3 years ago
										 | 'use strict'; | ||
|  | 
 | ||
|  | 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; | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | 
 |