nodejs serve pre-compressed gz file - node.js

I have a .gz file located at /public/files/update.tar.gz. I would like to serve it for downloading using the route /ud/files/update.tar.gz. I would like to do it as static content and also with route (as some files will have a dynamic generated route).
I've tried the following for static (Actually achieved with nginx wich maybe is even better):
main.use('/ud/files', express.static(path.join(__dirname, 'public/files')));
Here I get the error:
Error: No default engine was specified and no extension was provided. at new View (bla bla)
And for dynamic url at /ud/files/tX2r8z/update.tar.gz:
router.get('/ud/files/:s/:file', function(req, res) {
checkSg(req.params.s, function(err) {
if(!err) {
res.download("/public/files/" + req.params.file, req.params.file); 'also tried sendFile()
} else {
res.send(404);
}
});
});
Here I get two errors toghether:
Error: Forbidden at SendStream.error (bla bla)
Error: No default engine was specified and no extension was provided. at new View (bla bla)
Any ideas?

Ok, found the solution: the first one it was a configuration problem as nginx was rewriting the path in order to serve the file itself (Right now I'm wondering why it wasn't served by nginx and the request was sent to node...):
location ~ ^/(ud\/files)/ {
rewrite ^/ud\/files(/.*)$ $1 last;
root /mnt/data/public/files;
gzip_static on;
add_header Cache-Control public;
}
location / {
proxy_pass http://127.0.0.1:3000;
}
So node was seeing a GET /updates.tar.gz
The second one has been solved as stated in this thread:
res.download(path.resolve("public/files/" + req.params.file));

Related

How to redirect all except main page with NGINX?

This is my NGINX conf file:
server {
listen 80;
listen [::]:80;
server_name other.com;
root /home/user/html;
location = / {
}
location / {
return 301 https://mydom.com$request_uri;
}
}
It suppose to redirect every request except main route ("/"). But now it redirect everything with main route too. Where is my mistake?
Your location = / block isolates a single URI - the original request.
By default, Nginx processes any request that ends with a /, by checking if it resolves to a directory, and checking the directory for any files matching those listed in the index directive (default: index.html).
The index directive causes an internal redirection which causes Nginx to repeat the search for a matching location.
You will also need to isolate the redirected request.
For example:
location = / { }
location = /index.html { }
location / { ... }
Alternatively, bypass the index directive and handle it a single location using a try_files statement.
For example:
location = / { try_files /index.html =404; }
location / { ... }
See this document for details.

how to make Nodejs redirect work when called via Vuejs

