Why does nodejs return 404? - javascript

I'm trying to create a custom module for a deployd backend to authenticate with the instagram api. The code is as follows:
var request = require('request');
var payload = undefined;
process.server.on('request', function(req, res) {
if (req.url === '/foo') {
function getPayload(callback) {
var code = req.headers.referer.substr(req.headers.referer.lastIndexOf('/') + 1);
request.post('https://api.instagram.com/oauth/access_token', {form:{
client_id: '****',
client_secret: '****',
grant_type: 'authorization_code',
redirect_uri: 'http://localhost:2403/auth/auth.html',
code: code
}},
function(error, response, body) {
var payload = JSON.stringify(body);
console.log(payload);
callback();
});
}
function setPayload() {
res.end(payload);
}
getPayload(setPayload);
}
});
I can console.log the response from the instagram server, but then when I try to write the response back to the client I get a 404 response. What am I missing? Sorry if this is a total noob question. That would be because I'm a noob. Thanks in advance.
Sorry for the lack of clarity. Edit for more info: I'm creating an endpoint at /foo with the above code. The client sends a GET request to /foo from a referring URL containing the Instagram access code. The server then POSTs the access code along with the other app-specific parameters to the Instagram server which returns an object containing an authorization token and information about the user. The 404 comes at the point where the client GETs /foo. My code successfully sends the access code to the Instagram server and returns the object containing the access token - this outputs on the console - but it won't write it back to the client, and the client gets a 404. Also, the 404 is returned to the client before the object returned by the Instagram server is logged in the console.

Related

Stop execution after writing to text file with fs.writeFile

I have the following Node.JS (ran with Express) code :
let app = express();
app.use(cors());
app.get('/callback', function (req, res) {
// your application requests refresh and access tokens
// after checking the state parameter
var code = req.query.code || null;
var authOptions = {
url: 'https://accounts.spotify.com/api/token',
form: {
code: code,
redirect_uri: redirectUri,
grant_type: 'authorization_code'
},
headers: {
'Authorization': 'Basic ' + (new Buffer(clientId + ':' + clientSecret).toString('base64'))
},
json: true
};
request.post(authOptions, function (error, response, body) {
if (!error && response.statusCode === 200) {
var access_token = body.access_token,
refresh_token = body.refresh_token;
fs.writeFile('test.txt', 'HELLO', function (err) {
if (err) return console.log(err);
console.log('Hello World > helloworld.txt');
});
}
}
)
});
console.log('Listening on 8888');
app.listen(8888);
The route is used as a callback for a request to the Spotify Web API, thus I can get an access token.
Spotify then redirects to the callback function above, you can see it in the URI by looking at "redirect_uri".
If you need more information about the Spotify Authorization Flow, see here.
Here's the URI I'm using to authenticate my app to Spotify.
https://accounts.spotify.com/authorize?client_id=CLIENT_ID&response_type=code&redirect_uri=http://localhost:8888/callback&scope=user-read-private%20user-read-email%20playlist-modify-public&state=PexBrjEzISHepTp7&show_dialog=false
CLIENT_ID is replaced by my real CLIENT_ID in the request I make
My problem is located to the file writing part :
fs.writeFile('test.txt', 'HELLO', function (err) {
if (err) return console.log(err);
console.log('Hello World > helloworld.txt');
});
When the callback route is called by Spotify, I have the string "HELLO" wrote in my text file, so the file writing is functional.
But even if it has finished writing the string, the Chrome page is still running and "pending" on the server. It runs for a few minutes and then crash by saying that the page didn't sent any data. Why ?
I've looked at this page talking about the methods of writing to text files, using writeFile and writeFileAsync, but using both of them didn't solved my problem.
EDIT: I don't really want to stop the Express process! I just want to be able to process another request :)
Any idea ? Thanks in advance :)
You aren't returning anything from your route, try adding res.send({})
In your get route you are not sending response, you must send response irrespective of writing a file was successful or not.
Add below code post writing to file (as well as in if error case)
res.send({YOUR_CHOICE_RESPONSE_DATA})

Client side unable to hit its own server endpoint

