Angular JS to Node Js using Express Js - javascript

I have been trying to run a angularJs front-end with NodeJs server with expressJs. This program is merely supposed to takes user input and prints it on the server console. Having limited knowledge in JavaScript I have compiled the following codes:
Client.js
angular.module("appModule",[]).
controller("appController", function($scope,$http){
$scope.action = function () {
console.log($scope.data);
var post = $http({
method: 'POST',
url: '/Data',
data: $scope.mod,
processData: false
})
post.success(function (response) {
console.log(response);
$scope.response.data = response;
});
}
});
Server.js
var express = require('express');
var fs = require("fs");
var url = require("url")
var http = require('http');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/Data', function (req, res) {
console.log(req.body);
res.setHeader('Content-Type', 'application/json');
req.body.serverMessage = "NodeJS replying to angular"
res.end(JSON.stringify(req.body));
});
http.createServer(function(request,response){
var pathname = url.parse(request.url).pathname;
console.log("Request for " + pathname + " received.");
fs.readFile(pathname.substr(1),function (err,data){
if(err){
console.log(err);
response.writeHead(404, {'Content-Type': 'text/html'});
}else{
response.writeHead(200, {'Content-Type': 'text/html'});
response.write(data.toString());
}
response.end();
});
}).listen(8081, function () {
console.log("Server running at http://127.0.0.1:8081/");
});
This seems to give an error on the terminal:
Server running at http://127.0.0.1:8081/
Request for /public/WebPageView.html received.
Request for /public/JavaScriptCode.js received.
Request for / received.
{ Error: ENOENT: no such file or directory, open ''
at Error (native) errno: -2, code: 'ENOENT', syscall: 'open', path: '' }
The scene of the browser was as follows
Browser Screen

#Ritik Saxena is correct. Also, you're not actually letting Express do it's job in the code you have above as you're not connecting it to the http server at all. the only code of yours actually running is the callback to the http.createServer call.
You should pass the express app to it rather than your own callback. If you want your existing callback to run you need to mount that as app middleware instead.

The last Request in your terminal output shows it receives request for /. Your code extracts / in variable pathname. In fs.readFile you provide first argument as pathname.substr(1) which boils down to null because pathname is / here. Hence, you get the corresponding error.

Related

I got the error : Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script

I'm trying to register a service worker to a html page and I get the error from title.
I'm working on linux,I have the right to write,delete,modify and so on,(I'm on # ).
I'm on a path like :
/var/www/a/b/c/d/e/f/project
And here I have a node.js server(index.js) , the html page(index.html) and the service worker(ServiceWorker.js)
The node.js server looks like:
const https = require('https');
const fs = require('fs');
var path = require('path');
const express = require('express');
const app = express();
const router = express.Router();
const pool = require('./mysqldb.js');
const pathView = __dirname + "/views/";
const IMGPath = "/public";
var bodyParser = require("body-parser");
const listenPort = 8010;
// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({ extended: true }));
// Process application/json
app.use(bodyParser.json());
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.use('/public', express.static('public'));
// This route will be used to print the type of HTTP request the particular
Route is referring to
router.use(function (req, res, next) {
next();
});
app.engine('html', require('ejs').renderFile);
app.get('/index.html',function(req,res){
res.render('/var/www/a/b/c/d/e/f/project/index.html');
});
app.use( "/", router);
// Not found
app.use("*",function(req,res){
res.setHeader('Content-Type', 'text/html');
res.status(404).send('Page introuvable !');
});
// Run server
app.listen(listenPort, function () {
console.log( listenPort )
});
//HTTPS
https.createServer(options, app).listen(8000);
And the .html file looks like:
<html>
<body>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('ServiceWorker.js', {
scope: './'
}).then(function (registration) {
var serviceWorker;
if (registration.installing) {
serviceWorker = registration.installing;
document.querySelector('#kind').textContent = 'installing';
} else if (registration.waiting) {
serviceWorker = registration.waiting;
document.querySelector('#kind').textContent = 'waiting';
} else if (registration.active) {
serviceWorker = registration.active;
document.querySelector('#kind').textContent = 'active';
}
if (serviceWorker) {
// logState(serviceWorker.state);
serviceWorker.addEventListener('statechange', function (e) {
// logState(e.target.state);
});
}
}).catch (function (error) {
// Something went wrong during registration. The service-worker.js file
// might be unavailable or contain a syntax error.
console.log('Service Worker registration error : ' , error);
});
} else {
console.log('Please update your brower!');
// The current browser doesn't support service workers.
}
</script>
</body>
</html>
I run the index.js node( command : "node index.js")
Everything is fine,the page is loading(I mean the script from the page) and i get the following error:
Service Worker registration error : TypeError: Failed to register a ServiceWorker: A bad HTTP response code (404) was received when fetching the script.
And I don't know what to do.I basically have the ServiceWorker.js,index.html and index.js in the same folder.I try to run them but somehow the path is wrong...
Can someone help me?
Include this in your app.js and put your service worker in your public directory/folder.
app.get("/ServiceWorker.js", (req, res) => {
res.sendFile(path.resolve(__dirname, "public", "ServiceWorker.js"));
});

