Making a POST request with Nodejs to Walmart Catalog Services - javascript

I'm having some trouble making a POST request with Nodejs. I can make the request with curl, but when I try and to do the same thing in Nodejs, I just get junk data back. I'm calling a Walmart service.
This is what my curl request looks like. This works fine.
curl -d "grant_type=client_credentials&client_id= WALMART_CLIENT_ID&client_secret= WALMART_CLIENT_SECRET" -X POST https://developer.api.walmart.com/api-proxy/service/identity/oauth/v1/token
This is an example of my code in Nodejs. I'm just getting junk data back from Walmart.
const https = require('https');
const qs = require('querystring');
const data = {
grant_type: "client_credentials",
client_id: WALMART_CLIENT_ID,
client_secret: WALMART_CLIENT_SECRET,
};
const options = {
hostname: "developer.api.walmart.com",
path: "/api-proxy/service/identity/oauth/v1/token",
method: "POST"
};
const request = https.request(options, result => {
var chunks = [];
result.on('data', data => {
chunks.push(data);
});
result.on('end', () => {
var body = chunks.join("");
console.log(body);
});
request.on('error', error => {
reject(error);
});
});
request.write(qs.stringify(data));
request.end();
The code works fine if I do a test POST request here. I'm not sure what I'm missing, or what curl is doing to have the Walmart request work.
const options = {
hostname: "reqbin.com",
path: "/echo/post/json",
method: "POST"
};
const data = {};

Except Catalog Pricing And Availability Snapshot and Catalog Store Locator API, all other APIs are GET calls not POST
Please verify which catalog API you are consuming and which HTTP method you are using
Request to follow below 2 steps to consumer any catalog API
First step, client would use api proxy service OAuth API to get the auth token using wm_consumer.id, client_id, client_secret.
Second step would be to call price and availability deltas API with relevant wm_consumer.id and auth token, i.e using the API token received from OAuth API, a call is made to the price and availability deltas API along with relevant wm_consumer.id
Please find the attachements for reference
Regards,
Firdos
IOSupport

Related

Express/axios don't set cookies and headers for response

I have very complicated problem. My project has 2 API's. 1 API is for front-end of my application and 1 is for back-end. How it works, is just I send request from front-end API to back-end API.
Front-end API has URL http://localhost:8080/api/ and back-end API has URL http://localhost:3000.
The problem is front-end API can't get cookies from back-end API.
Here is example, function of front-end API just send request to back-end:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
return res.json(data.data)
})
Back-and just sends cookie and some random text:
router.get("/test-back-api", (req, res) => {
res.cookie("test", "cookie")
res.send("Hi from back-end")
})
A here is where I have problem:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
console.log(data.headers) // If you do console.log here you will this cookie test
return res.json(data.data)
})
But this cookie is not set in browser.
Let me show one more example. In browser I can just type http://localhost:8080/api/test-front-api and here is result, no cookie:
But, if I type not front-end API endpoint, but back-end, everything works perfect:
I was trying literally everything I found about cors options, axios {withCredentials: true} etc. Nothing works.
I have found one solution, but I don't like it:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
// Something like this
res.cookie("test", JSON.stringify(data.headers['set-cookie']))
return res.json(data.data)
})
So, my question is why cookie is no set by front-end endpoint?
I have found not reason of the problem, but solution that seems to be ok. As I said, there are 2 API's - front-end and back-end.
From back-end API I get this cookie, but actually, it makes no sense to send it in header. Why? Because the front-end API will send it back on front.
So, using example above, you can do this, first, just send this cookies in body:
router.get("/test-back-api", (req, res) => {
res.json({cookie: "cookie"})
res.send("Hi from back-end")
})
And then, in front-end API, handle it:
router.get('/test-front-api', async (req, res) => {
const data = await api.get('/test-back-api')
res.cookie("test", data.cookie)
return res.json(data.data)
})
But I still have no idea, why I can send the same headers twice, through back-end API, then front-end API and finally on front.

