Genereren van configuraties voor nginx, geschiedenis van één pull-verzoek

Gegroet, kameraden. Prachtig op mijn gevechtsservers nginx draait sinds 2006 en in de loop van de jaren dat ik het beheerde, heb ik veel configuraties en sjablonen verzameld. Ik prees nginx veel en op de een of andere manier bleek dat ik zelfs een nginx-hub op de hub begon, pronk met m/
Vrienden vroegen me om een ​​ontwikkelingsboerderij voor hen op te zetten, en in plaats van ze mijn specifieke sjablonen te slepen, herinnerde ik me een interessant project nginxconfig.io, dat configuraties in de schappen verspreidt en alles voorbereidt op let-encryptie, enz. Ik dacht: waarom niet? Ik was echter woedend over het feit dat nginxconfig mij aanbiedt het zip-archief naar de browser te downloaden, zonder dat ik het rechtstreeks naar de server kan uploaden met wget/fetch/curl. Wat een onzin, waarom heb ik het in de browser nodig, ik heb het op de server nodig vanaf de console. Boos ging ik naar github om de kern van het project te zien, wat leidde tot de fork en, als resultaat, een pull-verzoek. Waar ik niet over zou schrijven als het niet interessant was 😉

Genereren van configuraties voor nginx, geschiedenis van één pull-verzoek

Voordat ik in de bronnen ging graven, keek ik natuurlijk naar waar Chrome het gegenereerde zip-archief met configuraties ophaalt, en daar wachtte een adres dat begint met "blob:" op mij, oeps. Het is al duidelijk geworden dat de dienst onderweg niets genereert, sterker nog, het wordt allemaal gedaan door js. Het zip-archief wordt inderdaad gegenereerd door de client, browser en javascript zelf. Die. het mooie is dat het project nginxconfig.io kan eenvoudig worden opgeslagen als een HTML-pagina en naar sommige worden geüpload narod.ru en het zal werken) Dit is een erg grappige en interessante oplossing, maar het is vreselijk lastig voor het opzetten van servers, sterker nog, precies waarvoor dit project is gemaakt. Het gegenereerde archief downloaden met een browser en vervolgens overbrengen naar de server met behulp van nc... in 2019? Ik stelde mezelf de taak een manier te vinden om de resulterende configuratie rechtstreeks naar de server te downloaden.
Nadat ik het project had afgerond, begon ik na te denken over wat mijn opties waren. De opgave werd bemoeilijkt door het feit dat ik niet wilde afwijken van de voorwaarde dat het project een pure front-end moest blijven, zonder enige back-end. De eenvoudigste oplossing zou natuurlijk zijn om nodejs op te halen en deze te dwingen een archief met configuraties te genereren met behulp van directe links.
Eigenlijk waren er niet veel opties. Om precies te zijn, er kwam er maar één in me op. We moeten de configuraties instellen en een link krijgen die we naar de serverconsole kunnen kopiëren om een ​​zip-archief te krijgen.
Verschillende tekstbestanden in het resulterende zip-archief wogen nogal wat, letterlijk een paar kilobytes. De voor de hand liggende oplossing was om de base64-string uit het gegenereerde zip-archief te halen en deze in de buffer te gooien, terwijl hij op de server was met de opdracht in de console

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

we zouden hetzelfde zipbestand kunnen maken.

nginxconfig.io is geschreven in AngularJS, ik kan me niet eens voorstellen welke kilometers code er nodig zouden zijn geweest als de auteur niet voor een reactief js-framework had gekozen. Maar ik kan me perfect voorstellen hoeveel eenvoudiger en mooier dit allemaal in VueJS geïmplementeerd zou kunnen worden, hoewel dit een heel ander onderwerp is.
In de projectbronnen zien we een methode voor het genereren van een zip-archief:

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

alles is vrij eenvoudig, met behulp van de bibliotheek jszip Er wordt een zip gemaakt waar de configuratiebestanden worden geplaatst. Nadat het zip-archief is gemaakt, stuurt js het naar de browser met behulp van de bibliotheek FileSaver.js:

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

waarbij inhoud het resulterende blobobject van het zip-archief is.

Oké, het enige dat ik hoefde te doen was er nog een knop naast toevoegen en toen ik erop klikte, zou ik het resulterende zip-archief niet in de browser opslaan, maar de base64-code eruit halen. Na een beetje rommelen, kreeg ik 2 methoden, in plaats van slechts één 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',
	});
};

Zoals je misschien hebt gemerkt, heb ik het genereren van het zip-archief zelf verplaatst naar de privé-genereZip-methode, enzovoort. Dit is AngularJS, en de auteur houdt zich zelf aan callbacks en heeft dit niet via beloften geïmplementeerd. downloadZip deed nog steeds saveAs als uitvoer, terwijl downloadBase64 iets anders deed. We maken een FileReader-object dat in html5 naar ons toekwam en al behoorlijk is доступный voor gebruik. Die in één keer een base64-string kan maken van een blob, of beter gezegd, het maakt een DataURL-string, maar dit is niet zo belangrijk voor ons, omdat DataURL bevat precies wat we nodig hebben. Bingo, er wachtte me een klein probleempje toen ik dit allemaal in de buffer probeerde te stoppen. De auteur gebruikte de bibliotheek in het project klembordjs, waarmee u zonder Flash-objecten met het klembord kunt werken, op basis van de geselecteerde tekst. Aanvankelijk besloot ik mijn base64 in een element met display:none; te plaatsen, maar in dit geval kon ik het niet op het klembord plaatsen omdat er vindt geen scheiding plaats. Daarom, in plaats van display:none; ik deed

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

waardoor ik het element zowel aan het zicht kon onttrekken als het daadwerkelijk op de pagina kon laten staan. Voila, de taak was voltooid, toen ik op mijn knop klikte, werd een regel als deze in de buffer geplaatst:

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

die ik eenvoudigweg in de console op de server plakte en onmiddellijk een zip-archief ontving met alle configuraties.
En natuurlijk heb ik een pull-request naar de auteur gestuurd, omdat... het project is actief en levendig, ik zou graag updates van de auteur willen zien en mijn eigen knop hebben) Voor degenen die geïnteresseerd zijn, hier is het mijn vork project en mijzelf pull verzoek, waar je kunt zien wat ik heb gecorrigeerd/toegevoegd.
Fijne ontwikkeling allemaal)

Genereren van configuraties voor nginx, geschiedenis van één pull-verzoek

Bron: www.habr.com

Voeg een reactie