Geração de configurações para nginx, histórico de uma solicitação pull

Saudações, camaradas. Linda em meus servidores de combate nginx está em funcionamento desde 2006 e ao longo dos anos de sua administração acumulei muitas configurações e templates. Eu elogiei muito o nginx e de alguma forma descobri que até comecei um hub nginx no hub também, mostre m/
Amigos me pediram para montar um farm de desenvolvimento para eles e, em vez de arrastar meus modelos específicos para eles, lembrei-me de um projeto interessante nginxconfig.io, que espalha configurações nas prateleiras e prepara tudo para permitir a criptografia, etc. Eu pensei, por que não? No entanto, fiquei furioso com o fato de o nginxconfig me oferecer o download de um arquivo zip no navegador, sem permitir que eu o carregasse diretamente para o servidor usando wget/fetch/curl. Que bobagem, por que preciso disso no navegador, preciso no servidor do console. Irritado, fui ao github para ver a essência do projeto, o que levou ao seu fork e, como resultado, a um pull request. Sobre o qual eu não escreveria se não fosse interessante 😉

Geração de configurações para nginx, histórico de uma solicitação pull

Claro, antes de me aprofundar nas fontes, olhei para onde o Chrome extrai o arquivo zip gerado com configurações, e lá um endereço começando com “blob:” estava esperando por mim, opa. Já ficou claro que o serviço não gera nada no caminho, na verdade, é tudo feito por js. Na verdade, o arquivo zip é gerado pelo cliente, pelo navegador e pelo próprio javascript. Aqueles. a beleza é que o projeto nginxconfig.io pode ser simplesmente salvo como uma página HTML, carregado em algum narod.ru e vai funcionar) Esta é uma solução muito engraçada e interessante, porém, é terrivelmente inconveniente para configurar servidores, aliás, exatamente para o que este projeto foi criado. Baixe o arquivo gerado com um navegador e depois transfira-o para o servidor usando nc... em 2019? Eu me propus a encontrar uma maneira de baixar a configuração resultante diretamente para o servidor.
Depois de bifurcar o projeto, comecei a pensar quais eram minhas opções. A tarefa foi complicada pelo fato de eu não querer me desviar da condição de que o projeto permanecesse um front-end puro, sem nenhum back-end. Claro, a solução mais simples seria puxar o nodejs e forçá-lo a gerar um arquivo com configurações usando links diretos.
Na verdade, não havia muitas opções. Mais precisamente, apenas um me veio à mente. Precisamos definir as configurações e obter um link que possamos copiar para o console do servidor para obter um arquivo zip.
Vários arquivos de texto no arquivo zip resultante pesavam bastante, literalmente alguns kilobytes. A solução óbvia era obter a string base64 do arquivo zip gerado e jogá-la no buffer, enquanto estava no servidor com o comando no console

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

poderíamos criar esse mesmo arquivo zip.

nginxconfig.io foi escrito em AngularJS, não consigo nem imaginar quantos quilômetros de código seriam necessários se o autor não tivesse escolhido uma estrutura js reativa. Mas posso imaginar perfeitamente o quão mais simples e bonito tudo isso poderia ser implementado no VueJS, embora este seja um tópico completamente diferente.
Nos recursos do projeto vemos um método para gerar um 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',
	});
};

tudo é bem simples, usando a biblioteca jszip Um zip é criado onde os arquivos de configuração são colocados. Depois de criar o arquivo zip, js o alimenta no navegador usando a biblioteca ArquivoSaver.js:

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

onde content é o objeto blob resultante do arquivo zip.

Ok, tudo o que precisei fazer foi adicionar outro botão próximo a ele e, ao clicar nele, não salvaria o arquivo zip resultante no navegador, mas obteria o código base64 dele. Depois de mexer um pouco, consegui 2 métodos, em vez de apenas um 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 você deve ter notado, mudei a geração do próprio arquivo zip para o método generateZip privado e assim por diante. Este é o AngularJS, e o próprio autor se limita aos retornos de chamada e não os implementou por meio de promessas. downloadZip ainda salvou como saída, enquanto downloadBase64 fez algo um pouco diferente. Criamos um objeto FileReader que chegou até nós em html5 e já é bastante acessível para uso. Que, ao mesmo tempo, pode fazer uma string base64 a partir de um blob, ou melhor, faz uma string DataURL, mas isso não é tão importante para nós, porque DataURL contém exatamente o que precisamos. Bingo, um pequeno problema me esperava quando tentei colocar tudo isso no buffer. O autor usou a biblioteca no projeto pranchetajs, que permite trabalhar com a área de transferência sem objetos flash, com base no texto selecionado. Inicialmente, decidi colocar minha base64 em um elemento com display:none;, mas neste caso não consegui colocar na área de transferência porque nenhuma separação ocorre. Portanto, em vez de display:none; Eu fiz

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

o que me permitiu ocultar o elemento da visualização e deixá-lo na página. Voila, a tarefa foi concluída, quando cliquei no meu botão, uma linha como esta foi colocada no buffer:

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

que simplesmente colei no console do servidor e recebi imediatamente um arquivo zip com todas as configurações.
E, claro, enviei um pull request ao autor, porque... o projeto está ativo e animado, gostaria de ver atualizações do autor e ter meu próprio botão) Para os interessados, aqui está meu garfo projeto e ele mesmo solicitação de recebimento, onde você pode ver o que corrigi/adicionei.
Feliz desenvolvimento a todos)

Geração de configurações para nginx, histórico de uma solicitação pull

Fonte: habr.com

Adicionar um comentário