Generovanie konfigurácií pre nginx, história jednej žiadosti o stiahnutie

Zdravím vás súdruhovia. Krásne na mojich bojových serveroch nginx beží od roku 2006 a za roky jeho správy sa mi nahromadilo množstvo konfigurácií a šablón. Veľmi som chválil nginx a nejako to dopadlo tak, že som na náboji dokonca založil aj nginx hub, pochváľte sa m/
Priatelia ma požiadali, aby som im zriadil vývojovú farmu, a namiesto toho, aby som im pretiahol svoje konkrétne šablóny, spomenul som si na zaujímavý projekt nginxconfig.io, ktorý rozhádže konfigurácie po regáloch a pripraví všetko na lets encrypt atď. Pomyslel som si, prečo nie? Bol som však rozhorčený skutočnosťou, že nginxconfig mi ponúka stiahnutie archívu zip do prehliadača bez toho, aby som ho mohol nahrať priamo na server pomocou wget/fetch/curl. Aký nezmysel, prečo to potrebujem v prehliadači, potrebujem to na serveri z konzoly. Nahnevaný som išiel na github, aby som si prezrel črevá projektu, čo viedlo k jeho forku a v dôsledku toho k žiadosti o stiahnutie. O čom by som nepísala, keby to nebolo zaujímavé 😉

Generovanie konfigurácií pre nginx, história jednej žiadosti o stiahnutie

Samozrejme, pred hrabaním v zdrojoch som sa pozrel, odkiaľ Chrome sťahuje vygenerovaný zip archív s konfiguráciami a tam ma čakala adresa začínajúca na „blob:“, ups. Už sa ukázalo, že služba počas cesty nič negeneruje, v skutočnosti to všetko robí js. Archív zip generuje samotný klient, prehliadač a javascript. Tie. krása je v tom projekte nginxconfig.io možno jednoducho uložiť ako html stránku, nahrať na niektoré narod.ru a bude to fungovať) Toto je veľmi vtipné a zaujímavé riešenie, ale je strašne nepohodlné na nastavenie serverov, v skutočnosti presne na to, na čo bol tento projekt vytvorený. Stiahnite si vygenerovaný archív pomocou prehliadača a potom ho preneste na server pomocou nc... v roku 2019? Dal som si za úlohu nájsť spôsob, ako stiahnuť výslednú konfiguráciu priamo na server.
Po forlingu projektu som začal rozmýšľať, aké mám možnosti. Úlohu komplikoval fakt, že som nechcel vybočiť z podmienky, že projekt má zostať čistým front-endom, bez akéhokoľvek back-endu. Samozrejme, najjednoduchším riešením by bolo stiahnuť nodejs a prinútiť ho vygenerovať archív s konfiguráciami pomocou priamych odkazov.
V skutočnosti nebolo veľa možností. Presnejšie, do úvahy prišiel len jeden. Musíme nastaviť konfigurácie a získať odkaz, ktorý môžeme skopírovať do konzoly servera, aby sme získali archív zip.
Niekoľko textových súborov vo výslednom zip archíve vážilo pomerne dosť, doslova niekoľko kilobajtov. Samozrejmým riešením bolo získať reťazec base64 z vygenerovaného archívu zip a hodiť ho do vyrovnávacej pamäte, zatiaľ čo na serveri pomocou príkazu v konzole

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

mohli by sme vytvoriť rovnaký súbor zip.

nginxconfig.io bol napísaný v AngularJS, neviem si ani predstaviť, aké kilometre kódu by boli potrebné, keby si autor nezvolil reaktívny rámec js. Ale viem si dokonale predstaviť, o koľko jednoduchšie a krajšie by sa to všetko dalo implementovať do VueJS, hoci toto je úplne iná téma.
V zdrojoch projektu vidíme metódu na generovanie archívu 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',
	});
};

všetko je celkom jednoduché, pomocou knižnice jszip Vytvorí sa zip, kde sú umiestnené konfiguračné súbory. Po vytvorení archívu zip ho js odošle do prehliadača pomocou knižnice FileSaver.js:

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

kde obsah je výsledný objekt blob archívu zip.

Ok, stačilo pridať ďalšie tlačidlo vedľa neho a keď som naň klikol, neuložil by som si výsledný zip archív do prehliadača, ale získal z neho kód base64. Keď som sa trochu pohral, ​​namiesto jedného downloadZip som dostal 2 metódy:

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

Ako ste si mohli všimnúť, samotné generovanie zip archívu som presunul na privátnu metódu createZip a pod. Toto je AngularJS a sám autor sa drží spätných volaní a neimplementoval to cez sľuby. downloadZip stále urobil saveAs ako výstup, zatiaľ čo downloadBase64 urobil niečo trochu iné. Vytvárame objekt FileReader, ktorý k nám prišiel v html5 a už je celkom k dispozícii na použitie. Čo môže naraz vytvoriť reťazec base64 z blobu, alebo skôr vytvorí reťazec DataURL, ale to pre nás nie je také dôležité, pretože DataURL obsahuje presne to, čo potrebujeme. Bingo, čakal ma malý zádrhel, keď som sa to všetko snažil dať do vyrovnávacej pamäte. Autor v projekte využil knižnicu clipboardjs, ktorý umožňuje pracovať so schránkou bez flash objektov na základe vybratého textu. Pôvodne som sa rozhodol vložiť svoj base64 do prvku s display:none;, ale v tomto prípade som ho nemohol vložiť do schránky, pretože nedochádza k žiadnemu oddeleniu. Preto namiesto display:none; urobil som

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

čo mi umožnilo skryť prvok zo zobrazenia a skutočne ho ponechať na stránke. Voila, úloha bola dokončená, keď som klikol na moje tlačidlo, do vyrovnávacej pamäte sa umiestnil takýto riadok:

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

ktorý som jednoducho vložil do konzoly na serveri a okamžite som dostal archív zip so všetkými konfiguráciami.
A, samozrejme, poslal som autorovi žiadosť o stiahnutie, pretože... projekt je aktívny a živý, chcel by som vidieť aktualizácie od autora a mať vlastné tlačidlo) Pre záujemcov tu je moja vidlička projektu a seba požiadavka pull, kde si môžete pozrieť, čo som opravil/doplnil.
Šťastný vývoj všetkým)

Generovanie konfigurácií pre nginx, história jednej žiadosti o stiahnutie

Zdroj: hab.com

Pridať komentár