Nginx konfigūracijų generavimas, vienos ištraukimo užklausos istorija

Sveikinimai, bendražygiai. Gražus mano kovos serveriuose nginx veikia nuo 2006 m. ir per jo administravimo metus sukaupiau daug konfigūracijų ir šablonų. Labai pagyriau nginx ir kažkaip taip išėjo, kad ant stebulės net įkūriau nginx hub'ą, parodyk m/
Draugai paprašė, kad įkurčiau jiems vystymo ūkį, ir užuot tempęs jiems savo konkrečius šablonus, prisiminiau įdomų projektą nginxconfig.io, kuri išbarsto konfigūracijas lentynose ir paruošia viską leidžia šifruoti ir t.t. Pagalvojau, kodėl gi ne? Tačiau mane supykdė tai, kad nginxconfig man siūlo atsisiųsti zip archyvą į naršyklę, neleisdamas įkelti jo tiesiai į serverį naudojant wget/fetch/curl. Kokia nesąmonė, kam man to reikia naršyklėje, reikia serveryje iš konsolės. Supykęs nuėjau į github, kad pamatyčiau projekto esmę, kuri atvedė prie jo šakutės ir dėl to patraukimo prašymo. Apie ką nerašyčiau, jei nebūtų įdomu 😉

Nginx konfigūracijų generavimas, vienos ištraukimo užklausos istorija

Žinoma, prieš gilindamasis į šaltinius, pažiūrėjau, kur Chrome ištraukia sugeneruotą zip archyvą su konfigūracijomis, o ten manęs laukė adresas, prasidedantis "blob:", oi. Jau tapo aišku, kad paslauga nieko negeneruoja, iš tikrųjų visa tai daro js. Iš tiesų, zip archyvą sukuria pats klientas, naršyklė ir javascript. Tie. grožis tame, kad projektas nginxconfig.io galima tiesiog išsaugoti kaip html puslapį, įkelti į kai kuriuos narod.ru ir jis veiks) Tai labai juokingas ir įdomus sprendimas, tačiau siaubingai nepatogu nustatyti serverius, tiesą sakant, būtent tam, kam buvo sukurtas šis projektas. Atsisiųskite sugeneruotą archyvą su naršykle ir perkelkite jį į serverį naudodami nc... 2019 m.? Iškėliau sau užduotį rasti būdą, kaip gautą konfigūraciją atsisiųsti tiesiai į serverį.
Pradėjęs projektą, pradėjau galvoti, kokios yra mano galimybės. Užduotį apsunkino tai, kad nenorėjau nukrypti nuo sąlygos, kad projektas liktų grynas front-end, be jokio back-end. Žinoma, paprasčiausias sprendimas būtų ištraukti nodejus ir priversti jį generuoti archyvą su konfigūracijomis naudojant tiesiogines nuorodas.
Tiesą sakant, nebuvo daug pasirinkimų. Tiksliau, į galvą atėjo tik vienas. Turime nustatyti konfigūracijas ir gauti nuorodą, kurią galime nukopijuoti į serverio konsolę, kad gautume ZIP archyvą.
Keli tekstiniai failai gautame zip archyve svėrė gana mažai, tiesiogine prasme kelis kilobaitus. Akivaizdus sprendimas buvo gauti base64 eilutę iš sugeneruoto zip archyvo ir įmesti į buferį serveryje su komanda konsolėje

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

galime sukurti tą patį zip failą.

nginxconfig.io buvo parašyta AngularJS, net neįsivaizduoju, kokių kilometrų kodo būtų reikėję, jei autorius nebūtų pasirinkęs reaktyvaus js karkaso. Bet puikiai įsivaizduoju, kiek paprasčiau ir gražiau visa tai būtų galima įgyvendinti VueJS, nors tai visai kita tema.
Projekto šaltiniuose matome ZIP archyvo generavimo metodą:

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

viskas yra gana paprasta, naudojant biblioteką jszip Sukuriamas ZIP failas, kuriame dedami konfigūracijos failai. Sukūręs ZIP archyvą, js perduoda jį naršyklei naudodamas biblioteką FileSaver.js:

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

kur turinys yra gautas ZIP archyvo blob objektas.

Ok, tereikėjo prie jo pridėti dar vieną mygtuką ir jį paspaudus neišsaugočiau gauto zip archyvo į naršyklę, o gaučiau iš jo base64 kodą. Šiek tiek pasvarsčius, gavau 2 metodus, o ne vieną 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',
	});
};

Kaip tikriausiai pastebėjote, aš perkėliau patį ZIP archyvo generavimą į privatų generavimoZip metodą ir pan. Tai AngularJS, o pats autorius laikosi atsišaukimų ir pažadais to neįgyvendino. „downloadZip“ vis tiek išsaugojo „SaveAs“ kaip išvestį, o „downloadBase64“ padarė šiek tiek kitaip. Mes sukuriame FileReader objektą, kuris atėjo pas mus html5 ir jau yra gana prieinama naudojimui. Kuris vienu metu gali sudaryti base64 eilutę iš blob, tiksliau, ji sukuria DataURL eilutę, bet tai mums nėra taip svarbu, nes DataURL yra būtent tai, ko mums reikia. Bingo, kai bandžiau visa tai įdėti į buferį, manęs laukė nedidelis kliuvinys. Autorius projekte naudojosi biblioteka iškarpinė, kuri leidžia dirbti su iškarpine be „flash“ objektų, remiantis pasirinktu tekstu. Iš pradžių nusprendžiau savo base64 įdėti į elementą su display:none;, bet šiuo atveju negalėjau jo įdėti į mainų sritį, nes atsiskyrimas nevyksta. Todėl vietoj display:none; aš padariau

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

Tai leido man paslėpti elementą ir palikti jį puslapyje. Voila, užduotis buvo atlikta, kai paspaudžiau savo mygtuką, buferyje buvo įdėta tokia eilutė:

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

kurį tiesiog įklijavau į pultą serveryje ir iškart gavau zip archyvą su visomis konfigūracijomis.
Ir, žinoma, nusiunčiau autoriui prašymą ištraukti, nes... projektas aktyvus ir gyvas, noreciau pamatyti autoriaus atnaujinimus ir tureti savo mygtuka) Tiems, kurie domisi, cia mano šakutė projektą ir save trauka prašymas, kur galima pamatyti ką pataisiau/pridėjau.
Linksmo vystymosi visiems)

Nginx konfigūracijų generavimas, vienos ištraukimo užklausos istorija

Šaltinis: www.habr.com

Добавить комментарий