I have created and tested the POST and GET request methods in Nodejs such that I can send the user through the Gocardless sign-up API perfectly fine.
This is a sign-up form provided by their API which allows them to input their details and then returns the user back after they fill it in.
But when I set up a front-end using Vuejs and make the same calls previously made from the back end using Axios, it seems that because the "redirect_url" fed back to me from the GC API had previously been fed directly into the browser url before, now, because it seems vue-router has control of the browser, I'm getting a cross origin error.
How can I configure the files to have the Nodejs back end acting as if it had control of the browser?
The end points are described here:
https://developer.gocardless.com/api-reference/#core-endpoints-redirect-flows
My nginx default is:
server {
charset UTF-8;
listen 80;
root /srv/www/sitename/;
index index.html;
server_name sitename.com;
location /api/ {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://sitename.com:8081;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
}
location / {
try_files $uri.html $uri $uri/ /index.html;
}
My button from Vuejs front end:
completeOrder()
..and uses axios this way:
import axios from 'axios'
export default() => {
return axios.create({
baseURL: 'http://sitename.com:8081/api'
})
}
And set it up here:
import Api from '#/services/Api'
export default {
completeOrder () {
return Api().post('order')
}
}
In the back end it sends:
app.post('/api/order', function (req, res){
rp({
//rp is npm request-promise
uri: BASE_URL + "/redirect_flows",
method: 'POST',
body:JSON.stringify(input_json),
headers: headers
}) // this works and API sends me the response
.then(function(response) {
var str_response =JSON.parse(response);
url = str_response['redirect_flows']['redirect_url']
// url works fine when I paste into a separate browser
res.redirect(url)
})
.catch(function (err) {
console.error(err);
})
})
Everything works up until the point:
res.redirect(url)
..where the Gocardless API response supplies me with the URL which I need to load into a browser.
It looks something like this:
https://pay-sandbox.gocardless.com/flow/RE000156
I think I need to break out of Vuejs's control of the browser via vue-router just long enough to allow the user to call the form with the redirect_url, then come back to the home page of the app again.
Any ideas very welcome!
I think you actually have a JS error. In the then block you instantiate a response, but you use a res variable to redirect.
Try chaging the variable
.then(function(response) {
var str_response = JSON.parse(response);
url = str_response['redirect_flows']['redirect_url']
// url works fine when I paste into a separate browser
response.redirect(url)
})
I am not a Vue.JS expert, so I don't know if that works, try using a vanilla JS redirect to test this feature:
window.location.href = url;
This way, you will be sure that the url works. After that, try checking out a full Vue.JS option.

Browser URLs and HTTP requests

I'm currently building a web portfolio that combines many smaller web apps that I've made in the past. At the route (/) you find a page with links to these other smaller web apps. For instance, there's a link to route (/board-game) which takes you to the small board-game web app I made in the past.
What I'm struggling with is this. The smaller web app board-game serves it's html, css, and javascript to routes that don't include the prefix route (/board-game). So when a board-game page makes a request for (/css/style.css) nothing is loaded because the content is actually at (/board-game/css/style.css).
My question is this. Is there a way to re-route these requests to the appropriate route? I would like to avoid rewriting any part of these smaller projects. Any suggestions? Thank you.
Also, this is my current nginx.conf file.
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream portfolio {
server portfolio-svc:8080;
}
upstream board-game {
server board-game-svc:8080;
}
server {
listen 80;
location / {
proxy_pass http://portfolio/;
}
location /board-game {
proxy_pass http://board-game/;
}
}
}
You need to rewrite the path as part of the location, for example:
worker_processes 1;
events {
worker_connections 1024;
}
http {
upstream portfolio {
server portfolio-svc:8080;
}
upstream board-game {
server board-game-svc:8080;
}
server {
listen 80;
location = / {
proxy_pass http://portfolio/;
}
location = /board-game {
proxy_pass http://board-game/;
rewrite ^(.*)board-game(.*)$ http://board-game/$2 permanent;
sub_filter /css/ /board-game/css/
}
}
}
You might have to play with the matching a bit, but that's the general idea.

Magento2 not reading my requirejs-config.js

