I'm using the webcams.travel API from RapidAPI (link to API doc) and I've set everything up using browserify, unirest, node, require, etc.
The API response is in json and the Response Header is being output, but the Response Body is supposed to give me an object with webcams, but instead it shows as "undefined". This is my output now:
image of the console output
Is the problem in the parsing of the json, or does it have something to do with unirest?
I'm thankful for any help.
Code in my app.js (which is the suggested request snippet from the API site):
var unirest = require('unirest');
unirest.get("https://webcamstravel.p.rapidapi.com/webcams/list/continent=AN?lang=en&show=webcams%3Aimage%2Clocation")
.header("X-RapidAPI-Key", "MY_RAPID_API_KEY")
.end(function (result) {
console.log(result.status, result.headers, result.body);
});
Following up because I got interest—I eventually solved this issue when I encountered it with Imgur’s API by using the Fetch API instead of Unirest. There seems to be some issue with RapidAPI and Unirest, but when I contacted support they were unaware of any issues.
I recommend trying fetch() if you’re still encountering this.
Related
I am having trouble with the authentication process for the GoogleAPI. In the end I want to be able to read the users steps using the GoogleFit API and then store that value in a database. Currently I'm using restdb.io and executing javascript in codehooks.
The documentation from Google that I am following can be found here, clicking on the HTTP/REST option in the code examples. At the moment I am at step 5: I have gotten the users authentication code and stored it in the database. Now I have to POST the code along with some other parameters and get the access and refresh tokens.
If the POST is successful (from what I understand) I should get back a 200-OK message that the request was valid. Google will then POST a JSON body with the access and refresh token to the redirect_uri that I have specified in my GoogleAPI credentials page and the initial request. At redirect_uri I have to handle the request and save the two values.
The problem is that I receive a redirect_uri_mismatch - Bad Request message from Google as a response when executing the request. I get it at the log.debug("ERROR HERE: " + [...]); in the code below:
async function mainFunction(){
const authCode = THIS_IS_MY_AUTHENTICATION_CODE;
try {
var answer = await postRequestToGoogle(authCode);
//do stuff with response from Google
} catch (error) {
//do stuff
}
}
async function postRequestToGoogle(authCode){
//body for the request
const params = "code=" + authCode + "&" +
"client_id=THIS_IS_MY_CLIENT_ID" + "&" +
"client_secret=THIS_IS_MY_CLIENT_SECRET" + "&" +
"redirect_uri=THIS_IS_MY_REDIRECT_URI" + "&" +
"grant_type=authorization_code";
try{
const result = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: params})
.then(res => {
log.debug("ERROR HERE: " + JSON.stringify(res.json()));
return res.json();
})
//return JSON back main function
return result;
}catch(error){
//do stuff
}
}
I looked up the error message and tried some things:
Copy and pasted multiple different Authorized redirect URI from the GoogleAPI credentials page into the code to make sure that there is no problem with
http/https
www/no www
trailing slashes
typos or capitalization
Waited for changes to be processed by Google (read that it can more than 30min)
Changed all the other parameters to see if the redirect_uri is actually the problem
If code is changed the message is invalid_grant - Bad Request
If client_id is changed the message is invalid_client - The OAuth client was not found
If client_secret is changed the message is invalid_client - Unauthorized
If the grant_type is changed the message is unsupported_grant_type - Invalid grant_type
That's why I think the issue is the redirect_uri, but it's unclear to me how since I copy&pasted it. Something that came to mind was that maybe the value of redirect_uri gets changed when it's read by Google? Or maybe when the request is being put together? Do some characters have to be replaced?
I tried to analyze the request with Wireshark but didn't think about the fact that it's HTTPS so I would have I would have to decrypt it.. Is that something I should look into?
Thank you for taking the time to read all of this! If you have any advice please let me know :)
Update 16.11.20:
I have created a new OAuth 2.0 Client ID and used the new id/secret in my request. The resulting message the same as before. I will wait and try again tomorrow to see if maybe Google needs some more time. Then I'll try to delete all current IDs and start with a fresh GoogleAPI project.
Update 19.11.20:
Creating a new OAuth 2.0 Client ID did not resolve my problem, neither did creating a whole new GoogleAPI project and adding those credentials into the request. I am in contact with the developers of restdb.io and have asked them to add the Google Auth Library: Node.js Client to the list of supported Node.js packages. Hopefully that will help, I will give it a try as soon as it can be used :)
Update 02.12.20:
No progress so far, but I'm optimistic that the developers will add the package soon. I will post a final update as soon as I am done with this project.
EDIT: Solved, posted details below as answer... Pretty stupid user error
I'm trying to write simple plugin for SteelSeries Gamesense to display currently playing song from iTunes in GameDAC screen. Basically the engine works via provided server listening to post requests with JSON body. I've been trying to get my request working for quite a while but with no go.
I tested request on Postman and it should be working as intended, so the problem is somewhere in syntax probably.
const axios = require('axios');
const coreProps = require(process.env.ProgramData + '/SteelSeries/SteelSeries Engine 3/coreProps.json');
const url = JSON.stringify(coreProps['address']);
axios.defaults.baseURL = 'http://' + url.replace(/"/g,'');
axios.defaults.headers['post'] = {'Content-Type': 'application/json'};
console.log(axios.defaults.headers);
function bind_itunes() {
const data = {
"game": "ITUNES",
"event": "NOWPLAYING",
"handlers": [
{
"device-type": "screened",
"zone": "one",
"mode": "screen",
"datas": [
{
"has-text": true,
"context-frame-key": "songname"
}
]
}
]
};
axios.post('game_event', JSON.stringify(data))
.then((res) => {
console.log(res)
}).catch((error) => {
console.error(error)
})
}
bind_itunes();
Code fails with long error block from Axios with error
"data: { error: 'passed value not string or JSON object' } }"
full error log (pastebin since it's quite long): https://pastebin.com/aLguKQ2C
Postman screenshot
Next time before asking question, I'll also make sure to triple check the API endpoints.
As seen when comparing the screenshot and code, I'm polling on wrong endpoint (game_event instead of bind_game_event), which quite obviously causes request to be bad.
Fixed the problem after hours and hours of wondering.
Thanks for assistance to everybody who tried and sorry to bother.
I would have suggested the same as #Phil: not to stringify your payload when using axios.post. The examples in the documentation of Axios might be useful: https://github.com/axios/axios. I took a look at your screenshot, it seems that you got a successful response with a status code of 200. Are you still having an issue or is the response to your request different?
Working on creating a custom zapier integration using zapier CLI. My API endpoint is not technically a create, but it uses the POST method so I made it under the create definition in zapier. I set my output fields to empty, but it breaks on my empty response object.
outputFields: []
The error message:
We had trouble sending your test through.
Unexpected end of JSON input
Hide details
Troubleshooting Errors | Contact Support
What happened (You are seeing this because you are an admin):
Starting POST request to https://api.fake.com/v2/demo-finance/live/csh-search
Received 202 code from https://api.fake.com/v2/demo-finance/live/csh-search after 596ms
Received content ""
Unexpected end of JSON input
Everything is working as expected the request went through it is just not happy with the empty string response not being valid JSON. Is there some way to tell zapier this is an acceptable response object?
David here, from the Zapier Platform team.
It's fine if your API works that way, but you still need to return something json serializable from your function. Try something like this:
const performCreate = async (z, bundle) => {
const response = await z.request('https://api.fake.com/v2/demo-finance/live/csh-search')
if (response.statusCode === 202) {
return {}
}
// handle errors, other cases, whatever
// just make sure to return an object
}
As a side note, just because the request uses a POST request doesn't mean it needs to be a Create; it should be whatever type makes the most sense for the operation. If it's a search (like the fake url suggests) a search is probably the way to go.
I am attempting to get this tutorial (here: https://www.hellorust.com/demos/add/index.html) to work, and it seems that whatever I do, I cannot get the WebAssembly MDN reserved function to properly work.
So, I followed the instructions on the link above and got an add.wasm file. As far as I can tell this should be fairly simple and should work. After a little digging I found that the newest WebAssembly module is to instantiate streaming - the documentation for which can be found here: (https://developer.mozilla.org/en-US/docs/WebAssembly/Using_the_JavaScript_API).
The MDN example says to do the following:
var importObject = {
imports: { imported_func: arg => console.log(arg) }
};
then
WebAssembly.instantiateStreaming(fetch('simple.wasm'), importObject)
.then(obj => obj.instance.exports.exported_func());
According to MDN the importObject is to unwrap the nested argument. Weird, but OK.
To make this as simple as possible I put the add.wasm file and the js file that would import it in the same directory and then did then following (NOTE: I am using Vue.js, but for anyone familiar with SPA like libraries this should be similar):
window.WebAssembly.instantiateStreaming(fetch('./add.wasm', {
headers: {
"Content-Type": "application/wasm",
},
}), importObject)
.then(obj => {
console.log('inside return obj from WebAssembly initiateStreaming')
obj => obj.instance.exports.exported_func()
})
.catch(error=>{
console.log('there was some error; ', error)
});
The error I get back is:
there was some error; TypeError: "Response has unsupported MIME type"
I've tried not adding the header to the fetch request, using fetch(add.wasm), dropping the window., dropping the importObject entirely and simple logging obj to console. Nothing appears to work.
It may be that I have to add the application/wasm field to webpack somehow if it is not widely supported, but I'm not sure and I haven't seen any examples online.
Does anyone know how to get this to work?
EDIT:
Someone suggested that since this was a fetch request it had to be making the request from a backend server. This made sense to me, so I did the following:
WebAssembly.instantiateStreaming(fetch('http://localhost:8000/files/add.wasm'), importObject)
.then(obj => {
console.log('inside return obj from WebAssembly initiateStreaming')
obj => obj.instance.exports.exported_func()
})
.catch(error=>{
console.log('there was some error; ', error)
});
Where http://localhost:8000/files/{someFile} is a backend route that serves my files (which I made sure to put add.wasm in of course). Unfortunately, I get the same error (i.e. unrecognized MIME type) and I'm not sure why.
Considering you can't change the server to properly return application/wasm for .wasm file requests for any reason, you can work around the issue by changing the way you instantiate the WebAssembly module. Instead of doing this:
WebAssembly.instantiateStreaming(fetch("./add.wasm")).then(obj => /* ... */)
Do this:
const response = await fetch("add.wasm");
const buffer = await response.arrayBuffer();
const obj = await WebAssembly.instantiate(buffer);
obj.instance.exports.exported_func();
Or the equivalent using then() if you cannot use async/await.
In practice, what my workaround does is to avoid calling instantiateStreaming(), which must check the MIME type returned by the server before proceeding (according to this specification). Instead, I call instantiate() passing an ArrayBuffer and avoid the check altogether.
there was some error; TypeError: "Response has unsupported MIME type"
The Web server you are running does not understands/serves a MIME type application/wasm.
You can use a rust based http server, it knows about wasm MIME type.
Installation
Simply use curl
curl -SsL https://cdn.rawgit.com/thecoshman/http/master/install.sh | sh
and execute the downloaded script or you can explorer other ways to do the same at https://crates.io/crates/https.
Running
Please use the downloaded server to server your Web Application(index.html).
e.g
cd ${YOUR_APPS_PATH}
http
A snippet of code for a workaround has been published on the WebAssembly Git here. Unfortunately, this is a workaround, and this defeats the purpose of instantiateStreaming() which is told here to be "a lot more efficient", since the workaround needs an ArrayBuffer that instantiateStreaming() helps to avoid.
James Wilson's "wasm-fractal" project deals with the error, like this:
importScripts("wasm_fractal.js");
delete WebAssembly.instantiateStreaming;
wasmFractal("./wasm_fractal_bg.wasm").then((wasm) => {
// establish connection between wasm and javascript
});
I use the delete WebAssembly.instantiateStreaming; trick myself during development, since my editor's builtin server, serves wasm with the incorrect mime type.
I am trying to catch a POST request with an empty body before it causes my server to crash. I've seen people using bodyparser but I am using the MVC model and basically I don't have references to app in this .js file.
var resource = req.body;
if(!resource) return res.status(400).send("Your request is missing details.");
I was told to try something like this but it still does not work. When I console.log resource it appears as "{}" even when no body was added in postman, so the null check doesn't work. If anyone has any advice I would appreciate it!
You can use:
if(Object.keys(req.body).length === 0)
or Object.getOwnPropertyNames(req.body).length == 0
And then your logic to respond to the user.