I have been experimenting with Node.js on my machine for a little while and I have found my knowledge of HTTP requests, XHR objects, and the like quite lacking. So the main thing that's been nagging at me while using Node is that I can't seem to understand how to communicate from the client to the server (other than simple GET requests) and vice versa. What brings me to this question is my recent project, which is a simple 2 player chess game (no AI opponents).
What I want to do is to be able to send the game board data (a JSON string) to the server and have it save the data to a file. I understand how to get the file contents using an XHR object on the client-side. I also understand how to use Node's fs module to create and read files on the server-side. What I don't understand is how to use the XHR object to send the string to the server and have Node process and save it into a file. Is it even possible to call server-side code using client-side code in this way? Is trying to send an argument through a XHR object to the server an incorrect way of doing this?
If what I have asked is too broad of a topic to answer, I would also be open to links and books on the topic of server and client communication.
Expanding on SLaks answer a little:
Assuming you're using jQuery on the client and express on the server (both are useful frameworks to avoid reinventing low-level stuff), you could do something like this.
Client
$.ajax({
type: "POST",
url: "http://www.yourserver.com:3000/some/path",
data: { ...chessdatahere... }
}).done(function(msg) {
alert("Data Saved: " + msg);
});
Server
var fs = require('fs');
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(bodyParser.json());
app.post('/some/path', function(req, res) {
fs.writeFile('filename', res.body, function(err) {
if (err) {
res.send('Something when wrong');
} else {
res.send('Saved!');
}
})
});
app.listen(3000);
(Note that the code has not been tested, but it should show the general idea at least).
You can can use XHR to send an HTTP request with (eg) JSON data in the POST payload.
You can then write server-side Node.js code that handles this request, reads the payload, and does whatever you want with the data.
Related
Many times I have created apps with express where I just spin up a server at a port and then on the client side do all the stuff. whether that be fetching with fetch/axios, rendering data, and even changing routes (react-router). I have never hugely explored node or the server part, until now....hopefully.
I get what it's doing partially. in terms of
app.get('/', (req, res) => res.send('Hello World!'))
this just sends the response to the browser window. and I have even managed to do this:
app.listen(port, () => {
console.log("Listening");
fetch(url, {
}).then((res => res.json()))
.then((json => console.log('json')))
.catch(() => {
console.log("bbb");
});
});
and this logs all the data into the sever window. however, I have a couple of questions
should I be doing this in the server or the client? whats the advantage?
secondly, once I have this data, how can I send it to the client? i.e. a react component
also, I cant seem to copy this code and get it work inside app.get()? am I doing it wrong? maybe I have misunderstood there
I understood more than questions, an answer to all would be great but I would just like to have some more knowledge on what goes inside express and the server
should I be doing this in the server or the client? whats the advantage?
You have to consider the followig things when requesting another server:
Serverside:
you can share the data to multiple clients
you can keep algorithms / secrets private
you probably have a better bandwith than your clients, so you can load big chunks of data and then only send the neccessary data to the client
Client:
Does not consume your servers ressources
secondly, once I have this data, how can I send it to the client? i.e. a react component
You can use AJAX, websockets (http://socket.io) or you have to use redirects.
also, I cant seem to copy this code and get it work inside app.get()?
If you expected to see the data at the client, you have to res.json(json).
Is it possible to do this? Or perhaps, the question I should ask, is it feasible?
Or would it be better off to just stick with Java/Android front-end and Java back end server?
Would a node js backend be practical for multiplayer games? Or perhaps just for web applications that do not require much
And if it (java-nodejs) is practical for multiplayer games, how would one go about getting a java client to be able to communicate with a node js server?
If you're building an API, you don't have to worry about the language in wich you write it, the way to communicate with it will remain the same (UDP/HTTP/WS request).
Nevertheless, you're creating a multiplayer game, so you will need good performance for the back-end.
NodeJS is good, very good ! Erlang is better ;)
Yes, it is feasible. Node is very efficient and fast in handling requests. Since it works on a event based model its great for server side.
If you are working with Android and NodeJs as the server side I can help with this:
You can use Volley in Android to make a json POST or GET request.
And for the NODE JS you can use node's built-in http module to create a simple HTTP server and then receive data from the req object.
const http=require('http');
const stringDecoder=require('string_decoder').StringDecoder;
var httpServer=http.createServer(function(req,res){
unifinedServer(req,res);
});
//Just another method.
var unifinedServer=function(req,res){
var decoder=new stringDecoder('utf-8');
var buffer='';
//reading the post data.
req.on('data',function(data){
buffer+=decoder.write(data);
});
//Reading of data is completed.
req.on('end',function(){
buffer+=decoder.end();
// Do what ever you want to do with the POST data.
});
}
//The Server is listening on a specific port.
httpServer.listen(7000,function(){
console.log("Server is now listening on Port..."+7000);
});
For the Android Code you can do this with volley:
String url = "http://example.com";
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest
(Request.Method.POST, url, postJsonObject, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
mTextView.setText("Response: " + response.toString());
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO: Handle error
}
});
// Access the RequestQueue through your singleton class.
MySingleton.getInstance(this).addToRequestQueue(jsonObjectRequest);
I'm connecting to an external API on my backend.
Data flow : External API -> My backend -> Client side
I know that exists modules like request or http that helps this process.
But, When I receive the data from External API, I need to modify it and add some information. After I'll send this "modified data" to the Client side.
I am searching a tool similar to BackBone Collections on the backend to help me. BB Collections have awesome functions like fetch/sort/each.
Every time I google only I found frameworks like BackBone on the client side not on the server side.
Edit 1
Tool would have to help me iterating over array (received from external API) or accessing to item with specific attr given.
Solved
After studying both options (Lodash and Unirest), finally I decided to use Lodash combined with request.
Try lodash to handle arrays in server side.
var unirest = require('unirest');
app.get('/api', function(req, res){
unirest.get('http://localhost:3000/getlist')
.header('Accept', 'application/json')
.end(function (response) {
response.body.forEach(function(item){
//handle item
});
res.send();
});
});
Maybe Unirest?
When you have a RESTful server which only responds with JSON by fetching some information from the database, and then you have a client-side application, such as Backbone, Ember or Angular, from which side do you test an application?
Do I need two tests - one set for back-end testing and another set for front-end testing?
The reason I ask is testing REST API by itself is kind of difficult. Consider this code example (using Mocha, Supertest, Express):
var request = require('supertest');
var should = require('chai').should();
var app = require('../app');
describe('GET /api/v1/people/:id', function() {
it('should respond with a single person instance', function(done) {
request(app)
.get('/api/v1/people/:id')
.expect(200)
.end(function(err, res) {
var json = res.body;
json.should.have.property('name');
done();
});
});
});
Notice that :id in the url? That's an ObjectId of a specific person. How do I know what to pass there? I haven't even looked into the database at this point. Does that I mean I need to import Person model, connect to database and do queries from within the tests? Maybe I should just move my entire app.js into tests? (sarcasm :P). That's a lot of coupling. Dependency on mongoose alone means I need to have MongoDB running locally in order to run this test. I looked into sinon.js, but I am not sure if it's applicable here. There weren't many examples on how to stub mongoose.
I am just curious how do people test these kinds of applications?
Have you tried using mongoose-model-stub in your server-side test? It will free you from having to remember or hardcode database info for your tests.
As for testing the client side, your "webapp" is basically two apps: a server API and a client-side frontend. You want tests for both ideally. You already know how to test your server. On the client you would test your methods using stubbed out "responses" (basically fake json strings that look like what your web service spits out) from your API. These don't have to be live urls; rather it's probably best if they're just static files that you can edit as needed.
I would use nock..https://github.com/pgte/nock
What you want to test is the code you have written for your route.
So what you do is, create a response that will be sent when the end point is hit.
Basically its a fake server..
Something like this..
Your actual method..
request({
method: "GET",
url: "http://sampleserver.com/account"
}, function(err, res, data){
if (err) {
done(err);
} else {
return done(null,data);
}
});
Then..
var nockObj = nock("http://sampleserver.com")
.get("/account")
.reply(200,mockData.arrayOfObjects);
//your assertions here..
This way you don't alter the functionality of your code.. Its like saying.. instead of hitting the live server..hit this fake server and get mock data. All you have to do is make sure your mock data is in sync with the expected data..
Problem
I need a way to store and collect JSON data in an entirely offline(!) web application, hosted on a local (shared) machine. Several people will access the app but it will never actually be online.
I'd like the app to:
Read and write JSON data continuously and programmatically (i.e. not using a file-upload type schema)
Preferably not require any software installation other than the browser, specifically I'd like not to use local server. (edit: I may be willing to learn a bit of Python if that helps)
The amount of data I need to store is small so it is very much overkill to use some sort of database.
Solution?
My first thought was to let the html5 file API, just read/parse and write my JSON object to a local txt file, but this appears not to be possible?!
Local storage is not applicable here right, when several people - each with their own browser - need to access the html?
Any ideas?
note
I know this topic is not entirely novel, but I think my situation may be slightly different than in other threads. And I've spent the better part of the last couple hours googling this and I'm none the wiser..
Have you considered Python's Json module? http://docs.python.org/2/library/json.html
Using this you can convert python objects to and from json strings. You can store the strings however you want to
You can't use Localstorage to enable such features because every client will have its own dataset stored.
Have you ever considered using a java applet to handle such informations ?
You could start a java applet using it as a bridge between browser clients and as a store of informations.
Browsers could share such information using websockets.
Some times ago I build demo with such solution.
Check it at: https://github.com/KingRial/SBrower
In this demo I open a browser/tab which starts a java Applet to create a websocket server.
All the browsers/tabs are just clients connecting to the websocket server and sharing informations.
Since python is one of the question tags, I am giving a python solution:
import json
#reading
file_json = open("json.txt")
print file_json
python_json_object = json.loads(file_json)
print python_json_object
file_json.close()
#writing
file_json = open("json.txt", 'w')
file_json.write(json.dumps(python_json_object))
My suggestion would be something like WampServer (Windows, Apache, MySQL, PHP). I've seen a few tutorials about adding Python to that mix.
You would have access to reading and writing JSON data to the local storage or placing your data in a local database.
I know you said you don't want to opt for local server, but nodejs could be the solution. If you know JavaScript, then it's very simple to set one server up and let everybody access to the server from any browser. Since it's entirely JavaScript you don't even have conversion issues with the JSON format.
For storing the JSON you can use the FileSystem built-in library of nodejs which lets you read and write from a file, so you don't even need a database.
This is using Node.js and Express.
const express = require('express');
const http = require("http");
const app = express();
const server = http.createServer(app);
const fs = require('fs');
const newestData = {
"id":123,
"title":"spoon"
}
app.get("/",async(req,res,next)=> {
res.status(200).send('Hello World!');
fs.readFile("Metadata.json", 'utf8', (err,content)=>{
if(err) throw err
let data = JSON.parse(content)
data.push(newestData)
fs.writeFile("Metadata.json",JSON.stringify(data), (err)=>{
if(err) throw err
})
})
})
const port = process.env.PORT || 5000;
require("dotenv").config();
server.listen(port, function() {
console.log('Express server listening on port ' + port);
});