Route that is executed within another route in Node.js is not being executed

Good Evening,
I have a function that contains a route that is a call to the Auth0 API and contains the updated data that was sent from the client. The function runs, but the app.patch() does not seem to run and I am not sure what I am missing.
function updateUser(val) {
app.patch(`https://${process.env.AUTH0_BASE_URL}/api/v2/users/${val.id}`,(res) => {
console.log(val);
res.header('Authorization: Bearer <insert token>)
res.json(val);
})
app.post('/updateuser', (req, ) => {
const val = req.body;
updateUser(val);
})
app.patch() does NOT send an outgoing request to another server. Instead, it registers a listener for incoming PATCH requests. It does not appear from your comments that that is what you want to do.
To send a PATCH request to another server, you need to use a library that is designed for sending http requests. There's a low level library built into the nodejs http module which you could use an http.request() to construct a PATCH request with, but it's generally a lot easier to use a higher level library such as any of them listed here.
My favorite in that list is the got() library, but many in that list are popular and used widely.
Using the got() library, you would send a PATCH request like this:
const got = require('got');
const options = {
headers: {Authorization: `Bearer ${someToken}`},
body: someData
};
const url = `https://${process.env.AUTH0_BASE_URL}/api/v2/users/${val.id}`;
got.patch(url, options).then(result => {
console.log(result);
}).catch(err => {
console.log(err);
});
Note: The PATCH request needs body data (the same that a POST needs body data)

Javascript AzureAd Consume Rest Service

RestAPI: I have a Rest API running Asp Core with AzureAd Authentication.
WebApp: I have a separate WebApplication running Asp Core as backend, with Javascript frontend.
The WebApp backend authenticates through AzureAd, and then against the RestAPI to check if a user is registred.
I want the javascript client to be able to consume the Rest API directly. How should i go about this without exposing the accesstoken?
I could go about sending the request from Javascript to WebApp Backend -> Rest API. But i really want to avoid this, because of unnecessary code.
In this scenario, you can try to implement ADAL for js in your JS client. Leveraging **adal** to gain the authentication token, and when you call your Web Api, it will add the authentication header in HTTP requests.
E.G.
Suppose we want to call the Microsoft Graph API from our JS client.we develop a node.js script that uses request to call the Microsoft Graph API for groups to create a new Security Group.
The following code shows how the API is consumed from that script. Note that the token and the name are passed by parameter. Additionally, this function returns a Promise that is successfully resolved when the group is correctly created and rejected when is not.
var request = require('request');
function createGroup(token, name) {
return new Promise((resolve, reject) => {
const options = {
method: 'POST',
url: 'https://graph.microsoft.com/v1.0/groups/',
headers: {
'Authorization': 'Bearer ' + token,
'content-type': 'application/json'
},
body: JSON.stringify({
"displayName": name,
"mailEnabled": false,
"securityEnabled": true
})
};
request(options, (error, response, body) => {
const result = JSON.parse(body);
if (!error && response.statusCode == 204) {
resolve(result.value);
} else {
reject(result);
}
});
});
}
In order to call Microsoft Graph API, we needed to be authenticated and that is why in the previous section we have a token as a parameter of the function which was used to perform the request.
we should add the following code to generate the token. Note that we are using the adal npm package to do this easier, calling the acquireTokenWithClientCredentials method of the AuthenticationContext object. Additionally, we have some constants that need to be updated with the client id and secret obtained before as well as the tenant name.
var adal = require('adal-node');
const TENANT = "{tenant-name-here}.onmicrosoft.com";
const CLIENT_ID = "{Application-id-here}";
const CLIENT_SECRET = "{Application-key-here}";
function getToken() {
return new Promise((resolve, reject) => {
const authContext = new adal.AuthenticationContext(`https://login.microsoftonline.com/${TENANT}`);
authContext.acquireTokenWithClientCredentials(GRAPH_URL, CLIENT_ID, CLIENT_SECRET, (err, tokenRes) => {
if (err) { reject(err); }
resolve(tokenRes.accessToken);
});
});
Hope it helps.

Yelp API authentication with Express

I'm attempting to issue a GET request to Yelp's API in order to perform a simple search using both Express and Nodejs, however I'm having trouble understanding how to set the request header with the provided API key. Using request I attempted to pass basic authentication following the documentation yet I'm receiving errors. Using setHeader I also received errors.
Using Postman I am able to enter the API keys and receive responses with no issue. I understand packages are out there for this but I think it might be good to learn without the use of additional dependencies if possible.
var express = require("express");
var app = express();
var request = require("request");
request.get('https://api.yelp.com/v3/businesses/search', function (error,
response, body) {
'auth': {
'bearer': 'api_key_here'
}
});
app.listen(3000)
Edit: I was able to fix the callback function(it was passing the header), and am now able to run, however I am now getting {"error": {"code": "TOKEN_MISSING", "description": "An access token must be supplied
in order to use this endpoint."}} . Still confused what I'm doing wrong here as the API key is working properly in POSTMAN.
var express = require("express");
var app = express();
var request = require("request");
request.get('https://api.yelp.com/v3/businesses/search', {
'Authorization': {
Bearer: 'api key'
}}
function(error, response, body){
console.log(body);
});
I tried using express.js to implement Yelp API, but I found using yelp-fushion much easier.
I implemented it like below:
require('dotenv').config();
const yelp = require('yelp-fusion');
const apiKey = process.env.YELP_API_KEY;
const searchRequest = {
term: 'restaurants',
location: 'Los Angeles',
};
const client = yelp.client(apiKey);
client.search(searchRequest)
.then((response) => {
console.log(response.jsonBody);
})
.catch((error) => {
console.log(error);
});
First line is to use .env file.
I saved my Yelp API key in .env file like this: YELP_API_KEY=6fNc0sj5Oyt_jsU2gdeDrlo_1NLm5c-df3f.
Then I assigned it to const apiKey and used it as an argument of yelp.client()
yelp-fushion's docs gives you more details on parameters for businesses search.
Lastly, client.search() method will return response.jsonBody containing all the data that you need.

Call /userinfo from spring backend (auth0)

I am attempting to do this call from my spring backend api. I already have the access token which the client sent me. What is the java-equivalent of this code?:
// Script uses auth0.js. See Remarks for details.
<script src="https://cdn.auth0.com/js/auth0/9.0.1/auth0.min.js"></script>
<script type="text/javascript">
// Initialize the Auth0 client
var webAuth = new auth0.WebAuth({
domain: '{domain}',
clientID: '{clientId}'
});
// Parse the URL and extract the access_token
webAuth.parseHash(window.location.hash, function(err, authResult) {
if (err) {
return console.log(err);
}
webAuth.client.userInfo(authResult.accessToken, function(err, user) {
// This method will make a request to the /userinfo endpoint
// and return the user object, which contains the user's information,
// similar to the response below.
});
});
</script>
Details in access token from client (I removed some of the details and replaced them with square brackets):
~~~~~~~~~ JWT Header ~~~~~~~
JWT Header : {"typ":"JWT","alg":"RS256","kid":"[kid]"}
~~~~~~~~~ JWT Body ~~~~~~~
JWT Body : {"iss":"https://demo.auth0.com/","sub":"google-oauth2|[my id here]","aud":["[api audience]","https://demo.auth0.com/userinfo"],"iat":[number],"exp":[expiry],"azp":"[azp]","scope":"openid"}
It is just a standard https call (plus adding the access token as an authorization bearer header) - no special library required.
An example making this from server-side using Node.js is here.
Basic Java outline, here using OkHttp, would be:
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://mytenant.auth0.com/userinfo")
.get()
.addHeader("authorization", "Bearer {{access_token}}")
.addHeader("cache-control", "no-cache")
.build();
Response response = client.newCall(request).execute();

Categories