I've a AngularFullStack project in which I'm trying to hit my project's server endpoint using the following code, however the problem is the call isn't going through from angular client side to the nodejs server. Since it's my first project, I've little to no idea what might be going wrong that might be causing this weird conflict.
ClientSide:
$http({
method: 'POST',
url: '/api/soapAPIs/soapAPI',
data: request,
headers: {
'Content-Type': 'application/json'
}
})
.then(function(response) {
console.log("response from server is: ", response);
})
.catch(function(error) {
console.log("error in calling server is: ", error);
});
I have installed CORS on server side and wrote the following code in app.js but still it doesn't work.
Server App.js
// Setup server
var app = express();
var cors = require('cors');
//add cors to do the cross site requests
app.use(cors());
Server Endpoint Code:
export function soapAPI(req, res) {
console.log("SERVER SIDE ", req.body);
res.status(statusCode).json({"status":"success"});
res.send();
}
Following are the problems:
If I try to hit nodejs endpoint like this /api/soapAPIs/soapAPI, the browser shows pending request and it never goes to the server.
When I add the full classified url for the endpoint like this http:localhost:9000/api/soapAPIs/soapAPI, it hits the endpoint but then the client never receives response from the server. I don't want to provide the full classified URL on the client side for obvious reasons.
How can I resolve this issue? Please let me know if you need any other code/information.
EDIT:
By using full classified path, the server endpoint gets hit but its response is never received by the client side. I get this error in browser:
Possibly unhandled rejection: {"data":null,"status":-1,"config":{"method":"GET","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"/api/things","headers":{"Accept":"application/json, text/plain, */*"}},"statusText":""}
Uncomment the following line:
/*mongoose.connect(config.mongo.uri, config.mongo.options);
mongoose.connection.on('error', function(err) {
console.error(`MongoDB connection error: ${err}`);
process.exit(-1); // eslint-disable-line no-process-exit
});
*/
Basically this is causing your controller to not return any response because your mongoose models are being referenced but the connection to mongo fails.

pass the credentials of user to all views node.js

I'm trying to build an android application using node.js web services,the first interface allow the user to connect to a host using ip address,login and password, so he can get all the databases,i want to save the object credentials to use in all other routes,i tried express-session but it didnt worked.
Any solution?
app.post('/connect',function(req,res){
sess=req.session;
sess.user=req.body.user;
sess.password=req.body.password;
sess.server=req.body.server;
sess.database=req.body.database;
console.log(sess)
user = req.body.user;
password = req.body.password;
server = req.body.server;
database = req.body.database;
var config = {
user: user,
password: password,
server: server,
database: database
};
// connect to your database
sql.connect(config, function (err) {
if (err) {res.json({success: false, message: "error connexion to SQL Server"});
sql.close()}
else{
res.json({success: true, message: "connexion established to SQL Server"});
sql.close();
}
});
});
In your case the request make by http lib of android (or another) which is not a browse then express-session will not work. Your server must be like a API server, client(android) request login server response a token (api key or the same), in next request client push data embeded token and server side can credentials the request. I suggest read about JWT (Json Web Token) to do this.
This is easy if you are using express module in node application.
You basically create routes using express and can pass the required data to the appropriate routes and views as follows
router.get('/', function(req, res, next) {
res.render('category',
{
videodata: vd
});
});
Here while rendering the response, the data that is to be passed is also included. It's name is videodata and value is vd

How to perform a POST request with session data to an endpoint within the server node js

I am working on express and I need to perform a POST request to an endpoint within the server. My code for this is :
request({
url : 'http://localhost:3000/api/oauth2/authorize',
qs:{
transaction_id:req.oauth2.transactionID,
user:req.user,
client : req.oauth2.client
},
headers:{
'Authorization':auth,
'Content-Type':'application/x-www-form-urlencoded'
},
method:'POST'
},function(err,res,bo){
console.log("Got response with body :"+bo);
});
localhost is the current server, this works properly but the session data is lost when i perform the POST request.
Is there any other way to perform a POST within the same server or to save the session data such that it is maintained after the POST?
Well, typically you register your routes something like:
var handlePostRequest = function(req,res,next) {
// process req.body etc.
};
app.post('/api/oauth2/authorize', handlePostRequest);
If you want to call that endpoint from within your application, you simply call handlePostRequest() providing the req, res, next objects as well.
Assuming handlePostRequest is in global scope, or required already; in your example that would be:
app.get('/some/other/endpoint', function(req,res,next){
// override the default req.body with your supplied data
req.body = {
transaction_id: req.oauth2.transactionID,
user: req.user,
client: req.oauth2.client
};
// you may also override req.headers etc. for authorization
// ...
// then call the "api" again with the new values
return handlePostRequest(req,res,next);
});
IF you however strictly want to make a POST request (for some reason), you need to supply the sessionID as well, which will be in your cookie. Then the session data will be available.

Passing parameters to the server (oAuth callback in Stripe Connect)

I am setting up Stripe Connect as explained here (Standalone Account). I handle the authorization and the retrieval of the access_token on my node server.
The user can visit the link MY_SERVER_URI/authorize and will be redirected to a pre-defined stripe AUTHORIZE_URI:
app.get("/authorize", function(req, res) {
// Redirect to Stripe /oauth/authorize endpoint
res.redirect(AUTHORIZE_URI + "?" + qs.stringify({
response_type: "code",
scope: "read_write",
client_id: CLIENT_ID
}));
});
After the user authorizes Stripe Connect, he or she will be redirected to a pre-defined REDIRECT_URI, which in this case equals to MY_SERVER_URI/oauth/callback, where the following script is executed:
app.get("/oauth/callback", function(req, res) {
var code = req.query.code;
// Make /oauth/token endpoint POST request
request.post({
url: TOKEN_URI,
form: {
grant_type: "authorization_code",
client_id: CLIENT_ID,
code: code,
client_secret: API_KEY
}
}, function(err, r, body) {
var accessToken = JSON.parse(body).access_token;
// Do something with your accessToken
// For demo"s sake, output in response:
res.send({ "Your Token": accessToken });
});
});
Now everything here works fine and the application is able to get the accessToken. However, this accessToken needs to be saved and matched with the user who is granting the access from the client side.
My question therefore boils down to, how can I either pass a client-side parameter (like the client-side userId) in the oauth/callback GET request, or process the server handling on the client side (e.g. a $http GET request instead of visiting the uri)? I guess that the later is not the recommended option.
I made two attempts:
I tried to pass a parameter using a dynamic REDIRECT_URI, but the
problem is that Stripe requires that alle urls need to be specified
first (resulting that no parameters can be passed in the redirect
url).
I tried to access the MY_STRIPE_URI/authorize with a $http GET request, but this gave me the obvious error No 'Access-Control-Allow-Origin' header is present on the requested resource
What can be done?
You have to pass your user id as "state" parameter and Stripe will return it on the callback. The only way I found to avoid session
Generally your scenario is as follows:
Make request to some route on your server and store the user's id there: req.session.user = {id: '...'}
From that route redirect the user to the third party authorization URL
In the route where you receive the access token, store it in the session as well: req.session.user.access_token = '...'
Use that access token for subsequent requests to the Stripe's API
Note:
Don't try to hack the authorization_code OAuth flow
You may find Grant easier to use for that type of OAuth flow, Stripe is supported
Relevant comment

Categories

Resources