transmission rpc with expressjs - node.js

i currently have transmission-daemon web ui served by nginx
server {
listen 2324;
server_name torrent.example.com;
location /rpc {
proxy_pass http://127.0.0.1:9091/transmission/rpc;
}
location /transmission {
proxy_pass http://127.0.0.1:9091/transmission;
}
location / {
proxy_pass http://127.0.0.1:9091/transmission/web/;
}
}
i am trying to display this page via https://github.com/stormpath/stormpath-express-sample this dashboard/user interface
in routes/index.js i have
router.get('/torrent', function (req, res, next) {
if (!req.user || req.user.status !== 'ENABLED') {
return res.redirect('/login');
}
var newurl = 'http://127.0.0.1:2324'
request(newurl).pipe(res)
});
i see the html when i goto /torrent but no images/css/js i am thinking the request is not the right tool for this purpose could some one offer a better solution
many thanks

Your HTML probably refers to CSS/images/etc using URLs such as /index.css. The browser makes these into fully-qualified URLs that look like http://torrent.example.com/index.css, which is not proxied by ngnix the way you have it set up.
You probably want to either use URLs such as /transmission/index.css for your CSS (when specified in the HTML), or alternatively have a <base> tag in your HTML for that.

ok so i have made progress with html/css i moved the transmission interface into the express root and imported the html into jade but now i am having a new problem
when i load the /torrent page i can seen in the web console it makes a request to /rpc which i have made a route for
router.get('/rpc|/rpc/', function (req, res) {
var newurl = 'http://127.0.0.1:9091/torrent/rpc/'
request(newurl).pipe(res)
});
but this comes up with a 404 when i change router.get to router.post i get a 405 error
i have removed the 409 error from transmission so this should work

i have solved the issue
i imported the transmission index.html into a jade template
i routed /torrent to render that template
then i made a new route for /rpc|/rpc/ made that do a post request to the backend transmission-daemon
i also changed /js/remote.js to look for the RPC._Root at the atchual domain

Related

Serving webpack generated CSS file via CDN in Heroku CI environment

I have an Node.JS Meteor app that I bundle with webpack, that generates a CSS file with a hash in the name: [hash].bundle.css. I can set the publicPath to the CDN domain:
output: {
publicPath: 'https://xxx.cloudfront.com/',
},
On Heroku the bundle will be generated in the staging-environment and the generated slug will then be moved to the live-environment (including the css file).
When there is a change in the CSS, there will be a new hash in the staging-environment. When the site is opened (testing...) cloudfront will be asking the live-environment for that file, but the Node.JS-server responses with the app-HTML, that is issuing a not-found error on the browser.
Idea: Making the CDN fallback to staging
This is recommended in ther heroku documentation. But since the app-server does not respond with a 404 http error, cloudfront will not look at the staging server.
Problem: serving a 404 http error for missing files
This sound's not to difficult. Meteor webapp uses connect and I use FlowRouter on the client side, so I can:
WebApp.connectHandlers.use('/', function(req, res, next) {
if(FlowRouter.matchPath(req.url).route.name == 'not-found') {
res.writeHead(404);
res.end('Not found.');
} else {
return next();
}
});
But: there is many other connectHandlers that I would need to know, and make FileSystem checks. I tried going down that road, but it seems endless, maintenance intensive and not fail-proof.
Idea: Using Meteor's ?meteor_css_resource=1
There is a Meteor specific treatment of a css file with a query parameter xx.css?meteor_css_resource=1, but that won't be counting as a 404 error for the CDN to make the request to staging again.
Instead of checking all available connectHandlers, we filter just the .css files.
WebApp.connectHandlers.use('/', function(req, res, next) {
const urlParts = url.parse(req.url)
if(urlParts.pathname.endsWith('.css')) {
res.writeHead(404)
res.end('CSS file not found.')
} else {
return next()
}
}

can node HTTPS server be created without public and private keys?

I am using expressjs to create an http/https server.
There was a case wherein the server was not able to fetch the public and private certificate files from a directory.
In which case I create the server using http and send a raw HTML file to the client indicating that there was an issue, but here lies the problem,
the user does not know that they need to move to http url rather than https to see the HTML file.
So is there a way I can redirect my users to a https url when they try to access the http URL
init.js
try {
// options = get public and private certificate file
} catch(e) {
// accessError
}
if(accessError) {
server = http.createServer();
} else {
server = https.createServer(options, (req, res) => {
res.writeHead(200);
res.end('hello world\n');
});
);
}
server.listen(8080);
app.js
let app = require('express');
app.use((req, res, next) => {
if(accessError) {
res.sendFile(index.html);
} else {
next();
}
});
index.html
<h1> there was an error <h1>
You can try a 301 Redirect like in the answer to this question.
Whenever somebody tries to access the http variant of a resource, they'll be redirected to the https one.
As a design decision I'd treat the inability to retrieve certificates as a fatal error. I imagine you're reading them at start time. If you can't read them for some reason, you should just terminate the application, and log an exception. You do need to have some monitoring in place to notice that the thing hasn't started and act accordingly when you can't find it. But displaying an error page seems like more trouble than it's worth. You're going to have the application in an up state, but not really. Cause it won't be able to do anything, and you'll need to rely on clients telling you that it doesn't work and there's a https related message etc. Better to fail hard.

