Generering av konfigurationer för nginx, historien om en pull request

VÀlkomna, kamrater. PÄ mina stridsservrar Àr det utmÀrkt nginx som har funnits sedan 2006 och under Ären som jag har administrerat det har jag samlat mÄnga konfigurationer och mallar. Jag har ofta hyllat nginx och av nÄgon anledning hade jag till och med startat en nginx-hub pÄ Habré, gillar att skryta/
Mina vĂ€nner bad mig att sĂ€tta upp en utvecklingsfarm för dem och istĂ€llet för att slĂ€pa med mig mina specifika mallar kom jag ihĂ„g ett intressant projekt nginxconfig.io, som delar ut konfigurationer och förbereder allt för lets encrypt och sĂ„ vidare. SĂ„ jag tĂ€nkte, varför inte? Men jag stördes av det faktum att nginxconfig ber mig att ladda ner en zip-arkiv i webblĂ€saren, utan att lĂ„ta mig ladda ner det direkt pĂ„ servern med wget/fetch/curl. Vad Ă€r det för dumhet, varför behöver jag det i webblĂ€saren, jag behöver det pĂ„ servern frĂ„n kommandoraden. Jag blev irriterad, sĂ„ jag gick in pĂ„ github för att kolla projektets inre, vilket ledde till en fork och dĂ€rmed en pull request. Som jag inte skulle ha skrivit om det inte var intressant 😉

Generering av konfigurationer för nginx, historien om en pull request

SjĂ€lvklart, innan jag började grĂ€va i kĂ€llkoden, kollade jag varifrĂ„n Chromium laddar ner det genererade zip-arkivet med konfigurationerna, och dĂ€r vĂ€ntade en adress som började med "blob:", oops. Det blev redan klart att tjĂ€nsten inte genererar nĂ„got, för faktiskt gör js allt detta. Det Ă€r verkligen sĂ„ att zip-arkivet genereras av klienten, webblĂ€saren, javascript. SĂ„ det fina med projektet nginxconfig.io kan helt enkelt sparas som en html-sida, laddas upp pĂ„ nĂ„gon narod.ru och det kommer att fungera ) Det Ă€r en mycket rolig och intressant lösning, men det Ă€r ocksĂ„ helt opraktiskt för serverinstĂ€llningar, just för det Ă€ndamĂ„l som detta projekt skapades. Att ladda ner det genererade arkivet via webblĂ€saren och sedan föra över det till servern med hjĂ€lp av nc
 Ă„r 2019? Jag satte mig för att hitta ett sĂ€tt att ladda ner den erhĂ„llna konfigurationen direkt till servern.
Efter att ha gjort en fork av projektet började jag tÀnka pÄ vilka alternativ jag har. Utmaningen blev svÄrare eftersom jag inte ville avvika frÄn kravet att projektet skulle förbli en ren front-end, utan nÄgon back-end. SjÀlvklart skulle den enklaste lösningen vara att dra in nodejs och fÄ det att generera arkivet med konfigurationerna enligt direkta lÀnkar.
Det fanns egentligen inte mÄnga alternativ. Snarare kom jag bara pÄ en. Vi mÄste konfigurera konfigurationerna och fÄ en lÀnk som vi kan kopiera till serverns konsol för att fÄ zip-arkivet.
NÄgra textfiler i den mottagna zip-arkivet vÀgde vÀldigt lite, bokstavligen nÄgra kilobyte. En uppenbar lösning var att fÄ en base64-strÀng frÄn den skapade zip-arkivet och klistra in den i urklippet, medan pÄ servern utfördes en kommando i konsolen

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

vi skulle kunna skapa just den zip-filen.

nginxconfig.io skrevs med AngularJS, jag kan inte ens förestÀlla mig hur mÄnga kilometer kod som skulle behövas om författaren inte valt ett reaktivt js-ramverk. Men jag kan tydligt förestÀlla mig hur mycket enklare och vackrare detta skulle kunna implementeras med VueJS, Àven om det Àr ett helt annat Àmne.
I projektets kÀllkod ser vi metoden för att generera zip-arkivet:

$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',
	});
};

det Àr ganska enkelt, med hjÀlp av biblioteket jszip skapas en zip dÀr konfigurationsfiler placeras. Efter att zip-arkivet skapats, matar js det till webblÀsaren med hjÀlp av biblioteket FileSaver.js:

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

dÀr content Àr det erhÄllna blob-objektet för zip-arkivet.

Okej, allt jag behövde göra var att lÀgga till en knapp bredvid och nÀr den trycktes skulle jag inte spara den mottagna zip-arkivet i webblÀsaren, utan fÄ base64-koden frÄn den. Efter lite fixande fick jag 2 metoder istÀllet för en: 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\/, '');
			// i variabeln base64 finns just det zip-arkivet som en base64-strÀng
		}
	});

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

Som ni kanske har mÀrkt har jag flyttat genereringen av sjÀlva zip-arkivet till en privat metod som heter generateZip, och eftersom det Àr AngularJS och författaren sjÀlv hÄller sig till callbacks, valde jag att inte implementera det genom promises. downloadZip gjorde fortfarande saveAs i utdata, medan downloadBase64 gjorde nÄgot lite annat. Vi skapar ett FileReader-objekt som kom till oss i html5 och som Àr ganska Ätkomlig för anvÀndning. Detta objekt Àr, för sin tid, kapabelt att konvertera blob till en base64-strÀng, mer exakt gör det en DataURL-strÀng, men det Àr inte sÄ viktigt för oss, eftersom DataURL innehÄller precis det vi behöver. Bingo, en liten fÀlla vÀntade mig vid försöket att lÀgga allt detta i urklipp. Författaren anvÀnde biblioteken clipboardjs, vilket gör att man kan arbeta med urklipp utan flash-objekt, baserat pÄ den markerade texten. I början beslutade jag mig för att lÀgga min base64 i ett element med display:none;, men i det fallet lyckades jag inte lÀgga det i urklipp, eftersom ingen markering sker. SÄ istÀllet för display:none; gjorde jag

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

, vilket gjorde att jag kunde dölja elementet för ögonen men ÀndÄ behÄlla det pÄ sidan. Voilà, uppgiften Àr slutförd, nÀr jag tryckte pÄ min knapp, placerades strÀngen i urklipp som sÄg ut sÄ hÀr:

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

som jag helt enkelt klistrade in i konsolen pÄ servern och omedelbart fick zip-arkivet med alla konfigurationer.
Och sjÀlvklart skickade jag en pull request till författaren, eftersom projektet Àr aktivt och levande, jag vill se uppdateringar frÄn författaren och ha min knapp ) För den som Àr intresserad, hÀr Àr min fork av projektet och sjÀlvt pull request, dÀr man kan se vad jag har ÄtgÀrdat/lagt till.
Önskar alla en produktiv utveckling )

Generering av konfigurationer för nginx, historien om en pull request

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster