Üdvözlöm, barátaim. A harci szervereimen csodás 2006 óta működik, és évek alatt sok konfigurációt és sablont gyűjtöttem össze. Sokáig dicsértem az nginx-t, és valahogy arra is én ösztönöztem, hogy az nginx hub is megjelenjen a Habr-on, jó móka m/
A barátaim megkértek, hogy hozzak létre nekik egy fejlesztő farmot, és ahelyett, hogy áthoznék nekik a saját specifikus sablonjaimat, eszembe jutott egy érdekes projekt , amely a konfigurációkat szétszórja és minden szükséges dolgot előkészít a lets encrypt-hez. Gondoltam, miért ne? Azonban irritált az a tény, hogy az nginxconfig megkér, hogy töltsök le egy zip archívumot a böngészőmből, nem engedve, hogy azonnal letöltsem a szerverre wget/fetch/curl segítségével. Mi ez a képtelenség, miért van szükségem rá a böngészőmben, amikor konzolban a szerveren van rá szükségem? Felháborodva megnéztem a github-on a projekt belső működését, ami a forkhoz és ennek következtében a pull requesthez vezetett. Amiről nem írtam volna, ha nem lenne érdekes 😉
Természetesen, mielőtt beleásnék a forráshoz, megnéztem, honnan tölti le a chrome a generált zip archívumot a konfigurációkkal, és ott egy „blob:” kezdettel rendelkező címet találtam. Már világos volt, hogy a szolgáltatás nem generál semmit, valójában mindezt a js végzi. Valóban, a zip archívumot maga a kliens, a böngésző, a javascript generálja. Tehát a szépsége az, hogy a projekt egyszerűen csak elmenthető html oldalként, feltölthető valahova és működni fog ) Ez egy nagyon szórakoztató és érdekes megoldás, azonban rettenetesen kényelmetlen a szerverek beállításához, pontosan azért, amire ezt a projektet létrehozták. A böngészőből letölteni a generált archívumot, majd átkonvertálni a szerverre nc segítségével… 2019-ben? Kitűztem magam elé a célt, hogy találjak egy módot, amellyel az elkészített konfigurációt közvetlenül a szerverre tudom letölteni.
A projekt fork után elkezdtem gondolkodni, hogy milyen lehetőségeim vannak. A feladatot nehezítette, hogy nem akartam eltérni attól a feltételtől, hogy a projektnek tiszta front-endnek kell maradnia, bármilyen back-end nélkül. Természetesen a legjobb megoldás az lett volna, ha igénybe veszem a nodejs-t, és arra kényszerítem, hogy generáljon archívumot közvetlen linkek alapján.
Igazából nem sok lehetőség volt. Pontosabban, csak egy ötlet jutott eszembe. Be kell állítanunk a konfigurációkat, és meg kell kapnunk a linket, amelyet be tudunk másolni a szerver konzoljába, hogy megkapjuk a zip archívumot.
Néhány szöveges fájl a megkapott zip archívumban mindössze néhány kilobájtot nyomott. Nyilvánvaló megoldás volt, hogy ki kell nyerni a base64 sztringet az előállított zip archívumból és be kell tenni a vágólapra, míg a szerveren parancssorban futtatjuk.
echo 'base64string' | base64 --decode > config.zipLétrehozhatnánk ezt a zip fájlt.
AngularJS-ben íródott, elképzelni sem tudom, mennyi kilométernyi kódra lett volna szükség, ha a szerző nem egy reaktív js keretrendszert választott volna. Viszont jól tudom, mennyivel egyszerűbb és szebben meg lehetett volna valósítani ezt VueJS-ben, de ez már egy teljesen más téma.
A projekt forrásaiban látjuk a zip archívum generálási metódust:
$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',
});
};
Minden elég egyszerű, a könyvtár segítségével. zip-t hoz létre, ahová a konfigurációs fájlok kerülnek. A zip archívum létrehozása után a js átkonvertálja azt a böngésző számára a könyvtár segítségével. :
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
ahol a content a megkapott zip archívum blob objektuma.
Rendben, mindössze annyit kellett tennem, hogy hozzáadok még egy gombot mellé, és ha rákattintok, ne mentse el a megkapott zip archívumot a böngészőbe, hanem szerezze meg belőle a base64 kódot. Kicsit variálva, két metódust kaptam az egy helyett, a downloadZip mellett:
$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,/, '');
// a base64 változóban ott van a szükséges zip archívum a base64 sztring formájában
}
});
gtag('event', $scope.getDomains().join(','), {
event_category: 'download_base64',
});
};
Ahogy észrevehettétek, a zip archívum generálását átvittem egy privát generateZip metódusba, és mivel ez AngularJS, valamint a szerző is a callback-ek mellett érvelt, nem valósítottam meg ígéretek (promises) segítségével. A downloadZip még mindig a saveAs-t adta ki, míg a downloadBase64 kicsit másra volt hivatott. Létrehozunk egy FileReader objektumot, amely a html5-ben érkezett hozzánk, és már elérhető. használatra. Amely egy ideje képes a blob-ból base64 stringet, pontosabban DataURL stringet készíteni, de ez nem annyira fontos, mivel a DataURL pontosan azt tartalmazza, amire szükségünk van. Bingo, egy kis bonyodalom várt rám, amikor megpróbáltam mindezt a vágólapra helyezni. A szerző a projektben a , könyvtárat használta, amely lehetővé teszi a vágólappal való munkát flash objektumok nélkül, a kiválasztott szöveg alapján. Kezdetben azt terveztem, hogy a base64-et egy display:none; elemből helyezem el, de ebben az esetben nem tudtam a vágólapra tenni, mivel a kiválasztás nem történt meg. Ezért a display:none; helyett azt csináltam, hogy
position: absolute;
z-index: -1;
opacity: 0;
ami lehetővé tette, hogy elrejtsük a szemet elől, de valójában a dokumentumban hagyjuk. Voilà, a feladat teljesítve, a gombom megnyomásakor a vágólapra egy olyan string került:
echo 'base64string' | base64 --decode > config.zipamit egyszerűen a szerver konzoljába illesztettem, és azonnal megkaptam a zip archívumot az összes konfigurációval.
És természetesen küldtem egy pull requestet a szerzőnek, mivel a projekt aktív és élő, szeretném látni a frissítéseket a szerzőtől és persze a saját gombomat is ) Aki érdekli, itt van a projektről és a , ahol meg lehet nézni, mit javítottam/hozzáadtam.
Mindannyiuknak sikeres fejlesztést! )
Forrás: habr.com