Node.js send data to backend with AJAX

I'm quite new to AJAX, so sorry for potential missunderstandings, but I'm not completely through that thing.
I'm trying a simple thing. I have a server.js file, which is my backend basically. Then I have a index.html and a script.js. That's all, so a very basic setup. Now, on my script.js, I'm getting some data (a mail address). Now I want to send that data to my backend (into the server.js) to work with it there. How can I do this?
I found some posts already about AJAX with node.js, but I don't get it, especially not where to receive it in my backend. I'm using express for the server by the way.
What I have in my script.js is:
$.ajax({
type: "POST",
url: "server.js",
data: { mail: mail },
success: function(data) {
},
error: function(jqXHR, textStatus, err) {
alert('text status '+textStatus+', err '+err)
}
});
Right so far? How can I now receive the information in my server.js?
There's not much in so far, just:
var express = require('express');
var app = express();
var server = app.listen(3000);
app.use(express.static('public'));
Thanks for any help :)
Note: This was written before the question was updated with the code so the field names and port numbers that I used here as examples may need to be updated with the correct values.
Client-side code - example with jQuery:
$.post('/email', { address: 'xxx#example.com' });
(this can take optional callbacks and it returns a promise that can be used to add a success/error handler)
Server-side code - example with Express:
const express = require('express');
const bodyParser = require('body-parser');
const dir = path.join(__dirname, 'public');
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/email', (req, res) => {
// you have address available in req.body:
console.log(req.body.address);
// always send a response:
res.json({ ok: true });
});
app.use(express.static(dir));
app.listen(4443, () => console.log('Listening on http://localhost:4443/'));
This assumes that your static files (HTML, client-side JavaScript, CSS) are in the public directory relative to your server.js file.
See this for background on the JSON/form-encoding issue:
Which method is prefer when building API
See this for background on serving static files:
How to serve an image using nodejs
That's actually quite simple to implement in Express.JS with the basic router:
I'm gonna give you the minified code snippets to help you get sense of how it works across browser and server.
in Front-End, you basically just want to "post" an email address to the backend:
$.post('/email', { email: 'howareyou#xx.com' })
and in Back-End(Express.JS), you should implement the basic router:
var express = require('express');
var app = express();
// use: app.METHOD(PATH, HANDLER)
app.post('/email/', function(req, res) {
var email = req.body.email
})
Read more here: http://expressjs.com/en/guide/routing.html
First, you need a valid route to hit when the server is running. You can do this in server.js through express.
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.use(express.static('public'));
app.post('/mail', function(req, res) {
var body = req.body;
console.log('email', body.email);
res.json({ message: 'I got the email!' });
});
var server = app.listen(3000);
Notice I have brought in an express middleware that will parse the body for JSON and make it available on the req object under req.body. You will need to install this dependency with npm install --save body-parser.
Then you need to send a POST request to that URL from the front-end.
$.ajax({
type: "POST",
url: "/mail",
data: { mail: mail },
success: function(data) {
console.log('message', data.message);
},
error: function(jqXHR, textStatus, err) {
alert('text status '+textStatus+', err '+err)
}
});
Now, if you submit an email, you should see a log in your terminal that shows the email and a log in your developer console in the browser that shows the message "I got the email!"
in server.js add this :
app.post('/searching', function(req, res){
//do something with req
});
and in script.js :
$.ajax({
type: "POST",
url: "/searching",
data: { mail: mail },
success: function(data) {
},
error: function(jqXHR, textStatus, err) {
alert('text status '+textStatus+', err '+err)
}
});
First of all you nedd to create a route for the Mail
var express = require('express');
var path = require('path');
var bodyParser = require('body-parser');
var app = express();
var router=app.Router();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false })); // Parse request body
app.use(express.static(path.join(__dirname, 'public')));
// Route to check Email
router.post('/CheckEmail',(req,res)=>{
var email=req.body.mail; // Get email here
})
app.listen(process.env.port || 3000,()=>{
console.log('server is running');
})
Ajax
$.ajax({
type: "POST",
url: "/CheckEmail", // post route name here
data: { mail: mail },
success: function(data) {
},
error: function(jqXHR, textStatus, err) {
alert('text status '+textStatus+', err '+err)
}
});
You need a few more things to actually be able to parse the body. Add this to your server.js file.
var bodyParser = require('body-parser');
var cookieParser = require('cookie-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
You need to specify a valid URL. Since you are listening on 3000. You also need to specify a route on your server as an endpoint.
$.ajax({
type: "POST",
url: "http:localhost:3000/",
data: { mail: mail },
success: function(data) {
},
error: function(jqXHR, textStatus, err) {
alert('text status '+textStatus+', err '+err)
}
});
Now you need to add a route on your server. You can do so by adding this to your server.js file after all of the app.use calls
app.post("/", function(req, res){
// your logic here
res.send("I am sending something back!");
})

Node Express sever error : Can't render headers after they are sent to the client

I'm fairly new to this. I created a node-express server that runs locally. And I have a index.html under public\html folder. When I visit that index page, I got an error Can't render headers after they are sent to the client node server error. My understanding is that if the url is localhost:8080 plus /, index.html will be rendered? How do I solve this problem? Many thanks!
ps: The odd thing is that when I move index.html out from the "public" folder to the same directory with the node server.js, and change to app.get('/', function (req, res {fs.readFile('/index.html'.. the index.html seems to work fine.
var fs = require('fs');
var http = require('http');
var https = require('https');
var request = require('request');
var XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest;
var path = require('path');
var express = require('express');
var app = express();
var certificate = fs.readFileSync( 'something.0.0.1.cert' );
var privateKey = fs.readFileSync('something.0.0.1.key');
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
app.use(express.static(__dirname+'/public'));
app.get('/', function (req, res) {
fs.readFile('__dirname + '/public'+ '/html'+/index.html', function(error, content) {
if (error) {
res.writeHead(500);
res.end();
}
else {
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(content, 'utf-8');
}
});
res.send('Hello World');
});
https.createServer({
key: privateKey,
cert: certificate
}, app).listen(8080,'0.0.0.0');
You only get one response for every request. Your code shows res.send('Hello World');
change this to res.sendFile("__dirname + '/public/html/' + 'index.html' ")
You can remove the fs.readFile line too.
The reason fs.readFile('/index.html') works when you move to the same file as your server is because that line means to read a file called index.html from the same directory. But you want to send a response to a request, not just read files.
Check out the docs on res.sendFile in express
Try this:
app.get('/', function (req, res) {
res.sendFile(__dirname + '/public/html/'+'index.html');
});

Ignore header validation for HTTP requests in Node

I am building a proxy server which is supposed to forward data from an Shoutcast server to the client. Using request or even Node's http module this fails due to missing HTTP header:
{ [Error: Parse Error] bytesParsed: 0, code: 'HPE_INVALID_CONSTANT' }
The URL in question is: http://stream6.jungletrain.net:8000
Doing a header request with curl I was able to verify this:
$ curl -I http://stream6.jungletrain.net:8000
curl: (52) Empty reply from server
Yet the stream is working fine as tested with curl stream6.jungletrain.net:8000.
Is there a way to disable the header verification in request or Node's http? This is the code I am testing it on:
var express = require('express');
var request = require('request');
var app = express();
app.get('/', function (req, res) {
request('http://stream6.jungletrain.net:8000').pipe(res);
stream.pipe(res);
});
var server = app.listen(3000, function () {
console.log('Server started')
});
I am aware this can be achieved by rolling an implementation with net, there is also icecast-stack but subjectively seen it only implements half of the Stream interfaces properly.
Using icecast, I was able to get this working both using the on('data') event and by piping it to the Express response:
var express = require('express');
var app = express();
var icecast = require('icecast');
var url = 'http://stream6.jungletrain.net:8000';
app.get('/', function(req, res) {
icecast.get(url, function(icecastRes) {
console.error(icecastRes.headers);
icecastRes.on('metadata', function(metadata) {
var parsed = icecast.parse(metadata);
console.error(parsed);
});
icecastRes.on('data', function(chunk) {
console.log(chunk);
})
});
});
var server = app.listen(3000, function() {
console.log('Server started')
});
Or simply:
app.get('/', function(req, res) {
icecast.get(url).pipe(res);
});
Also of some note:
It appears the icecast package has been superseded by https://www.npmjs.com/package/icy

Parsing POST data with body-parser in Node.js app

I am trying to build a simple Node.js app which will parse data passed to it as POST requests from my AngularJS app. Below is the code used in my AngularJS app and my Node.js app. Problem I am facing is that I've searched the web trying to find how to parse (data and header) information passed in POST requests but failed to find any example, so any help with an example of parsing (data and header) passed in POST requests will help me a lot. Thanks.
Note: I am using express 4.1.2, body-parser 1.8.0.
Node app:
var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');
var app = express();
app.set('port', process.env.PORT || 3000);
app.use(bodyParser.json());
app.post('/', function (req, res) {
console.log(req.body);
res.send(200);
});
http.createServer(app).listen(app.get('port'), function(){
console.log('Server listening on port ' + app.get('port'));
});
POST request code
var deferred = $q.defer();
var dataObj = {};
dataObj.name = 'Chan';
dataObj.email_address = 'email#domain.com';
var myToken = '1234567890';
$http({ method:'POST',
url: '/',
data: dataObj,
headers: { 'Token' : myToken
}
}).success(function(data,status,headers,config){
deferred.resolve(data);
}).error(function(data,status,headers,config){
deferred.reject(status);
});
return deferred.promise;
If you're setting data to a plain js object, angular is interpreting that as a urlencoded form with the various keys and values in that object.
So there's two possible fixes here. One is to add something like app.use(bodyParser.urlencoded({ extended: false })); after app.use(bodyParser.json());
The second possible fix is to change your $http call to post JSON instead of urlencoded data. For that, change data: dataObj, to data: JSON.stringify(dataObj), and add 'Content-Type': 'application/json' to your headers so that it looks like this:
headers: {
'Token' : myToken,
'Content-Type': 'application/json'
}

Categories