Foursquare API 405 Method Not Allowed? - foursquare

Here is my code:
This code is used angularjs but when I submit it got message error "Response for preflight has invalid HTTP status code 405"
$scope.listLocation = [];
$scope.getLocation = function() {
var time = Date.now();
return $http({
method: "POST",
url: 'https://api.foursquare.com/v2/venues/search?ll=11.5448729,104.8921668&client_id=.....&client_secret=......&v=1494294266811&limit=500&radius=500&intent=browse',
}).then(function success(res) {
$scope.listLocation = res.data.response.venues
}, function error(res) {
return res;
});
}

It looks like you just need to change your method from "POST" to "GET", if you are just trying to retrieve data.
$scope.listLocation = [];
$scope.getLocation = function() {
var time = Date.now();
return $http({
method: "GET",
url: 'https://api.foursquare.com/v2/venues/search?ll=11.5448729,104.8921668&client_id=LP5KESHULNRR3BCNKBD3O1J1FNMWQ3RFRHN34SSLV0GPMQLV&client_secret=ZI5233EL5L5LVJZIVHWKWSCBUCX0HIQ3MUJAXIEYVWQGOJTR&v=1494294266811&limit=500&radius=500&intent=browse',
}).then(function success(res) {
$scope.listLocation = res.data.response.venues
}, function error(res) {
return res;
});
}
P.s., That client_secret query parameter looks sensitive.

Related

nodejs modio api "add modfile" failing to upload

