Invoke HTTP GET and POST request without pages using Node.js + Express - javascript

I have a Node.js app running with Expressjs. I have the typical setup right now, using view jade files and route js files to process GET and POST requests. An example is as follows:
router.post('/postaction', function(req, res) {
// elements from the actual jade view itself
var one = req.body.from;
var two = req.body.to;
// do something
});
router.get('/getaction', function(req, res) {
// elements from the actual jade view itself
var one = req.body.from;
var two = req.body.to;
// do something
});
This works, I can carry out GET and POST requests. For example, a button might invoke the POST action. My question is, how can I use a separate script or npm module to invoke the same GET and POST requests without having to do it via the views? Ideally, I would have something like this:
somescript-get <param1>
somescript-post <param1> <param2>
with the params being akin to req.body.from and req.body.to. Essentially, I am looking to emulate the info from the page without having to use the page itself.
I am new to Node.js and would really appreciate some help. Please point out if I haven't explained something enough and I'll try to.
Thank you

An often-used tool for that is curl.
For instance, to make a GET request:
$ curl 'http://your.url/getaction?from=FOO&to=BAR'
To make a POST request:
$ curl -XPOST http://your.url/postaction -d 'from=FOO&to=BAR'
An alternative, one that I prefer myself, is httpie.

Related

Upload JSON File to my server with vue and node js