URL rewriting not working with iframe expressjs

I am trying to rewrite the URL of an iframe using express.
Similar code works fine on files available in my public folder (which express knows about thanks to server.use(express['static'](__dirname + '/public').
Jade code:
iframe(width="560", height="315", src="/videos/9bZkp7q19f0", frameborder="0", allowfullscreen=true)
Express code:
server.use(function(req, res, next) {
if (/videos/.test(req.url)) {
req.url = req.url.replace("videos", "embed");
req.url = "www.youtube.com" + req.url;
}
next();
});
Adding console.log(req.url) shows the correct url (www.youtube.com/embed/9bZkp7q19f0), yet express logs a 404 error.
Thanks in advance.
You can't just change req.url and expect the client to actually retrieve data from there. What you need is either a proxy or a redirect.
A redirect will force the iframe to redirect to youtube.com:
res.redirect('http://www.youtube.com' + req.url.replace('videos', 'embed'));
A proxy will actually request the page from your server, download the content, and serve back to the client: (you can use request for this)
req.pipe(require('request')('http://www.youtube.com'
+ req.url.replace('videos', 'embed'))).pipe(res);

server-side changes for $locationProvider.html5Mode(true);

server code:
app.get('/', function(req, res){
console.log('executed "/"')
res.render('home');
});
app.get('/partials/:name', function (req, res) {
console.log('executed partials:name');
var name = req.params.name;
console.log(name);
res.render('partials/' + name);
});
the code works perfectly before i put $locationProvider.html5Mode(true); to convert '/#/' url into regular / url.
After which, the console.log('executed partials:name'); fails to execute. Documentation says:-
Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all
your links to entry point of your application (e.g. index.html)
The changes I have tried are not working. What are changes to be made?
Edit: The following is the angular code:
var myApp = angular.module('myApp', []);
myApp.config(['$routeProvider', function($routeProvider, $locationProvider) {
$routeProvider.
when('/', {
templateUrl: 'partials/partial',
controller: 'homePage'
}).
otherwise({redirectTo: '/login'});
$locationProvider.html5Mode(true);
}]);
I again mention, the routing works perfectly well, till i add $locationProvider.html5Mode(true); to angular.
Not quite sure if this matches your problem but when we did this we needed to create a few rules on the server(in Nginx with our setup) to make sure a link to /page didn't just return 404 because it didn't exist on the server.
First we needed to make sure that a link to an Angular route was treated as such. So we do a rewrite ourdomain.com/page to ourdomain.com/#/page. /page doesn't exist on the server, only in Angular, so it would return 404. It needs to go to the index so that Angular can handle the route (this is relevant from incoming links, not so much for when you are on the site since then Angular handles the links anyway).
Secondly we needed to make an exceptions for partials, since those actually actually exists on the server and are not Angular routes. So going to ourdomain.com/partials/partial actually needs to find the partial on the server and can't be rewritten by the above rule.
Hope that helps somewhat at least.
Error is not with routing in this case. myApp.config(['$routeProvider', function($routeProvider, $locationProvider) is defined wrongly.
it should include $locationProvider thus :-
myApp.config(['$routeProvider', '$locationProvider', function($routeProvider,
$locationProvider) {
works perfectly.

Node - Tell origin of request

Is it possible to tell the difference between a request coming directly from a URL in a browser vs. a resource being called from a remote web page?
For example, I would like to serve a web page when someone visits my URL directly (types in http://mywebsite.com) in a web browser, but when a user calls a resource on my app via a url from a seperate domain (like <img src='http://mywebsite.com' />) then I'd like to serve different content.
I've looked in the request and in the headers but it looks the same regardless of
I think you are looking for the referer string in the request.header.
So the simple version would look like this:
http.createServer(function (req, res) {
var ref = req.headers.referer;
if(ref) {
// serve special content
}
else {
// serve regular homepage
}
}).listen(1337, '127.0.0.1');
edited the answer to reflect the input from anu below - it should be referer
In middleware you have to use this way "req.headers.origin"
app.use(function(req, res, next) {
//var origin=req.headers.origin
next();
});

Resources