Im trying to upload modfiles with the api but it keeps saying that Im not including filedata. Ive tried with fetch like in the docs but it just gives the same error. If I try http it just gives a list of the files as if it was a GET request.
var zip = `./mod.zip`; // it exists!
var body = {
//filedata: `#${zip}`,
filedata: fs.readFileSync(zip, `binary`),
//filehash: crypto.createHash('md5').update(fs.readFileSync(zip, `binary`)).digest('hex'),
//version: version,
//active: active,
//changelog: changelog,
//metadata_blob: meta,
};
var res = await fetch(`https://api.mod.io/v1/games/${config.modio.gameid}/mods/${config.modio.modid}/files`, { // actually HTTP
method: 'POST',
headers: {
'Authorization': `Bearer ${config.modio.token}`,
'Content-Type': 'multipart/form-data',
'Accept': 'application/json',
},
body: JSON.stringify(body),
});
//console.log(body.filedata);
res = await res.json();
if (res.error)
console.log(res.error);
else
console.log(res);
{
"error": {
"code": 422,
"error_ref": 13009,
"message": "Validation Failed. Please see below to fix invalid input:",
"errors": {
"filedata": "The filedata field is required when upload id is not present.",
"upload_id": "The upload id field is required when filedata is not present."
}
}
}
Yes, ive submitted a bug report to them already, twice. Now they are ghosting me. (I'll probably submit a link to this as well)
They replied!
Hi
As mentioned, you would need to send data using FormData, not JSON.
You can find details at https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects
Thanks,
Danny King
Developer Relations Specialist
So, I remade my code
const https = require(`https`);
var crypto = require('crypto');
var FormData = require('form-data');
function ObjectToForm(obj = {}) {
var form = new FormData();
Object.keys(obj).forEach(key => {
var val = obj[key];
switch (typeof val) {
case `boolean`:
val = String(val);
break;
}
form.append(key, val);
});
return form;
}
if (fs.statSync(zip).size > 5368709120) return consolelog(`Zip bigger then 5gb`);
var body = {
filedata: fs.createReadStream(zip),
filehash: crypto.createHash('md5').update(fs.readFileSync(zip)).digest('hex'),
version: version,
active: active,
changelog: changelog,
metadata_blob: meta,
};
var form = ObjectToForm(body);
var options = {
hostname: 'api.mod.io',
port: 443,
path: `/v1/games/${config.modio.gameid}/mods/${config.modio.modid}/files`,
method: 'POST',
headers: {
'Authorization': `Bearer ${config.modio.token}`,
...form.getHeaders(),
'Accept': 'application/json',
},
};
var req = https.request(options, (res) => {
var data = [];
res.on('data', (d) => data.push(d));
req.on(`close`, () => {
var buffer = Buffer.concat(data);
var resp = JSON.parse(buffer.toString());
if (resp.error)
console.log(resp.error);
else if (res.statusCode == 201)
r(true);
});
});
req.on('error', (e) => {
console.log(`Error publishing:`);
console.log(e);
r(e);
});
form.pipe(req)
.on(`close`, () => req.end());
And it worked. Thanks King.

Convert AJAX request into HTTP request in nodejs

Actually i am using ajax call to connect to a 3rd party api when i am using the api on browser and i am able to get the data from the api.
Here is the AJAX code:-
var settings = {
async: true,
//crossDomain: true,
url: "https://rest.cricketapi.com/rest/v2/schedule/?access_token=XXX"
//"url": "https://rest.cricketapi.com/rest/v2/match/indaus_2020_one-day_02/?access_token=XXX"
//bblt20_2019_g28
};
//create token for the api for 24hours
let token;
function getToken() {
$.ajax({
type: "POST",
url: "https://rest.cricketapi.com/rest/v2/auth/",
data: {
access_key: "********************************",
secret_key: "********************************",
app_id: "http://localhost:8000/",
device_id: "developer"
},
success: function(data) {
console.log(data);
token = data.auth.access_token;
console.log(token,);
//do something when request is successfull
createUpcomingMatchesSchedule();
},
dataType: "json"
});
}
function createUpcomingMatchesSchedule() {
var urlJson = settings.url;
urlJson = urlJson.replace(/XXX/g, token);
settings.url = urlJson;
$.ajax(settings).done(function(response) {
console.log(response);
toGetUpcomingMatches(response);
});
}
Now i want to convert this ajax method into http request so that i can use the data on the server using nodejs.
Here is the code:-
const { db } = require("../../utility/admin");
var request = require("request");
// //*************************** API INITIALIZATION ********************************
var settings = {
async: true,
//crossDomain: true,
url: "https://rest.cricketapi.com/rest/v2/schedule/?access_token=XXX"
//"url": "https://rest.cricketapi.com/rest/v2/match/indaus_2020_one-day_02/?access_token=XXX"
//bblt20_2019_g28
};
var options = {
method: "POST",
// hostname: "https://rest.cricketapi.com",
uri: "https://rest.cricketapi.com/rest/v2/auth/",
access_key: "********************************",
secret_key: "********************************",
app_id: "http://localhost:8000/",
device_id: "developer"
};
let token;
function getToken() {
request(options, function(error, response, body) {
if (error) {
console.log(error);
} else {
console.log(body);
token = body.auth.access_token;
console.log(token);
// console.log(response);
}
});
}
module.exports = { getToken };
But i am not able to access the data from the api when i am using the nodejs code.
Thanks in advance
👨‍🏫 For an example, you can look at this code below: 👇
var options = {
method: "POST",
// hostname: "https://rest.cricketapi.com",
uri: "https://rest.cricketapi.com/rest/v2/auth/",
// make sure, on this API, use body or headers.
// If body, you can change this `headers` to `form`.
headers: {
access_key: "********************************",
secret_key: "********************************",
app_id: "http://localhost:8000/",
device_id: "developer"
}
};
let token;
function getToken() {
return new Promise((resolve, reject) => {
request(options, function(error, response, body) {
if (error) return reject(error)
body = JSON.parse(body);
console.log(body);
token = body.auth.access_token;
return resolve(token);
});
})
}
I hope it can help you 🙏.

Using nodejs how can I return an object containing all the data from a batch of API calls in a loop?

I'm aware of closures and callbacks in JavaScript but it's obvious I don't get them on an intuitive level.
I have a small app that is scraping data from an API and I can easily console.log the responses from each request, my problem is I'm trying to gather the data and build an object to save to a file when all requests are complete.
I get that nodejs is a single thread of execution and it doesn't block but I can't figure out where to put the call backs when all the inner requests are finished I can console.log the built object. You'll see my console.log lines are in the wrong place and execute before the first response from the inner request.
Breakdown
Fetch country data
Loop over countryResponse and use each country id to fetch details
Add each detail to an array
Add array to object when all requests are complete.
code
const limit = require("simple-rate-limiter");
let request = limit(require("request")).to(1).per(200);
let options = {
method: 'POST',
url: 'https://myendpoint/details',
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json'
},
body: {
"token": "TOKEN",
"method": "countries"
},
json: true
};
global.package = {};
global.services = {};
let countryServices = [];
/*
Country fetch
*/
request(options, function (err, response, countryResponse) {
if (err) {}
package.countries = countryResponse;
countryResponse.forEach(function (entry) {
let innerOptions = {
method: 'POST',
url: 'https://myendpoint/details',
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json'
},
body: {
"token": "TOKEN",
"method": "services"
},
json: true
};
//THIS LINE OMG
//let countryServices = [];
innerOptions.body.countryCode = entry.countryCode;
request(innerOptions, function (err, response, innerResponse) {
if (err) {}
countryServices.push(innerResponse);
console.log(" inner response " + entry.countryCode + ' : ' + JSON.stringify(innerResponse, null, ""));
});//END innerResponse
});//END countryResponse.forEach
services = countryServices;
console.log(JSON.stringify(package, null, ""));
console.log(JSON.stringify(countryServices, null, ""));
});//END orderResponse
countryResponse
[
{
"countryCode": 1,
"countryName": "Virgin Islands (U.S.)"
},
{
"countryCode": 7,
"countryName": "Russian Federation"
}
]
innerResponse
[
{
"Type": "1",
"id": 2
},
{
"Type": "2",
"id": 3
}
]
The most concise and straightforward way to do this may be async/await way. You can manually promisify request and replace simple-rate-limiter dependency with simple delay:
'use strict';
const request = require('request');
function promisifiedRequest(options) {
return new Promise((resolve, reject) => {
request(options, (err, response, body) => {
if (err) reject(err);
else resolve(body);
});
});
}
function delay(ms) {
return new Promise((resolve) => { setTimeout(resolve, ms); });
}
const options = {
method: 'POST',
url: 'https://myendpoint/details',
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json',
},
body: {
token: 'TOKEN',
method: 'countries',
},
json: true,
};
(async function main() {
try {
const countryResponse = await promisifiedRequest(options);
const innerRequests = [];
for (const entry of countryResponse) {
const innerOptions = {
method: 'POST',
url: 'https://myendpoint/details',
headers: {
'cache-control': 'no-cache',
'Content-Type': 'application/json',
},
body: {
token: 'TOKEN',
method: 'services',
countryCode: entry.countryCode,
},
json: true,
};
const innerRequest = promisifiedRequest(innerOptions);
innerRequests.push(innerRequest);
await delay(200);
}
const countryServices = await Promise.all(innerRequests);
console.log(JSON.stringify(countryServices, null, ''));
} catch (err) {
console.error(err);
}
})();
These materials can be helpful if you want more background or need to scale your app (add parallel requests with more complicated rate limits):
Stackoverflow: How do I return the response from an asynchronous call?
Stackoverflow: Why is my variable unaltered after I modify it inside of a function?
Handling asynchronous operations in parallel
Back-off and retry using JavaScript arrays and promises
The console.logs at the end of your code won't wait for all the asynchronous operations fired off by your forEach to complete before they run. You'll need to introduce some kind of mechanism that waits for all the functions fired by forEach to complete their requests.
If you want to stick with using callbacks, then you could take a look at using something like the each method of async, which will handle this kind of situation for you.
This problem is commonly handled using Promises and async/await. If you used a promise based interface to request, your example would look something like this, assuming a fairly up to date version of Node.js (options omitted):
const request = require('request-promise');
async function run() {
const options = {};
const countryServices = [];
const countryResponse = await request(options);
for (const country of countryResponse) {
const innerOptions = {};
const innerResponse = await request(innerOptions);
countryServices.push(innerResponse);
}
console.log(countryServices);
}
run();
This is a bit clearer than using callbacks, and the for-of loop behaves exactly how you would expect.

