Generiranje konfiguracij za nginx, zgodovina ene zahteve po vleku

Lep pozdrav, tovariši. Lepo na mojih bojnih strežnikih nginx deluje od leta 2006 in v letih njegovega upravljanja se mi je nabralo veliko konfiguracij in predlog. Zelo sem hvalil nginx in nekako se je izkazalo, da sem celo zagnal nginx hub na hubu, pohvali se m/
Prijatelji so me prosili, naj jim postavim razvojno farmo, in namesto da bi jim povlekel svoje posebne predloge, sem se spomnil zanimivega projekta nginxconfig.io, ki razmetava konfiguracije po policah in pripravlja vse za lets encrypt itd. Pomislil sem, zakaj pa ne? Vendar me je razjezilo dejstvo, da mi nginxconfig ponuja prenos zip arhiva v brskalnik, ne da bi mi dovolil, da ga naložim neposredno na strežnik z uporabo wget/fetch/curl. Kakšne neumnosti, zakaj ga rabim v brskalniku, rabim na serverju iz konzole. Jezen sem šel na github, da bi videl bistvo projekta, kar je privedlo do njegove razcepitve in posledično zahteve po vleku. O kateri ne bi pisal, če ne bi bilo zanimivo 😉

Generiranje konfiguracij za nginx, zgodovina ene zahteve po vleku

Seveda, preden sem se poglobil v vire, sem pogledal, kam Chrome potegne generirani zip arhiv s konfiguracijami, in tam me je čakal naslov, ki se začne z “blob:”, ups. Postalo je že jasno, da storitev ne ustvari ničesar na poti, pravzaprav vse naredi js. Dejansko arhiv zip ustvarijo odjemalec, brskalnik in sam javascript. Tisti. lepota je v tem, da projekt nginxconfig.io lahko preprosto shranite kot html stran, naložite na nekatere narod.ru in bo delovalo) To je zelo smešna in zanimiva rešitev, vendar je strašno neprijetno za nastavitev strežnikov, pravzaprav točno za to, za kar je bil ta projekt ustvarjen. Prenesite ustvarjeni arhiv z brskalnikom in ga nato s pomočjo nc prenesite na strežnik... leta 2019? Zadal sem si nalogo, da najdem način za prenos nastale konfiguracije neposredno na strežnik.
Po razcepu projekta sem začel razmišljati, kakšne so moje možnosti. Nalogo je oteževalo dejstvo, da nisem hotel odstopati od pogoja, da mora projekt ostati čisti front-end, brez kakršnega koli back-enda. Seveda bi bila najpreprostejša rešitev, da povlečete vozlišča in jih prisilite, da ustvarijo arhiv s konfiguracijami z uporabo neposrednih povezav.
Pravzaprav ni bilo veliko možnosti. Natančneje, na misel mi je prišel samo eden. Nastaviti moramo konfiguracije in dobiti povezavo, ki jo lahko kopiramo na strežniško konzolo, da dobimo arhiv zip.
Več besedilnih datotek v nastalem arhivu zip je tehtalo precej, dobesedno nekaj kilobajtov. Očitna rešitev je bila pridobiti niz base64 iz ustvarjenega arhiva zip in ga vreči v medpomnilnik, medtem ko ste bili na strežniku z ukazom v konzoli

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

lahko ustvarimo isto datoteko zip.

nginxconfig.io je bil napisan v AngularJS, si sploh ne morem predstavljati, koliko kilometrov kode bi bilo potrebnih, če avtor ne bi izbral reaktivnega ogrodja js. Si pa čisto predstavljam, koliko bolj preprosto in lepše bi se dalo vse to implementirati v VueJS, čeprav je to čisto druga tema.
V virih projekta vidimo metodo za ustvarjanje arhiva 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',
	});
};

vse je zelo preprosto, z uporabo knjižnice jszip Ustvari se zip, kjer so nameščene konfiguracijske datoteke. Ko ustvarite arhiv zip, ga js posreduje brskalniku s pomočjo knjižnice FileSaver.js:

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

kjer je vsebina nastali objekt blob arhiva zip.

Ok, vse kar sem moral storiti je, da sem zraven dodal še en gumb in ko sem kliknil nanj, nastalega zip arhiva ne bi shranil v brskalnik, ampak iz njega dobil kodo base64. Po tem, ko sem se malo poigraval, sem dobil 2 metodi namesto enega downloadZip-a:

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

Kot ste morda opazili, sem generiranje samega arhiva zip premaknil v zasebno metodo generateZip itd. To je AngularJS, sam avtor pa se drži povratnih klicev in tega ni implementiral z obljubami. downloadZip je še vedno naredil saveAs kot izhod, medtem ko je downloadBase64 naredil nekaj nekoliko drugačnega. Ustvarimo objekt FileReader, ki je prišel do nas v html5 in je že precej na voljo za uporabo. Kar naenkrat lahko iz blob-a naredi niz base64, oziroma naredi niz DataURL, vendar to za nas ni tako pomembno, ker DataURL vsebuje točno to, kar potrebujemo. Bingo, čakala me je mala zadrega, ko sem vse to poskušal spraviti v medpomnilnik. Avtor je pri projektu uporabil knjižnico odložiščejs, ki vam omogoča delo z odložiščem brez flash objektov, na podlagi izbranega besedila. Sprva sem se odločil, da svojo base64 postavim v element z display:none;, vendar ga v tem primeru nisem mogel dati v odložišče, ker ne pride do ločitve. Zato namesto display:none; jaz sem

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

kar mi je omogočilo, da element skrijem pred pogledom in ga dejansko pustim na strani. Voila, naloga je bila opravljena, ko sem kliknil svoj gumb, je bila v medpomnilnik postavljena vrstica, kot je ta:

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

ki sem ga preprosto prilepil v konzolo na strežniku in takoj prejel zip arhiv z vsemi konfiguracijami.
In seveda sem avtorju poslal prošnjo za vleko, ker ... projekt je aktiven in živahen, rad bi videl posodobitve avtorja in imel svoj gumb) Za tiste, ki jih zanima, tukaj je moje vilice projekt in sebe povlecite zahtevo, kjer si lahko ogledate kaj sem popravil/dodal.
Srečen razvoj vsem)

Generiranje konfiguracij za nginx, zgodovina ene zahteve po vleku

Vir: www.habr.com

Dodaj komentar