I'm new to Magento2 and trying to figure out how RequireJS works in Magento.
Here is my situation:
I have following module:
app/code/Mymodule/Test/view/frontend/requirejs-config.js
Here is the content of this file:
var config = {
map: {
'*': {
jQuery110: "Mymodule_Test/js/jquery-1.10.2",
jqueryNoConflict: 'Mymodule_Test/js/jquery.no-conflict',
flexslider: 'Mymodule_Test/js/jquery.flexslider-min',
header: 'Mymodule_Test/js/store/header'
}
}
};
My theme is at this location:
app/design/frontend/Mycompany/Basic
My Javascripts are at following location:
app/code/Mymodule/Test/view/frontend/web/js/jquery.no-conflict.js
app/code/Mymodule/Test/view/frontend/web/js/jquery.flexslider-min.js
app/code/Mymodule/Test/view/frontend/web/js/store/header.js
In the PHTML file:
app/code/Mymodule/Test/view/frontend/templates/home.phtml
I added the lines:
require(['jqueryNoConflict', 'flexslider'],function($, flexslider){
(function($) {
$(window).load(function () {
$('.flexslider').flexslider();
});
})(jQuery);
});
When I check my page in browser, I get 404 error with paths:
http://mag2.com.local/pub/static/frontend/Mycompany/Basic/en_US/flexslider.js
But if I change the require[] line to this:
require(['Mymodule_Test/js/jquery.no-conflict', 'Mymodule_Test/js/jquery.flexslider-min'],function($, flexslider){
(function() {
$(window).load(function () {
$('.flexslider').flexslider();
});
})(jQuery);
});
the files are loading.
I also cleared the cache, my theme is correct, I executed the command:
php bin/magento setup:static-content:deploy
So, I am not able to figure out why my requirejs-config.js is not loading. I followed the documentation as well.
I found the problem.
Under pub/static/_requirejs/frontend/Namespace/Theme/en_US, delete the file requirejs-config.js.
Refresh your page and it will be generated again with new content.
This may help someone else with a very similar issue on local with nginx. The /static block was not rewriting correctly and this needed to be added per this comment https://github.com/magento/magento2/issues/7869#issuecomment-268585438
location /static/ {
if ($MAGE_MODE = "production") {
expires max;
}
# Remove signature of the static files that is used to overcome the browser cache
location ~ ^/static/version {
rewrite ^/static/(version\d*/)?(.*)$ /static/$2 last;
}
location ~* \.(ico|jpg|jpeg|png|gif|svg|js|css|swf|eot|ttf|otf|woff|woff2)$ {
add_header Cache-Control "public";
add_header X-Frame-Options "SAMEORIGIN";
expires +1y;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
location ~* \.(zip|gz|gzip|bz2|csv|xml)$ {
add_header Cache-Control "no-store";
add_header X-Frame-Options "SAMEORIGIN";
expires off;
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
}
if (!-f $request_filename) {
rewrite ^/static/(version\d*/)?(.*)$ /static.php?resource=$2 last;
}
add_header X-Frame-Options "SAMEORIGIN";
}
The detailed explanation is here
As requested by other members, adding the important bits:
Check if you can find the file it's trying to load on the filesystem. If it's there, it would point to a web server configuration problem instead. If it's not check file permission and then do static content deploy.

Flatiron js - director - how to do async routing from a table?

I'm starting to get things set up using flatiron as the toolset for a web app.
I'm using director with app.plugins.http, and can't seem to figure out how to create a "catchall" route for static files & 404s - It appears that .get("<RegEx>") only matches the first folder position, so if <RegEx> is /.*, it'll match /foo, but not /foo/bar.
Here's my code, as a better example:
in routes.js:
var routes = {
/* home
* This is the main route, hit by queries to "/"
*/
"/" : {
get: function(){
getStatic("html/index.html",_.bind(function(err,content){
if(err) throw err;
renderContent(this,content);
},this));
}
},
/* static files
* Last rule, if no other routes are hit, it's either a static resource
* or a 404. Check for the file then return 404 if it doesn't exist.
*/
'/(.*)' : {
get : function(){
getStatic(this.req.url,_.bind(function(err,content){
if(!err){
renderContent(this,content);
} else {
this.res.writeHead(404);
// TODO: fancier 404 page (blank currently)
this.res.end();
}
},this))
}
}
}
and in my main app file:
/* Define the routes this app will respond to. */
var routes = require('./lib/routes');
/* set up app to use the flatiron http plugin */
app.use(flatiron.plugins.http);
/* loop through routes and add ad-hoc routes for each one */
for(var r in routes){
var route = routes[r];
if(!routes.hasOwnProperty(r)) continue;
for(var method in route){
if(!route.hasOwnProperty(method)) continue;
app.router[method](r,route[method]);
}
}
/* Start the server */
app.listen(8080);
I'd like to be able to keep my routes in a separate module and import them - I'm pretty unclear on if this method or using director and a vanilla http server would be better, but I've tried both ways without any luck.
Here's what I get:
localhost:8080/
>> (content of index file - this works)
localhost:8080/foo
>> (blank page, 404 header)
localhost:8080/foo/bar
>> (no static file for this - I get a 404 header, but the body is now "undefined" - where is this coming from??)
localhost:8080/css/min.css
>> (this file should exist, but the route is never called. I do however still get a 404 header, and get the "undefined" body)
so, I'm assuming the "undefined" body is default behavior for undefined routes.
Is there a way to create a catchall route without adding rules for each depth?
You could try using node-ecstatic which is a static file serving add-on for flatiron. It works well for me and you can find it at:
https://github.com/colinf/node-ecstatic
Try using onError:
app.use(flatiron.plugins.http,{
onError: function (err) {
this.res.end('Nope');
}
});
To manage your static files I suggest you to use flatiron/union + connect.static

Resources