Node JS Request Printing nothing in console

I'm making an post call using the nodejs requests module. However, the console.log statements seems to be not working for either the error or the response.body that I am trying to get.
My POST request needs the following headers -
Accept : "application/json"
Content-Type : "application/json"
Authorization : Basic + Base64Encoded(username+password)
The post body is something like this
Body:
{
"arg_1" : "a_string_key"
, "arg_2" : "a_string"
, "arg_3" : "a_string"
, "arg_4" : "some_value"
, "arg_5" : "some_string"
, "arg_6" : "<yyyy-mm-dd>"
, "arg_7" : "<yyyy-mm-dd>"
}
My code does nothing but send a POST request and checks if the response.statusCode ==200
Here is what I am doing
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'URL_I_WANT',
// method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
}
console.log('Before request');
request.post(options, function(error, response) {
if (error) {
console.log(error);
}
try {
if (!error && response.statusCode == 200) {
console.log(response.body);
console.log('Success');
}
} catch (error) {
console.log(error)
}
});
console.log('After request');
The code runs without any glitch and I get the before and after request console statements. However the statements inside the requests do not appear in the console, which means my request is not going through. I am not able to understand this. Shouldn't an error come if there is an issue with the request itself? Any if the request is failing, why isn't the error printed out?
This could be because your node process is auto-closed and it will exit before the async request to finishes (haven't looked into it but it might be something configurable). I've seen such set-up on repl.it for example.
To overcome this(if not configurable), you could wrap your code in an async function and use the request-promise to call await request.
var request = require('request-promise-native');
var int_user = "username";
var int_pass = "password";
var encoding = "base64"
var auth = "Basic" + new Buffer(int_user + int_pass).toString(encoding);
var headers = {
"Accept": "application/json",
"Content-Type": "application/json",
"Authorization": auth
}
var options = {
url: 'https://google.com',
method: 'POST',
headers: headers,
body : {
"arg_1": "a_string_key",
"arg_2": "a_string",
"arg_3": "a_string",
"arg_4": "some_value",
"arg_5": "some_string",
"arg_6": "<yyyy-mm-dd>",
"arg_7": "<yyyy-mm-dd>"
},
json: true
};
console.log('Before request');
async function main() {
try {
const response = await request.post(options);
if (response.statusCode === 200) {
console.log(response.body);
console.log('Success');
process.exit();
}
console.log(`Bad statusCode:${response.statusCode}`);
}
catch (error) {
console.log(error);
}
}
main();
you can check-out the code below
a link to the code above, working on repl.it

Nodejs Execute methods of an object only after the object has been initialized

I'm trying to create a module in nodejs so i create an Object called Client that has his constructor and some methods.
The problem is that the constructor run an async request (using request) and methods need things from construction to be invoked correctly.
How i can make the contructor synchronous?
function Client(id){
var token;
o = {
method: 'POST',
url: url + '/getToken',
headers: headers,
json: true,
body: id }
request(o).then(function(body) {
token = JSON.parse(body).token
})
function getValue(){
return new Promise(function(ff, rj) {
o = {
method: 'GET',
url: url + '?token=' + token,
headers: headers
}
request(o).then(function(body) {
ff(JSON.parse(body).value)
})
})
}
return{
getValue
}
}
I want to do something like this
var client = Client(id)
client.getValue().then(console.log)
but, because of async of request, when getValue return an error (token doesn't have a value yet)
How i can do that? Thank you
You should take in token as a dependency and do the async separately, perhaps in some kind of factory function.
function Client(token) {
this.getValue = function () {
return request({
method: 'GET',
url: url + '?token=' + token,
headers: headers
}).then(function (body) {
// Notice that you can return a synchronous value instead of a
// promise here. It will be wrapped in a promise and the next
// .then call will receive this returned value.
return JSON.parse(body).value;
});
}
}
function clientFactory (id) {
return request({
method: 'POST',
url: url + '/getToken',
headers: headers,
json: true,
body: id
}).then(function (body) {
var token = JSON.parse(body).token;
return new Client(token);
});
}
Or if you want to use es6 classes & arrow functions:
class Client {
constructor (token) {
this.token = token;
}
getValue () {
return request({
method: 'GET',
url: `${url}?token=${this.token}`,
headers: headers
}).then((body) => JSON.parse(body).value);
}
}
function clientFactory (id) {
return request({
method: 'POST',
url: `${url}/getToken`,
headers: headers,
json: true,
body: id
}).then((body) => new Client(JSON.parse(body).token));
}
The es6 class example is actually better because you're not recreating the getValue method for every new instance of Client. To make the first example as performant as the es6 example, you'd have to do it like this:
function Client(token) {
this.token = token;
}
Client.prototype.getValue = function () {
return request({
method: 'GET',
url: url + '?token=' + this.token,
headers: headers
}).then(function (body) {
return JSON.parse(body).value;
});
};
Now you should be able to do something like this:
var client = clientFactory(id).then(function (client) {
client.getValue().then(console.log);
});

Resources