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
						
					
					
				| '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;
 | |
| };
 | |
| 
 | |
| 
 | |
| 
 |