React Node API Request Design Pattern - node.js

I need to make an API request to an external API using an API Key. I know how to make this API request in React by writing a onSubmit function. But since I have an API key that I want to keep a secret I am going to write a simple Node app to house env variables.
Besides messing around in node this is my first production experience with Node and I am wondering if my thought process is correct and if not, the better way to do this.
Most of this question will be pseudo code since I haven't started with the Node portion yet.
The idea is that from within the React component it would call the Node app who in turn would call the external API.
React -> Node -> External API
So the React component would be something like so:
handleSubmit: function() {
var data = this.refs.testData.getDomNode().value;
$.ajax({
url: '/my-node-endpoint',
dataType: 'json',
type: 'POST',
data: { test: data },
success: function(data) {
// Whatever success call I want to make
}.bind(this)
})
}
And then in my Node app it would like something like this:
app.post('/my-node-endpoint', function(req, res) {
// Store the values we are posting as JSON
// Start the post request
// On End tell the React component everything is ok
// Prosper
});
As always, thanks for any help that is offered.

Your thought process looks right to me.
If the API you are calling is from a different domain, you will have to build a wrapper on your node server like you did here. Unless the external API supports cross-origin requests with no domain restrictions (such as MapBox web services), you will have to do this.
Several improvements to your code:
As far as I know, you can use React.findDOMNode(this.refs.testData).value instead of this.refs.testData.getDomNode().value. getDomNode() is deprecated in v0.13.
For all the AJAX calls, you can use the Store concept in Flux. The store keeps the states of the data, including updating data through AJAX request. In your React UI code, you just need to call the methods of the store, which makes your UI code clean. I usually create a store class myself without using Flux.

Related

How to make a private call when using SSR Nuxt?

I am writing a headless solution for a WordPress website and noticed that for one particular endpoint, I need to authenticate to pull some data that will be used publicly. But, I'm concerned that where I'm using it will expose it to the web.
In my store/index.js I use the nuxtServerInit action method to execute some actions and I pass them some objects they need to fulfill their tasks:
async nuxtServerInit ({ dispatch }, { $axios, app }) {
await dispatch('initialize', { $axios, app })
},
$axios is passed because it will be used to query the API, and app is passed to help build the options to authenticate the request.
Is this a security vulnerability in Nuxt SSR? I think it is. If so, where are the only valid areas you can use secrets? asyncData ()?
If you're using SSR, you can use the privateRuntimeConfig runtime object and pass your secret in the nuxt.config.js file
export default {
privateRuntimeConfig: {
apiSecret: process.env.API_SECRET
}
}
If you read the documentation of nuxtServerInit, you can see that
Vuex action that is called only on server-side to pre-populate the store
Since this method is server-side only, you can use apiSecret (in my example) and it should be totally fine security-wise.
PS: Keep in mind that everything beyond what is generated on the server (hence, with NodeJS or nuxtServerInit) is "public". So your VueJS's client code lifecycle hooks are public: mounted(), fetch(), asyncData() because they will be visible on your browser's devtools.
Also, should your endpoint be that critical? If so, nuxtServerInit is the good way to go. If you need to fetch some more data in a "private way", you'll need to proxy it through some backend to hide the sensitive info and retrieve only the useful public data.

How to structure external API calls for Node.js, express, ejs routing?

//API Call one
function receiveLocation(){
axios({
"method":"GET",
"url":"https://ip-geo-location.p.rapidapi.com/ip/check",
...
})
.then((response)=>{
return response.data.country.name;
})
.catch((error)=>{
console.log(error)
})
}
//API Call two
//API Call three
console.log(receiveLocation());
app.get("/", function(req,res){
var location = receiveLocation();//
//Then render all the data from my API calls such as location, currency,
//etc. in my landing page. Also use that data on the backend.
res.render("landing",{location:location});
});
I am currently trying to make a website that uses multiple API calls to get information such as location, currency, and other things of a user who loads the website.
I am attempting to receive all the information from the different API calls as I go through the get request route that allows a user to see the landing page. Firstly, I am not even sure if this is allowed. If it is allowed/standard practice, what am I doing wrong in this example. I am attempting to call a function that in the get route to the root page that returns the country of a visiting user. But after doing some console.log() debugging I see that that information is never being received in the get route. Last note: I want to use the info from the API calls both to change what the user sees, and for some calculations that would need to be run on the backend.
If this is not allowed/not standard practice, may someone explain what I should do instead/point in the right direction as to what I should learn to get a better understanding of what I am trying to do
What you are trying at the moment to do is not standard practice, you should lookup MVC for Express,there you will learn how to structure your backend code so that the GET Routes will be used as Views ( these will be your server getting some public files like html,css,javascript that will be passed some information from the Controllers,this is done by using some server-side renders like EJS).
I recommend taking this Udemy course https://www.udemy.com/course/nodejs-the-complete-guide/ for a full understanding,but if you don't have the time,lookup node.js mvc with express, there is plently information about this.

Using socket.io with sails js

