Xeración de configuracións para nginx, historial dunha solicitude de extracción

Saúdos, compañeiros. Fermoso nos meus servidores de combate Nginx leva funcionando desde 2006 e ao longo dos anos da súa administración acumulei moitas configuracións e modelos. Eloxioi moito a nginx e, dalgunha maneira, resultou que incluso iniciei un hub nginx no hub, mostrar m/
Os amigos pedíronme que lles fixera unha granxa de desenvolvemento e, en lugar de arrastralos os meus modelos específicos, lembreime dun proxecto interesante. nginxconfig.io, que espalla as configuracións nos andeis e prepara todo para lets encrypt, etc. Pensei, por que non? Non obstante, enfureceume o feito de que nginxconfig me ofreza descargar o arquivo zip no navegador, sen permitirme cargalo directamente no servidor usando wget/fetch/curl. Que tonterías, por que o necesito no navegador, necesito no servidor dende a consola. Enfadado, fun a github para ver as entrañas do proxecto, o que levou á súa bifurcación e, como resultado, a unha solicitude de extracción. Sobre o que non escribiría se non fose interesante 😉

Xeración de configuracións para nginx, historial dunha solicitude de extracción

Por suposto, antes de investigar nas fontes, observei onde Chrome tira o arquivo zip xerado con configuracións, e alí estaba agardando por min un enderezo que comezaba por "blob:". Xa quedou claro que o servizo non xera nada ao longo do camiño, de feito, todo está feito por js. De feito, o arquivo zip é xerado polo cliente, o navegador e o propio javascript. Eses. o fermoso é que o proxecto nginxconfig.io pódese gardar simplemente como unha páxina html, cargada nalgúns narod.ru e funcionará) Esta é unha solución moi divertida e interesante, con todo, é terriblemente inconveniente para configurar servidores, de feito, exactamente para o que se creou este proxecto. Descarga o arquivo xerado cun navegador e despois transfirao ao servidor usando nc... en 2019? Púxenme a tarefa de atopar unha forma de descargar a configuración resultante directamente no servidor.
Despois de facer o proxecto, comecei a pensar cales eran as miñas opcións. A tarefa complicouse polo feito de que non quería desviarme da condición de que o proxecto debía seguir sendo un front-end puro, sen ningún back-end. Por suposto, a solución máis sinxela sería sacar nodejs e obrigalo a xerar un arquivo con configuracións usando ligazóns directas.
En realidade, non había moitas opcións. Máis precisamente, só se me ocorreu un. Necesitamos configurar as configuracións e obter unha ligazón que podemos copiar na consola do servidor para obter un arquivo zip.
Varios ficheiros de texto do arquivo zip resultante pesaban bastante, literalmente uns poucos kilobytes. A solución obvia era obter a cadea base64 do arquivo zip xerado e botala no búfer, mentres estaba no servidor co comando na consola.

echo 'base64string' | base64 --decode > config.zip

poderiamos crear este mesmo ficheiro zip.

nginxconfig.io foi escrito en AngularJS, nin sequera podo imaxinar que quilómetros de código serían necesarios se o autor non escolle un framework js reactivo. Pero podo imaxinar perfectamente o máis sinxelo e fermoso que todo isto podería implementarse en VueJS, aínda que este é un tema completamente diferente.
Nos recursos do proxecto vemos un método para xerar un arquivo zip:

$scope.downloadZip = function() {
	var zip = new JSZip();

	var sourceCodes = $window.document.querySelectorAll('main .file .code.source');

	for (var i = 0; i < sourceCodes.length; i++) {
		var sourceCode = sourceCodes[i];

		var name	= sourceCode.dataset.filename;
		var content	= sourceCode.children[0].children[0].innerText;

		if (!$scope.isSymlink() && name.match(/^sites-available//)) {
			name = name.replace(/^sites-available//, 'sites-enabled/');
		}

		zip.file(name, content);

		if (name.match(/^sites-available//)) {
			zip.file(name.replace(/^sites-available//, 'sites-enabled/'), '../' + name, {
				unixPermissions: parseInt('120755', 8),
			});
		}
	}

	zip.generateAsync({
		type: 'blob',
		platform: 'UNIX',
	}).then(function(content) {
		saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
	});

	gtag('event', $scope.getDomains().join(','), {
		event_category: 'download_zip',
	});
};

todo é bastante sinxelo, usando a biblioteca jszip Créase un zip onde se colocan os ficheiros de configuración. Despois de crear o arquivo zip, js envíao ao navegador mediante a biblioteca FileSaver.js:

saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');

onde o contido é o obxecto blob resultante do arquivo zip.

Ok, o único que tiña que facer era engadir outro botón ao seu carón e, ao facer clic nel, non gardaba o arquivo zip resultante no navegador, senón que conseguiría o código base64 del. Despois de xogar un pouco, conseguín 2 métodos, en lugar de só un downloadZip:

$scope.downloadZip = function() {
	generateZip(function (content) {
		saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
	});

	gtag('event', $scope.getDomains().join(','), {
		event_category: 'download_zip',
	});
};
$scope.downloadBase64 = function() {
	generateZip(function (content) {
		var reader = new FileReader();
		reader.readAsDataURL(content);
		reader.onloadend = function() {
			var base64 = reader.result.replace(/^data:.+;base64,/, '');
			// в переменной base64 как раз нужный мне zip архив в виде base64 строки
		}
	});

	gtag('event', $scope.getDomains().join(','), {
		event_category: 'download_base64',
	});
};

Como podedes ter notado, pasei a xeración do propio arquivo zip ao método privado generateZip, etc. Este é AngularJS, e o propio autor segue coas devolucións de chamada e non o implementou mediante promesas. downloadZip aínda gardou como saída, mentres que downloadBase64 fixo algo lixeiramente diferente. Creamos un obxecto FileReader que nos chegou en html5 e que xa está bastante accesible para o seu uso. O que, nun momento, pode facer unha cadea base64 a partir dun blob, ou mellor dito, fai unha cadea DataURL, pero isto non é tan importante para nós, porque DataURL contén exactamente o que necesitamos. Bingo, agardábame un pequeno inconveniente cando tentei poñer todo isto no buffer. O autor utilizou a biblioteca no proxecto portapapeisjs, que permite traballar co portapapeis sen obxectos flash, en función do texto seleccionado. Inicialmente, decidín poñer o meu base64 nun elemento con display:none;, pero neste caso non puiden poñelo no portapapeis porque non se produce ningunha separación. Polo tanto, no canto de mostrar:none; fixen

position: absolute;
z-index: -1;
opacity: 0;

o que me permitiu ocultar o elemento á vista e deixalo na páxina. Voila, a tarefa foi completada, cando premei no meu botón, unha liña como esta foi colocada no búfer:

echo 'base64string' | base64 --decode > config.zip

que simplemente peguei na consola do servidor e inmediatamente recibín un arquivo zip con todas as configuracións.
E, por suposto, enviei un pull request ao autor, porque... o proxecto é activo e animado, gustaríame ver actualizacións do autor e ter o meu propio botón) Para os interesados, aquí está o meu garfo proxecto e el mesmo solicitude de tracción, onde podes ver o que corrixín/engadín.
Feliz desenvolvemento para todos)

Xeración de configuracións para nginx, historial dunha solicitude de extracción

Fonte: www.habr.com

Engadir un comentario