I'm new to node js and vue development and I want to create a process where I can create and upload a JSON file to my server when the user saves data in a form. This process should be done in the background. Later I want to read and update that file from the server when the user changed something.
So my first idea was to use fs.writeFile() this doesn't work very well and I think this only works for local stuff is that correct?
var fs = require('fs')
export default {
methods:{
send(){
fs.writeFile("/test.json","Hello World!",function(err){
if(err){
throw err;
}
});
}
}
}
Furthermore it looks like fs.writeFile doens't work with vue because it throws this error:
TypeError: fs.writeFile is not a function at VueComponent
So my second idea was to use express js with the app.post('/api/apps',...) and app.get() method. Here I have no idea how to implement that into the vue framework because I have to call the api like mydomain.com/api/apps but this doesn't work too.
So what is the best way to create, read, upload, delte files into a specific folder on my server? And how it works with vue? I tend to express js.
I'm using vue cli :)
Thanks in advance :)
EDIT
Now what I do is:
I created a new folder in my vue project root and named it "backend". In this folder I created a file named index.js and put this code
app.post('/appjson',(req,res) => {
fs.writeFile("/appjson/myJson.json",req.body,function(err){
//handle error
});
});
on the client side I put this code
axios.post('myDomain.com/appjson', {
JSONdata: myJSONdata,
})
My project looks like:
So when I build I get the dist folder and this I can upload on my server and it works fine. But I can't do the call to my backend? Whats wrong do I call the wrong link? Or how can I access my backend? Is the project struture correct or do I need to add the backend to a specific folder?
Vue is client side, your code is trying to write something to the filesystem of the user thats using your website. what you want to do is send this data to your NodeJS server, this requires using a package like Axios to send data to and from the server without refreshing the page. Axios is pretty straight forward to use, what you need will look similar to the function below.
saveJSON (myJSONData) {
const url = myNodeJSURL/savescene
return axios.post(url, {
JSONdata: myJSONdata,
})
Read some tutorials on ExpressJS, It's a pretty painless framework to use. You'll get the data stored in the body of the HTTP request and then you can use fs.writeFile to save data to the local filesystem of your server. Let me know if you need more help.
EDIT:
Your front end needs to be access a domain or IP address associated with your back end in order to communicate with it. Add the snippet below to your ExpressJS application and then when you run the server any requests to localhost:3000 will be handled by your app. You'll also have to update the URL in your Axios call.
app.listen(3000, function () {
console.log('my server is listening on port 3000!')
})
this setup only works for testing purposes because client and server will have to be on the same machine for localhost to mean the same to both. If you want this project to be public then you need to get your own domain for your site and host the ExpressJS application through there. Google compute makes this pretty easy to do, I'd look into that if I were you.

What's the most efficient way to call a Node.js backend function with JavaScript

I'm an html5 developer with mainly JavaScript experience. I'm starting to learn the backend using Node.js. I don't have a particular example of this question/requirements. I'd like to call a back end function with JavaScript, but I'm not sure how. I already researched events and such for Node.js, but I'm still not sure how to use them.
Communicating with node.js is like communicating with any other server side technology.. you would need to set up some form of api. What kind you need would depend on your use case. This would be a different topic but a hint would be if you need persistent connections go with web sockets and if you just need occasional connections go with rest. Here is an example of calling a node function using a rest api and express.
var express = require('express');
var app = express();
app.post('/api/foo', foo);
function foo(req, res){
res.send('hello world');
};
app.listen(3000);
From the frontend you can post to this REST endpoint like so.
$.post("/api/foo", function(data) {
console.log( "Foo function result:", data );
});
If you're just starting with node-js, don't worry about Websockets just yet.
You're going to want to create a REST API (most likely) depending on what you're trying to accomplish. You can put that REST API behind some kind of authentication if desired.
A REST API is going to have endpoints for creating/deleting/updating and getting (finding) a document, like a given user.
My recommendation is to work backwards from something that's already working. Clone this app locally and check out the controllers to see examples of how this application interacts with creating users.
https://github.com/sahat/hackathon-starter
Once you create a controller that returns data when a client hits an endpoint (like http://localhost:3000/user/create ) , you'll want to create some HTML that will interact with endpoint through a form HTML element. Or you can interact with that endpoint with Javascript using a library like jQuery.
Let me know if that makes sense to you. Definitely a good starting point is to clone that app and work backwards from there.
Can I suggest trying api-mount. It basically allows calling API as simple functions without having to think about AJAX requests, fetch, express, etc. Basically in server you do:
const ApiMount = apiMountFactory()
ApiMount.exposeApi(api)
"api" is basically an object of methods/functions that you are willing to call from your web application.
On the web application you then do this:
const api = mountApi({baseUrl: 'http://your-server.com:3000'})
Having done that you can call your API simply like this:
const result = await api.yourApiMethod()
Try it out. Hope it helps.

Multipage Node.js Server Without Routing Bloat?

Can I set up a multipage Node.js web server that does not require a unique route for every page?
I have a simple HTTP server set up using Node and Express, using EJS for view engine. My routing currently looks like this:
// routing
app.get('/', routes.index);
app.get('/hig', routes.hig);
app.get('/proto', routes.proto);
app.get('/design', routes.design);
app.get('/process', routes.process);
app.get('/demo', routes.demo);
app.get('/api', api.index);
app.get('/api/rules', api.list);
app.get('/api/rules/:id', api.ruleid);
I'd like to be able to easily update my site to have pages such as /hig/section1 and /hig/section2 (and so on) without having to update the route table each time and restart the server. More importantly, I'd like to be able to quickly and easily make multiple versions of a demo and be able to link to them.
For example, create a new demo and link a user to /demo/version23 while linking someone else to /demo/version 35, allowing me to illustrate different functionality without breaking previous demo sites. It would not be long until /demo/version108 and beyond exist, so having a sane way to create these without having 108+ routes is preferable.
The only method I've been successful at so far is updating route tables. Is there another way I can point to different pages in the route table that will allow me to more easily add new pages?
You should consider making part of url variable for ex as /hig/:section.
You should then get section as a parameter which you can use to map to different content, page or do any other logic that you want with that.
In my express api, I have a wildcard get. The endpoint var parses the keyword and then whatever you decided to do with that is up to you. In mine I have some if statements to change the database model etc but you don't need that... I would suggest keeping the 404 send, so if somebody hits an undesired url you can just give them whatever status code.
app.get('/:endpoint', function (req, res) {
var endpoint = req.params.endpoint;
if( endpoint == 'something' ){
} else if( endpoint == 'something' ){
} else { return res.send(404, { erorr: "That resource doesn't exist" }); }
// Display the results
});
I implemented simple demo project to achieve multi-app structure.
https://github.com/hitokun-s/node-express-multiapp-demo
With this structure, you can easily set up and maintain each app independently.
I hope this would be a help for you.

Express.js: reverse proxying different web app along with assets

I want to allow an authenticated client in Express to access to other web applications that are running on the server, but on different ports.
For example, I have express running on http://myDomain and I have another application running on say port 9000. I want to be able to reach the other app through http://myDomain/proxy/9000.
I had a little bit of success using node-http-proxy, for example:
function(req, res) {
var stripped = req.url.split('/proxy')[1];
var path = stripped.split('/');
var port = path.shift();
var url = path.join('/');
req.url = url;
proxy.web(req, res, {
target: 'http://127.0.0.1:' + port
});
}
However, the big problem is that when the web app makes GET requests, such as for /js/lib.js, it resolves to http://myDomain/js/lib.js, which is problematic because express is not aware of those assets. The correct request would be to http://myDomain/proxy/9000/js/lib.js. How do I route all these additional requests?
What you need to do is to replace URLs in the initial page with the new URL pattern. What is happening is that the initial page that your reverse proxy returns has a reference to:
/js/lib.js or http://myDomain/js/lib.js
so when the browser makes a second request it has the wrong pattern for your reverse proxy.
Based on the incoming request you know what the pattern should look like. In your example it's http://myDomain/proxy/9000. You then fetch the appropriate page from the other server running on http://127.0.0.1:9000/. You do a string replace on any resources in that file. You'll need to experiment with the pattern but you might look for 'script src="/' or 'href="/' and you might find regex helps with the pattern if, for example, the src attribute isn't the first listed in a script tag.
For example you might find 'scr="/' and then you replace it with 'src="/proxy/9000/' that way when the browser asks for that local resource it will come through with the port that you're looking for. This is going to need experimentation and it's a great algorithm to write unit testing around to get perfect.
Once you've done the replacement you just stream that page to the client. res.send() will do this for you.
Something else that you might find useful is that ExpressJS gives you a way to pull out the port number with a little less hassle than you're doing. Take a look at this example:
app.get('/proxy/:port', function(req, res){
console.log('port is ' + req.params.port);
});
I don't think http://myDomain/proxy/9000 is the correct way to do it. Web pages are going to assume the site's domain to be just myDomain and not myDomain/proxy/9000, because that is what the standard says.
Your use case would be better served by using subdomains like 9000.proxy.myDomain.

How to test REST API + Client-side MVC apps?

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..

Categories