Yelp API authentication with Express - javascript

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.

Related

Making a POST request with Nodejs to Walmart Catalog Services

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

How we can intergrate Qr code monkey api to an express.js backend

Intergrate this for https://rapidapi.com/qrcode-monkey/api/custom-qr-code-with-logo
For this code
const express = require('express');
const http = require("https");
const router = express.Router();
router.post('/',async (req,res)=>{
console.log("req",req.body);
return res.sendStatus(200);
});
module.exports = router;
I'm not sure the question you're asking here.
My guess is that you're trying to interact with the qrcode-monkey API using express.js?
If that's true, following the qrcode-monkey API documentation you'll have to invoke (in this case) express to issue either a GET or POST request to the correct end point /qr/transparent with the required data both in the request body and head. this is documented in the link you provided
since you're doing this via express it's I assume you're going to be passing the URL that the qr code points to via your endpoint then to the 3rd party API. This might looking something like this.
router.get('/:url', async (req, res, next) => {
if (!req.params.url) next(new Error('400 missing url param'))
try {
res.body.qr = await fetch('https://qrcode-monkey.p.rapidapi.com/qr/transparent',
{
method: 'GET',
headers: { ... },
body: { ... }
}
).json()
} catch (error) {
next(error)
}
res.json(req.body.qr)
})
note: this is pesudo code and shouldn't just be copy/pasted.
I suggest refering to the express.js documentation
This question seems to go into more detail about 3rd party API interation with express.

Problem sending file in POST request to API using Axios from a Firebase Function

I'm using form-data and Axios to upload a file to another API from a Firebase Function. However, when I add createReadStream(filePath) to my formData object and attach it to my POST request, the response gives a 400 status code, claiming that the file is not present. My code:
const { fileName } = data;
const tempFilePath = path.join(os.tmpdir(), 'image.jpg');
const bucket = admin.storage().bucket();
await bucket.file(fileName).download({destination: tempFilePath});
let formData = new FormData();
formData.append('photo', fs.createReadStream(tempFilePath));
const formHeaders = formData.getHeaders();
await axios.post('api/endpoint', formData, {
headers: {
...formHeaders
}
}).catch(err => {
console.error(err.response.data)
});
The error I get after the Post request has a status code of 400 and is as follows:
{ error: 'invalid_query_missing_photo', ok: false }
I have verified that the tempFilePath does lead to an actual file, and I am able to make the request from Postman. However, even the code generated from Postman's code generation feature results in the same error.
My import statements:
// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
const axios = require('axios');
// The Firebase Admin SDK to access Firestore.
const admin = require('firebase-admin');
admin.initializeApp();
const path = require('path');
const os = require('os');
const fs = require('fs');
const { firebaseConfig } = require('firebase-functions');
const FormData = require('form-data');
The error 400 is coming from the second API, maybe something else is required to mark an take the request as valid, or the field required is not named photo.
I tested your code and I created another function simulating the second API, in my second API, I experienced an HTTP error 400 when the file field of the form doesn't match with the required in the API
Second API Code (Function written on python)
import os
def hello_world(request):
print(request.files)
#this must match with the form field or you gonna receive an error 400
file = request.files['photo']
filename="cool.png"
file.save(os.path.join("/tmp", filename))
#this is to verify that the object were saved and is in /tmp
print('Size :', os.path.getsize(os.path.join("/tmp", filename)))
return f'Hello World!'
With this second function I can validate that the issue is not coming from your function code.
I discovered you need to use getRawBody from the createReadStream, but only for cloud functions. This is what finally worked for me for google cloud firebase functions:
const fullFile = await getRawBody(fs.createReadStream(fileLocation));
...
formData.append('file', fullFile, { filename: 'somename.png'} );
...
await axios.post('api/endpoint', formData.getBuffer(), {
headers: {
...formHeaders
}
}).catch(err => {
console.error(err.response.data)
});
This solved my error of:
TypeError [ERR_INVALID_ARG_TYPE]: The "string" argument must be one of type string, Buffer, or ArrayBuffer. Received type object
Locally readstream seems to be converted into a full buffer automatically, but on cloud servers you need to convert it manually. There doesn't seem to be any documentation about this anywhere.

Unexpected end of JSON input getting Instagram JSON data with request

I'm trying to display the JSON data form instagram's URL: https://www.instagram.com/apple/?__a=1.
If I put this in browser, it shows the JSON, but I want to be able to get it with express so I can attempt to capture any data I need to with that URL
const express = require("express");
const Instagram = require("node-instagram").default;
const keys = require("./config/keys");
const app = express();
const request = require("request");
app.get("/", (req, res) => {
const url = "https://www.instagram.com/apple/?__a=1";
request(url, (err, response, body) => {
const json = JSON.parse(body);
console.log(json);
res.json(request.json);
});
});
app.listen(5000);
When I'm trying to deploy this in localhost, I'm getting an error:
SyntaxError: Unexpected end of JSON input
If you are logged in to instagram in your browser, you are getting authentication via cookies, and everything works fine, but if you are not logged in, the url https://www.instagram.com/apple/?__a=1 responds wit a 403 (access denied) error. This is the case for your back-end code since you are not sending cookies or authentication headers.
You are probably getting an error but not checking for errors in your request callback (the err parameter).
According to the instagram developer documentation, you need to register your app and authenticate before you can perform the request with OAuth credentials.
Check request's documentation on OAuth signing for more info.

Hiding api url in react/redux application (proxy)

I am concerned about security of my react/redux application as my api url is exposed to the public inside bundled app.js file. I've been researching this and some developers proxy it somehow i.e. instead of using my api url I can use api/ whenever I perform calls with libraries like axios or superagent and it gets proxied to my api url, but this way users can only see api/ on their side.
I'm trying to figure this out, I assume this is set up within express config?
You have a valid concern.
Typically you would have your clientside code make calls to, say, /api, and in express (or whatever server you use) create a route for "/api" that proxies that request to the actual api url.
This way you can obscure any sensitive information from the client. For example authentication tokens, api keys, etc.
In express you could do something like this:
app.use('/api', (req, res) => {
const method = req.method.toLowerCase();
const headers = req.headers;
const url = 'your_actual_api_url';
// Proxy request
const proxyRequest = req.pipe(
request({
url
headers,
method,
})
);
const data = [];
proxyRequest.on('data', (chunk) => {
data.push(chunk);
});
proxyRequest.on('end', () => {
const { response } = proxyRequest;
const buf = Buffer.concat(data).toString();
res.status(response.statusCode).send(buf);
});
});
This example is a bit more elaborate that is has to be, but it will probably work for you.

Categories