I am currently running an express server express.js with an angular js app. I use the UI router https://github.com/angular-ui/ui-router with stateprovider and state.go.
I have a requirement to allow a url to be typed in the browser
/getEmployeeDetails/1234
Am i going along the right lines , in that the following code can be added to the express server.js to achieve this or should I be handling this in the angular app states.
app.get('/p/:empId', function(req, res) {
controller.getEmpDetaails(req.params.empId);
state.go("employeeDetailsview")
});
I am not sure what was the reason for writing angular code inside your Express server but you should really separate your client code from your server code.
I assume you are trying to get some employee details by ID from your server.
The way it is usually done is by sending a HTTP request with the ID number from your client to the server. Then, the server will process the HTTP request (Maybe get some data from the database) and return a HTTP response to the client. And then the client will process the response and do something with it.
In your client yo can do something like this:
$http.post('SERVER_URL/getEmployeeDetails/', {'id': 1234})
.then(function(response){
// Response.data will have the data returned from the server
// Do something with it. for example, go to other state and pass the data to it
state.go("employeeDetailsview", {'employee': response.data});
});
The above will request an employee with id 1234 and do something with it.
In the server side:
app.post('getEmployeeDetails/', function(req, res) {
var employeeId = req.body.id; // YOU SHOULD USE THE BODY-PARSER MODULE IN ORDER FOR THIS TO WORK.
....
// Do something with ID
....
// Return some data to the client - for example an employee object
res.status(200).json({'data': employeeObject});
});
Related
I am new to web development and slowly understanding the web process . I want to know which how nodejs helps to build webserver in frontend ? for react applications npm start --> react-scripts start which runs application in localhost .here where exactly it create webserver and executes in localhost
An application can have front end and back end. A ReactJs application can be the front end for example, and nodeJs can be the back end. The back end will offer the server and will communicate with the database.
So, concretely, you will have 2 different projects: client and server. The client project will be your ReactJS application. The server project will be the NodeJS server. You create each one separetly.
A server can be accessed by paths, for example
http://my-server.localhost/login
http://my-server.localhost/logout
http://my-server.localhost/users
So, a basic connection between client and server can be based on the url paths, so in your client project you can do:
window.location.href = "http://my-server.localhost/login";
to call the login service from the server. And then, in your server, you can redirect to a client's url path.
BUT: the best way (for me) to establish connection between client and server is by using socket.
Socket is very simple, your client can emit requests to the server, and vice-versa:
socket.emit('hello', data);//where data can be any type of object, a string for example..
Similarly, the server can also emit requests to the client:
socket.emit('welcom', new_data);
Then, in the server and the client, you should hear for each request. Finally the code can be something like this:
Client side:
socket.emit('hello', data);// I will say 'hello' message (request) to the server..
socket.on('welcome', (data, callback) => {//I will hear to 'welcome' message(request) from the server..
console.log('server emited welcome with data =>', data);
});
Server side:
socket.on('hello', (data, callback) => {//I will hear to 'hello' message(request) from the client..
console.log('client emited hello with data =>', data);
socket.emit('welcome', ':)');//I will say(reply) 'welcome' to the client..
});
Hope this helps you to understand the concept.
I followed the following tutorial to create a RESTApi for my node server...https://scotch.io/tutorials/build-a-restful-api-using-node-and-express-4
My server file now has routes that allow it to to make GET and POST requests which I've tested on Postman and they work. My server file is pretty long but here is an excerpt to get an idea of how it works...
router.route('/bears')
// create a bear (accessed at POST http://localhost:8080/api/bears)
.post(function(req, res) {
var bear = new Bear(); // create a new instance of the Bear model
bear.name = req.body.name; // set the bears name (comes from the request)
// save the bear and check for errors
bear.save(function(err) {
if (err)
res.send(err);
res.json({ message: 'Bear created!' });
});
})
.get(function(req, res) {
Bear.find(function(err, bears) {
if (err)
res.send(err);
res.json(bears);
});
});
router.route('/bears/:bear_id')
// get the bear with that id (accessed at GET http://localhost:8080/api/bears/:bear_id)
.get(function(req, res) {
Bear.findById(req.params.bear_id, function(err, bear) {
if (err)
res.send(err);
res.json(bear);
});
});
...etc,etc
Now, since I am using an ionic framework I need to configure it to use this server as a backend.
My problem is, how do I connect to it using angular?
All my routes are prefixed using /api
app.use('/api', router);
So I tried the following...
app.factory('Bear', function ($resource) {
return $resource('http://XXX.XXX.X.XX:3000/api/bears/:bearId');
});
But I'm not sure this is working. I want to make one Post request so that I can test that the backend is working but I do not know what code to add to do so.
For example, if I have a form on my index.html and I send this info to my angular controller, how can my controller take this info and make a post request to my server? I've been trying to figure this out for days.
If you just want to test that your backend is working, check out postman.
Here's how you can refactor your code. First, note that as it is currently, how you're using $resource isn't actually make any calls to the API. You should inject your Bear service in a controller or another service somewhere in your app, depending on how you're going to use the bears. Then, in this other service or controller, you would do
var result = Bear.get({ bearId: <value> }) or var result = Bear.post({ bearId: <value> })
or whatever other http method you want to use. The resource object will then automatically hit the URL endpoint with the specified HTTP action and the parameter you have provided and then return you back the result.
Check out the $resource documentation for more detail. Also, the fact that you're using ionic has no bearing on connecting to the API.
I'm trying to access the data from server to $scope.resp but only raw json is getting displayed on the page.
here is the routes/addr.js
router.get('/', function(req, res) {
var pers = [{add: "abc"},{add: "pqr"}]
res.json(pers)
});
})
aj.js:
var app = angular.module('addbook', [])
app.controller('listcontroller', function($scope, $http){
$http.get('/list').then(function(response) {
$scope.resp = response
})
})
There is no error on chrome console. I notice that when $http.get request is commented out it still displays raw json. I saw a similar question where they asked to do do stringify but it is not working.
After our discussion in chat, we discovered that the issue was with your Express routes.
Angular is a client framework, which does not perform full page reloads. The user does not navigate directly to the URL on the server that is serving the data, they navigate to a URL that doesn't exist on the server, which is directed to the index.html file, where Angular is able to perform an AJAX request to retrieve the data from the Server URL and dynamically redraw the page.
If your user navigates to the server route that is serving the RAW JSON, the browser will receive the JSON and display it without any templating, styling, or other page elements. Therefore, your server URLs and your client URLs need to be different, and your server should use URLs that are exclusively identified as API urls. many people prepend /api/ to these URLs to avoid confusion, or secure them so that clients can't request them directly.
if you get a pure Json try to convert like this
$scope.resp = JSON.parse(response.data);
I use Angulars $http service to call for data on the backend. Let's say JSON data. An example URL to do so would be something like:
/get/data
Doing this from within Angular nicely returns the requested data. No problem.
But even though I catch all other Angular routes using Angular UI Router with $urlRouterProvider.otherwise('/');, I can still go to my browser and type in the mydomain.com/get/data URL, which provides me with a page of JSON code.
How to I restrict back-end server calls to come just from Angular, NOT from my browser URL without user authentication?
N.B.
Using Express 4.X on Node, I also provided my app with a 'catch-all' route to default back to my front-end index.html page, like so:
router.get('*', function(req, res) {
res.sendFile(path.join(__dirname, '/index.html'));
});
Thanks!
My God! Spent whole frikin day fighting this problem, finally fixed it!
The dog is burried in headers - you have to specify one on Angular http request, then read it in node.
First of - routing setup is the same as in this guide: https://scotch.io/tutorials/setting-up-a-mean-stack-single-page-application
On frontend in Angular http request I specify one of the accepted header types to be json:
$http.get('/blog/article', {
headers: {
'Accept': 'application/json;'
}
}).success(function(data) {
console.log(data);
})
.error(function(data) {
console.log('Error: ' + data);
});
On backend in Node I check if header includes json type. If it does, I serve back json data, so angular can receive the content. If it doesn't, I force node to load index.html, from which the controller runs the before mentioned http request with the header, ensuring you get your data then.
app.get('/blog/article', function(req, res) {
if(/application\/json;/.test(req.get('accept'))) {
//respond json
//console.log("serving json data...");
blogItemModel.find({ "_id" : req.query.id }, 'title full_text publish_date', function(err, blog_item){
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err) res.send(err);
res.json(blog_item);
});
} else {
//respond in html
//console.log('Request made from browser adress bar, not through Angular, serving index page...');
res.sendfile('./public/views/index.html');
}
});
Agree with #HankScorpio
Angular UI routing for Angular application paths and server application accessing URL paths are two different things.
Angular UI router allows you to navigate within a single page application as if you have a multi page application. This is in no way similar to accessing the actual server application endpoint.
All restrictions should be done on the web server and server web application end. Hence you will have to implement some authentication/authorisation strategy.
This isn't really an angular issue. When a user enters mydomain.com/get/data they never actually load up the angular app, so your solution must be done elsewhere.
For example, you could add this to your website's .htaccess file. It will redirect all traffic to the root of your domain.
Check out this answer here:
.htaccess Redirect based on HTTP_REFERER
You can't.
Your angular code is running on their machine, in their browser.
As such, one can spoof the environment, capture the data as the browser requests it, edit the JS of your app while it is in their browser, or various other methods.
Why do you want such a restriction anyway?
I can't connect to socket.io in production. It works fine in my dev server, but I'm not getting the "websocket user connected" message in the console in production and my heat map isn't populating with the test data. I'm getting net:: ERR_CONNECTION_TIMED_OUT in the browser jscript console.
from the server:
io.origins('http://example.com/path:8080')
app.get('/somepath', function (req, res, next) {
// code here
io.emit('update', data)
console.log('update has been emitted') // this prints and I see the data object in the console
res.end("OK")
})
io.on('connection', function (socket) {
console.log('websocket user connected')
});
from the angular controller:
$http.get('http://example.com/somepath?'+str) // hits somepath with test data in query string 'str'
from the script in /path:
var socket = io('http://example.com:8080');
and I've also included the cdn for socket.io in the page /path
<script src="https://cdn.socket.io/socket.io-1.3.2.js"></script>
The problem was that I had to include to port number in the URL for the development server, but it will not make the connection if I use the port in my production server. I'm not sure exactly why this is, but I suppose that the port is implied in a request from my browser and maybe something about the format makes it unrecognizable if explicitly stated.
Changes I made:
I removed the io.origins statement from the server because the default for socket.io is to allow any origin. That removes one possible source of error.
I removed the port number from $http.get() in the angular controller and changed var socket = io('http://example.com:8080') to var socket = io('http://example.com') in another script