While there used to be very good documentation for using sockets, thanks to Irl Nathon's Sails Cast series. Things have changed in v0.11, with the sails team wrapping and burying the socket.io routines.
The sails site e.g. SailsSocket is maddeningly concise, saying what to do, but not how or where to do it, or if I need to npm or bower something. This has been particularly frustrating trying to use the sails.config.sockets talked about on the sails site. Which I cannot even find in my v0.11 directories.
First, I would like to know how and where to create my own response to a io.socket.get or .post or whatever. Right now when I do a get with something like:
`io.socket.request({
method: 'get',
url: '/sites/2',
params: {},
headers: {}
},function serverResponded(body, JWR){console.log("Body: ", JSON.stringify(body,null, 4)); console.log(' JWR: ', JWR.body)});'
I get back:
undefined
VM1149:7 "Not implemented in core yet"
VM1149:7 JWR: Not implemented in core yet
I can see the sites being called in the sails console, but nothing comes across.
I believe it is because I have defined my own routes and have my own find: function in my site controller and I manually need to push something into the server side socket. But I am confused as to how I am to call a whole page with HTTP and just the tables with socket.io in the same controller routine.
Where do I write my own low level socket.io routines that can be called from a web page?
Do I still do it in the app.js file?
Sails Cast showed it being done there, but again things have changed.
Sails "virtual requests" (what they call these socket.io-based HTTP-ish request) are generally used to retrieve or post JSON data to the server. Additionally, if a client-side script makes a virtual request, the server may add or remove the requesting socket to/from rooms.
Note that using a "virtual method" will ultimately run the same controller action, but will set req.isSocket = true.
This example is a view that renders a view for HTML-wanting requests but returns JSON data for socket-based requests:
...
// 'get /sites/:id': 'SomeController.showSite' (should be put in your `routes.js`)
showSite: function(req, res) {
// load something from the database
Site.findOne(req.param('id')).exec(function(err, site) {
// handler errors (same for HTTP or sockets)
if (err) return res.serverError();
if (!site) return res.notFound();
if (req.isSocket) return res.json(site); // render JSON response for our `site` object
else return res.view('sites/show', {site: site}); // render an HTML view
});
}
As for low-level socket.io, sails provides the global variable io (from sails.io.js), which is an instance of SailsSocket. It allows you to make HTTP-ish "virtual requests". More info here (although it seems you have already read all there is to read about SailsSocket :). You can access the underlying socket.io client with io.socket._raw.
// do this in the browser.
// sails.io.js should be included in layout.ejs by default.
io.socket.get('/site/2', console.log); // "virtual request"
// neat little trick ^^^^^^^^^^^ for testing :)
var rawIO = io.socket._raw;
rawIO.emit('some:event', "using native socket.io");
Hope this helps!

API mocking in Mithril for front-end development, like jquery-mockjax

I am using mithril in an IoT framework. I am trying to isolate the front-end development from backend API implementation tasks. In jQuery, I have used jQuery-mockjax and a similar mechanism in Angular. What I understand is that those libraries intercept ajax function call an appropriately respond with data that are setup using $.mockjax (or similar functions)
The mechanism recommended here https://groups.google.com/forum/#!topic/mithriljs/FzpCPMfauf0, does not give the flexibility to implement this. There is no easy way to use mock for a selected few APIs.
After looking through the code, I realized is, to implement this, I need to get access to the ‘ajax’ function (or just the XHR processing section), so that it can be overridden using my own implementation that can mock selected APIs. The problem is that ajax is a local function in the library. If it is exposed as m.ajax, my library can override it and get the functionality I need.
My question is, is there a better way to achieve the same? If you have done similar things please share.
My code structure will be something like this:
// in mithril-mockjax.js, implements mockjax function
m.mockjax = function (options) { … }
// in app-api-mocks.js
m.mockjax({
method: GET,
url: /sessions/123,
response: { …}
});
m.mockjax({
method: POST,
url: /sessions,
data: {},
response: { … }
});
The above two files are inserted in the page when I am in the development mode. The rest of the code remains the same.
You can do this by either mocking m.request by monkey-patching it or you add a layer of abstraction between m.request and your code that you are then able to mock away.

Explain the service.js in AngularJS

I'm quite new to AngularJS and NodeJS. I'm trying to develop an app using MEAN stack. I just looked through the sample code in the mean.io boilerplate. I created my own app referring the sample app. I'm trying to submit the AngularJS front end and expecting it to call NodeJs server side but it isn't working. I think service.js is messing up something. Here is the service code of sample app. Can any one explain what this code does with respect to Angular client side and NodeJS Server side.
'use strict';
//Articles service used for articles REST endpoint
angular.module('mean.articles').factory('Articles', ['$resource', function($resource) {
return $resource('articles/:articleId', {
articleId: '#_id'
}, {
update: {
method: 'PUT'
}
});
}]);
It creates a new factory in angular called Articles. The Articles factory has the $resource service injected. The $resource object is used to setup an object for communicating with a RESTful service, in this case "articles/:articleId" the articleId will be pulled from the _id of the resource objects that are returned from queries using this $resource. When you call to update on one of the resources it will use the PUT HTTP Verb.
By itself this just defines the factory but doesn't actually make any calls you would need to inject this and use it somewhere like Articles.query();
From the docs
If the parameter value is prefixed with # then the value of that
parameter is extracted from the data object (useful for non-GET
operations).

Resources