Generierung von Konfigurationen für Nginx, Verlauf einer Pull-Anfrage

Grüße, Kameraden. Wunderschön auf meinen Kampfservern läuft seit 2006 und im Laufe der Jahre habe ich viele Konfigurationen und Vorlagen angesammelt. Ich habe Nginx sehr gelobt und irgendwie stellte sich heraus, dass ich sogar einen Nginx-Hub auf dem Hub gestartet habe, zeig m/
Freunde baten mich, eine Entwicklungsfarm für sie einzurichten, und anstatt ihnen meine spezifischen Vorlagen zu übertragen, fiel mir ein interessantes Projekt ein nginxconfig.io, das Konfigurationen in den Regalen verstreut und alles für Lets Encrypt usw. vorbereitet. Ich dachte, warum nicht? Allerdings ärgerte mich die Tatsache, dass nginxconfig mir anbietet, das Zip-Archiv in den Browser herunterzuladen, ohne dass ich es mit wget/fetch/curl direkt auf den Server hochladen kann. Was für ein Unsinn, warum brauche ich es im Browser, ich brauche es auf dem Server von der Konsole aus. Wütend ging ich zu Github, um mir den Kern des Projekts anzusehen, was zu seiner Abzweigung und infolgedessen zu einer Pull-Anfrage führte. Worüber ich nicht schreiben würde, wenn es nicht interessant wäre 😉

Generierung von Konfigurationen für Nginx, Verlauf einer Pull-Anfrage

Bevor ich mich mit den Quellen befasst habe, habe ich mir natürlich angeschaut, wo Chrome das generierte ZIP-Archiv mit den Konfigurationen abruft, und dort wartete eine Adresse, die mit „blob:“ begann, auf mich, ups. Es ist bereits klar geworden, dass der Dienst unterwegs nichts generiert, sondern alles von js erledigt wird. Tatsächlich wird das Zip-Archiv vom Client, Browser und Javascript selbst generiert. Diese. Das Schöne ist, dass das Projekt nginxconfig.io kann einfach als HTML-Seite gespeichert und auf einige hochgeladen werden narod.ru und es wird funktionieren) Dies ist eine sehr lustige und interessante Lösung, sie ist jedoch furchtbar unpraktisch für die Einrichtung von Servern, genau für das, wofür dieses Projekt erstellt wurde. Das generierte Archiv mit einem Browser herunterladen und dann mit nc auf den Server übertragen... im Jahr 2019? Ich habe es mir zur Aufgabe gemacht, einen Weg zu finden, die resultierende Konfiguration direkt auf den Server herunterzuladen.
Nachdem ich das Projekt geforkt hatte, begann ich darüber nachzudenken, welche Optionen ich hätte. Die Aufgabe wurde dadurch erschwert, dass ich nicht von der Bedingung abweichen wollte, dass das Projekt ein reines Frontend bleiben sollte, ohne jegliches Backend. Die einfachste Lösung wäre natürlich, nodejs aufzurufen und zu zwingen, über direkte Links ein Archiv mit Konfigurationen zu generieren.
Eigentlich gab es nicht viele Möglichkeiten. Genauer gesagt fiel mir nur eines ein. Wir müssen die Konfigurationen einrichten und einen Link erhalten, den wir auf die Serverkonsole kopieren können, um ein Zip-Archiv zu erhalten.
Mehrere Textdateien im resultierenden Zip-Archiv wogen ziemlich viel, buchstäblich ein paar Kilobyte. Die offensichtliche Lösung bestand darin, die Base64-Zeichenfolge aus dem generierten ZIP-Archiv abzurufen und sie mit dem Befehl in der Konsole auf dem Server in den Puffer zu werfen

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

Wir könnten dieselbe ZIP-Datei erstellen.

nginxconfig.io Da es in AngularJS geschrieben wurde, kann ich mir gar nicht vorstellen, wie viele Kilometer Code nötig gewesen wären, wenn der Autor sich nicht für ein reaktives JS-Framework entschieden hätte. Aber ich kann mir gut vorstellen, wie viel einfacher und schöner das alles in VueJS umgesetzt werden könnte, obwohl das ein ganz anderes Thema ist.
In den Projektressourcen sehen wir eine Methode zum Generieren eines Zip-Archivs:

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

Mit der Bibliothek ist alles ganz einfach jszip Es wird eine ZIP-Datei erstellt, in der die Konfigurationsdateien abgelegt werden. Nachdem das Zip-Archiv erstellt wurde, leitet js es mithilfe der Bibliothek an den Browser weiter FileSaver.js:

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

Dabei ist Inhalt das resultierende Blob-Objekt des ZIP-Archivs.

Ok, ich musste nur noch eine weitere Schaltfläche daneben hinzufügen und wenn ich darauf klickte, speicherte ich das resultierende Zip-Archiv nicht im Browser, sondern holte den Base64-Code daraus. Nachdem ich ein wenig herumgespielt hatte, bekam ich statt nur einer downloadZip zwei Methoden:

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

Wie Sie vielleicht bemerkt haben, habe ich die Generierung des Zip-Archivs selbst auf die private Methode „generateZip“ usw. verschoben. Das ist AngularJS, und der Autor selbst hält sich an Rückrufe und hat es nicht durch Versprechen umgesetzt. downloadZip führte immer noch saveAs als Ausgabe aus, während downloadBase64 etwas etwas anderes tat. Wir erstellen ein FileReader-Objekt, das in HTML5 zu uns kam und bereits recht ist доступный für den Einsatz. Was zu einem Zeitpunkt aus einem Blob einen Base64-String erstellen kann, oder besser gesagt, es erstellt einen DataURL-String, aber das ist für uns nicht so wichtig, weil DataURL enthält genau das, was wir brauchen. Bingo, ein kleiner Haken erwartete mich, als ich versuchte, das alles in den Puffer zu packen. Der Autor hat die Bibliothek im Projekt verwendet Zwischenablagejs, mit dem Sie basierend auf dem ausgewählten Text mit der Zwischenablage ohne Flash-Objekte arbeiten können. Ursprünglich habe ich beschlossen, mein Base64 in ein Element mit display:none; einzufügen, aber in diesem Fall konnte ich es nicht in die Zwischenablage legen, weil es findet keine Trennung statt. Anstelle von display:none; ich habe gemacht

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

Dadurch konnte ich das Element sowohl ausblenden als auch tatsächlich auf der Seite belassen. Voila, die Aufgabe war erledigt, als ich auf meinen Button klickte, wurde eine Zeile wie diese im Puffer abgelegt:

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

die ich einfach in die Konsole auf dem Server eingefügt habe und sofort ein Zip-Archiv mit allen Konfigurationen erhalten habe.
Und natürlich habe ich eine Pull-Anfrage an den Autor gesendet, weil ... Das Projekt ist aktiv und lebendig, ich würde gerne Updates vom Autor sehen und einen eigenen Button haben) Für Interessierte, hier ist es meine Gabel Projekt und sich selbst Pull-Anforderung, wo Sie sehen können, was ich korrigiert/hinzugefügt habe.
Allen eine gute Entwicklung)

Generierung von Konfigurationen für Nginx, Verlauf einer Pull-Anfrage

Source: habr.com

Kommentar hinzufügen