VÀlkomna, kamrater. PÄ mina stridsservrar Àr det utmÀrkt som har funnits sedan 2006 och under Ären som jag har administrerat det har jag samlat mÄnga konfigurationer och mallar. Jag har ofta hyllat nginx och av nÄgon anledning hade jag till och med startat en nginx-hub pÄ Habré, gillar att skryta/
Mina vĂ€nner bad mig att sĂ€tta upp en utvecklingsfarm för dem och istĂ€llet för att slĂ€pa med mig mina specifika mallar kom jag ihĂ„g ett intressant projekt , som delar ut konfigurationer och förbereder allt för lets encrypt och sĂ„ vidare. SĂ„ jag tĂ€nkte, varför inte? Men jag stördes av det faktum att nginxconfig ber mig att ladda ner en zip-arkiv i webblĂ€saren, utan att lĂ„ta mig ladda ner det direkt pĂ„ servern med wget/fetch/curl. Vad Ă€r det för dumhet, varför behöver jag det i webblĂ€saren, jag behöver det pĂ„ servern frĂ„n kommandoraden. Jag blev irriterad, sĂ„ jag gick in pĂ„ github för att kolla projektets inre, vilket ledde till en fork och dĂ€rmed en pull request. Som jag inte skulle ha skrivit om det inte var intressant đ
SjÀlvklart, innan jag började grÀva i kÀllkoden, kollade jag varifrÄn Chromium laddar ner det genererade zip-arkivet med konfigurationerna, och dÀr vÀntade en adress som började med "blob:", oops. Det blev redan klart att tjÀnsten inte genererar nÄgot, för faktiskt gör js allt detta. Det Àr verkligen sÄ att zip-arkivet genereras av klienten, webblÀsaren, javascript. SÄ det fina med projektet kan helt enkelt sparas som en html-sida, laddas upp pÄ nÄgon och det kommer att fungera ) Det Àr en mycket rolig och intressant lösning, men det Àr ocksÄ helt opraktiskt för serverinstÀllningar, just för det ÀndamÄl som detta projekt skapades. Att ladda ner det genererade arkivet via webblÀsaren och sedan föra över det till servern med hjÀlp av nc⊠Är 2019? Jag satte mig för att hitta ett sÀtt att ladda ner den erhÄllna konfigurationen direkt till servern.
Efter att ha gjort en fork av projektet började jag tÀnka pÄ vilka alternativ jag har. Utmaningen blev svÄrare eftersom jag inte ville avvika frÄn kravet att projektet skulle förbli en ren front-end, utan nÄgon back-end. SjÀlvklart skulle den enklaste lösningen vara att dra in nodejs och fÄ det att generera arkivet med konfigurationerna enligt direkta lÀnkar.
Det fanns egentligen inte mÄnga alternativ. Snarare kom jag bara pÄ en. Vi mÄste konfigurera konfigurationerna och fÄ en lÀnk som vi kan kopiera till serverns konsol för att fÄ zip-arkivet.
NÄgra textfiler i den mottagna zip-arkivet vÀgde vÀldigt lite, bokstavligen nÄgra kilobyte. En uppenbar lösning var att fÄ en base64-strÀng frÄn den skapade zip-arkivet och klistra in den i urklippet, medan pÄ servern utfördes en kommando i konsolen
echo 'base64string' | base64 --decode > config.zipvi skulle kunna skapa just den zip-filen.
skrevs med AngularJS, jag kan inte ens förestÀlla mig hur mÄnga kilometer kod som skulle behövas om författaren inte valt ett reaktivt js-ramverk. Men jag kan tydligt förestÀlla mig hur mycket enklare och vackrare detta skulle kunna implementeras med VueJS, Àven om det Àr ett helt annat Àmne.
I projektets kÀllkod ser vi metoden för att generera zip-arkivet:
$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',
});
};
det Àr ganska enkelt, med hjÀlp av biblioteket skapas en zip dÀr konfigurationsfiler placeras. Efter att zip-arkivet skapats, matar js det till webblÀsaren med hjÀlp av biblioteket :
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
dÀr content Àr det erhÄllna blob-objektet för zip-arkivet.
Okej, allt jag behövde göra var att lÀgga till en knapp bredvid och nÀr den trycktes skulle jag inte spara den mottagna zip-arkivet i webblÀsaren, utan fÄ base64-koden frÄn den. Efter lite fixande fick jag 2 metoder istÀllet för en: 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\/, '');
// i variabeln base64 finns just det zip-arkivet som en base64-strÀng
}
});
gtag('event', $scope.getDomains().join(','), {
event_category: 'download_base64',
});
};
Som ni kanske har mÀrkt har jag flyttat genereringen av sjÀlva zip-arkivet till en privat metod som heter generateZip, och eftersom det Àr AngularJS och författaren sjÀlv hÄller sig till callbacks, valde jag att inte implementera det genom promises. downloadZip gjorde fortfarande saveAs i utdata, medan downloadBase64 gjorde nÄgot lite annat. Vi skapar ett FileReader-objekt som kom till oss i html5 och som Àr ganska för anvÀndning. Detta objekt Àr, för sin tid, kapabelt att konvertera blob till en base64-strÀng, mer exakt gör det en DataURL-strÀng, men det Àr inte sÄ viktigt för oss, eftersom DataURL innehÄller precis det vi behöver. Bingo, en liten fÀlla vÀntade mig vid försöket att lÀgga allt detta i urklipp. Författaren anvÀnde biblioteken , vilket gör att man kan arbeta med urklipp utan flash-objekt, baserat pÄ den markerade texten. I början beslutade jag mig för att lÀgga min base64 i ett element med display:none;, men i det fallet lyckades jag inte lÀgga det i urklipp, eftersom ingen markering sker. SÄ istÀllet för display:none; gjorde jag
position: absolute;
z-index: -1;
opacity: 0;
, vilket gjorde att jag kunde dölja elementet för ögonen men ÀndÄ behÄlla det pÄ sidan. Voilà , uppgiften Àr slutförd, nÀr jag tryckte pÄ min knapp, placerades strÀngen i urklipp som sÄg ut sÄ hÀr:
echo 'base64string' | base64 --decode > config.zipsom jag helt enkelt klistrade in i konsolen pÄ servern och omedelbart fick zip-arkivet med alla konfigurationer.
Och sjÀlvklart skickade jag en pull request till författaren, eftersom projektet Àr aktivt och levande, jag vill se uppdateringar frÄn författaren och ha min knapp ) För den som Àr intresserad, hÀr Àr av projektet och sjÀlvt , dÀr man kan se vad jag har ÄtgÀrdat/lagt till.
Ănskar alla en produktiv utveckling )
KĂ€lla: habr.com
