Greetings, comrades. On my combat servers, fine
nginx has been spinning since 2006 and over the years of its administration I have accumulated a lot of configs and patterns. I praised nginx a lot and somehow it turned out that even the nginx hub on Habré also started me up, ponty \ m /
Friends asked them to raise a developer farm, and instead of dragging their specific templates to them, I remembered about an interesting project
nginxconfig.io , which
scatters configs on the shelves and lets you encrypt everything and prepare everything. I thought, why not? However, I was infuriated by the fact that nginxconfig invites me to download the zip archive into the browser, not allowing it to be merged directly onto the server by means of wget / fetch / curl. What kind of nonsense, why is it in my browser, I need it on the server from the console. Angry, I climbed on github to look at the guts of the project, which led to its fork and, as a result, pull request `y. About which I would not write, if it was not interesting;)

')
Of course, before picking up the sources, I looked up from where chrome pulls the generated zip archive with configs, and there the address starting with “blob:” was waiting for me, oppa. Already it became clear that in the course of the service does not generate anything, in fact, it all does js. Indeed, the zip archive is generated by the client, browser, javascript. Those. the beauty is that the
nginxconfig.io project can be simply saved as an html page, uploaded to some
narod.ru and it will work) This is a very funny and interesting solution, however, it is terribly inconvenient for setting up servers, in fact, for what this project was created for. Download the generated archive with the browser, and then transfer it to the server using nc ... in 2019? I set myself the task of finding a way to download the received config directly to the server.
Having made a fork of the project, I began to think what options I have. The task was complicated by the fact that I did not want to deviate from the condition that the project should remain clean front-end, without any back-end. Of course, the simplest solution would be to pull up nodejs, and force it to generate an archive with configs by direct links.
The options, in fact, there were not many. More precisely, only one came to mind. We need to set up configs and get a link that we can copy to the server console to get a zip archive.
Several text files in the resulting zip archive weighed quite a bit, literally a few kilobytes. The obvious solution was to get the base64 line from the generated zip archive and throw it into the buffer, while on the server a command in the console
echo 'base64string' | base64 --decode > config.zip
we could create this zip file.
nginxconfig.io was written in AngularJS, I can’t even imagine what code kilometers would be needed if the author had not chosen the reactive js framework. But I can well imagine how much simpler and more beautiful it would be to implement all this on VueJS, although this is a completely different topic.
In the project we see the method of generating a zip archive:
$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', }); };
everything is quite simple, using the
jszip library
creates a zip, where the configuration files are put. After creating the zip archive, js feeds it to the browser using the
FileSaver.js library:
saveAs(content, 'nginxconfig.io-' + $scope.getDomains().join(',') + '.zip');
where content is the resulting blob zip archive object.
Ok, all I had to do was add one more button side by side and when I click on it, do not save the resulting zip archive to the browser, but get the base64 code from it. A little shuffling, I got 2 methods, instead of one 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,/, '');
As you can see, the generation of the zip archive itself I brought to the private method generateZip, well, and so on. This is AngularJS, and the author himself adheres to callbacks, did not implement it through promises. downloadZip still did saveAs on output, whereas downloadBase64 did a little more. We create a FileReader object that came to us in html5 and is already
available for use. Which, in due time, is able to make a base64 blob from a blob, or rather, it makes a DataURL string, but this is not so important to us, since DataURL contains exactly what we need. Bingo, a little tricky waiting for me when trying to put it all in the buffer. The author used the
clipboardjs library in the project, which allows you to work with the clipboard without flash objects, based on the selected text. Initially, I decided to put my base64 in an element with display: none; but in that case I could not put it on the clipboard, since selection does not occur. Therefore, instead of display: none; I did
position: absolute; z-index: -1; opacity: 0;
which allowed me to hide the element from the eyes and in fact leave it on the page. Voila, the task is completed, when you click on my button, a line of the following type was placed in the buffer:
echo 'base64string' | base64 --decode > config.zip
which I just inserted into the console on the server and immediately received a zip archive with all the configs.
And, of course, I threw the pull request to the author, because the project is active and alive, I want to see updates from the author and have my own button) Who cares, here is
my project
fork and
pull request myself, where you can see what I fixed / added.
All vigorous development :-)
