I have a problem with using Imgur API. I received clientId for anon uploading of media files. Then I tried to use this credentials for API requests. I had problems with using 'https://api.imgur.com/3/upload' route for uploading from the client browser Javascript, but then I found that 'https://api.imgur.com/3/image' works as expected with images uploading (in base64 format), but not working as expected with video uploading (in binary format, because of base64 returns error), after changing method of sending video in binary format doing few requests I managed to receive 200 response code, but the only info I received (besides status info) was 'ticket' field, and nothing else (no error message or code). And I don't know how to use this info to get access to the uploaded video. This type of response not documented anywhere and I'm not really sure it should be working like it is now. Can you please help me with this case? Maybe someone had a similar situation. I have attached 'har' request info from Chrome so that you could see how I made a request, maybe I did mistake somewhere. Really waiting for your answer, thanks!
HAR request info
Send file function:
sendFile = async (fileObj) => {
const myHeaders = new Headers();
myHeaders.append('Authorization', uploadCredentials);
const formData = new FormData(),
{
type
} = fileObj,
fileTitle = fileObj.file.name.split('.').shift(),
splitDataMarker = ';base64,';
let fileData;
if (type === 'image') {
const indexOfMarker = fileObj.data.indexOf(splitDataMarker),
indexOfDataStart = indexOfMarker ? indexOfMarker + splitDataMarker.length : 0;
fileData = fileObj.data.substr(indexOfDataStart);
formData.append('type', 'base64');
} else if (type === 'video') {
formData.append('type', 'file');
const res = await fetch(fileObj.data);
fileData = await res.blob();
}
formData.append(type, fileData);
formData.append('name', fileObj.file.name);
formData.append('title', fileTitle);
const requestOptions: any = {
method: 'POST',
headers: myHeaders,
body: formData,
redirect: 'follow',
};
try {
const res = await fetch(uploadUrl, requestOptions),
data = await res.json();
return data;
} catch (error) {
throw Error(error);
}
},
Your question is answered here: https://stackoverflow.com/a/57240243
In short: for videos you need to use the /upload api endpoint and include a file with a name of video.
If you are including the file as a base64 encoded value in the POST body then you need to set the type to base64, if it is attached, then you need to set the type to file:
# If base64 body data:
curl --location --request POST 'https://api.imgur.com/3/upload' --header 'Authorization: Client-ID 3a49f81624b9a16' --data 'image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&type=base64&disable_audio=0'
CLIENT_ID=3a49f81624b9a16; curl --location --request POST 'https://api.imgur.com/3/upload' --header "Authorization: Client-ID $CLIENT_ID" --data 'image=R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7&type=base64&disable_audio=0'
# If reading file (in this case, from stdin:
echo 'R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' | base64 --decode | curl --location --request POST 'https://api.imgur.com/3/upload' --header "Authorization: Client-ID $CLIENT_ID" -F 'type=file' -F 'disable_audio=0' -F 'image=#-'
In both examples above, for a video, change image= to video=
Related
I m newbie who is learning to play with API. I m getting POST req error while using axios.
In docs of API which I want to interact, they give curl example.
curl -X POST https://ssuploader.streamsb.com/upload/01
-d "api_key=948324jkl3h45h"
-d "#path/filename.mp4"
-H "Content-Type: application/x-www-form-urlencoded"
I am trying to make that POST request using axios. I wrote simple script like this.
const axiosConfig = {
headers : {
"Content-Type": "application/x-www-form-urlencoded"
}
}
const file = __dirname + "/video/Video.mp4";
const fileData = fs.readFileSync(file);
const data = `api_key=${API_KEY}&${fileData}`;
axios.post('https://ssuploader.streamsb.com/upload/01', data, axiosConfig).then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
I am getting this error.
Getting Error : AxiosError: getaddrinfo ENOTFOUND ssuploader.streamsb.com
I m really new to interacting with API, so that I thought some of my structure was wrong while converting curl to axios. I really don't know what to do. I mean I can't figure out my false. Can anyone help me? Thank you so much.
Some Changes
I figure out some of my false with the help of answers. I forget to GET the server first. So that I updated my code to this.
const file = __dirname + "/video/Video.mp4";
const fileData = fs.createReadStream(file);
const formData = new FormData();
formData.append('file', fileData);
formData.append('api_key', API_KEY);
console.log(formData)
axios.get(`https://api.streamsb.com/api/upload/server?key=${API_KEY}`).then(result => {
const url = result.data.result;
axios.post(url, formData, axiosConfig)
.then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
})
But I am getting new Error.
AxiosError: Request failed with status code 400
As I understand from the documentation this is 2 step process. At first you need to get the upload URL (server as they call it) and then use it to upload your file.
So use something like this:
axios.get(`https://api.streamsb.com/api/upload/server?key=${API_KEY}`).then((result) => {
const url = result.data.result;
// your post request to this url here
}).catch((err) => {
console.log("Getting Error : ", err);
});
You are sending fileData as a string in the data Object
Use 'Content-Type': 'multipart/form-data'instead of using "Content-Type": "application/x-www-form-urlencoded"
Code will be like this
import FormData from 'form-data';
const axiosConfig = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
const file = __dirname + "/video/Video.mp4";
const fileData = fs.createReadStream(file);
const formData = new FormData();
formData.append('file', fileData);
formData.append('api_key', API_KEY);
axios.post('https://ssuploader.streamsb.com/upload/01', formData, axiosConfig)
.then((result) => {
console.log(result.data);
}).catch((err) => {
console.log("Getting Error : ", err);
});
If you have any query, you can ask
It's them, not you.
There is no DNS record for ssuploader.streamsb.com (you can enter it into https://mxtoolbox.com/DNSLookup.aspx to check), which means that when you try to connect to it, it leads nowhere.
Unless you do some digging and find a domain from them that has a DNS record, there isn't anything you can do.
I made an external adapter from the Javascript External Adapter Template from Chainlink, trying to use the Client Credentials flow for Spotify's API to return artist data, documentation listed below.
https://developer.spotify.com/documentation/general/guides/authorization-guide/#client-credentials-flow
https://developer.spotify.com/console/get-artist/
and I am able to make the call just fine with this code through Axios
but when I try to run the same call through the External Adapter which uses Axios for it's API calls as well, I get this error.
Here is a snippet of the main code of the external adapter from index.js
const customParams = {
artist: [''],
endpoint: false
}
const createRequest = (input, callback) => {
// The Validator helps you validate the Chainlink request data
const apiID = process.env.API_ID
const apiKey = process.env.API_KEY
let token = 'BQDlkzka093OuR4tL7XyaI-Tag4R166FQGBSogBP6hEBxhsCjH8XfMRqs_apKFk0T87FGIrwPtT1bkuGCeE';
const validator = new Validator(callback, input, customParams)
const jobRunID = validator.validated.id
const endpoint = validator.validated.data.endpoint
const artistID = validator.validated.data.artist.toUpperCase()
const url = `https://api.spotify.com/v1/artists/${artistID}`
const params = {
artistID
}
// curl -X "GET" "https://api.spotify.com/v1/artists/5K4W6rqBFWDnAN6FQUkS6x" -H "Accept: application/json" -H "Content-Type: application/json" -H "Authorization: Bearer authtoken"
// This is where you would add method and headers
// you can add method like GET or POST and add it to the config
// The default is GET requests
// method = 'get'
// headers = 'headers.....'
const head = {
'Accept' : 'application/json',
'Content-Type' : 'application/json',
'Authorization' : 'Bearer ' + token
}
const config = {
url,
headers: head
}
console.log("config:", config)
and this is the command I am running in the terminal to pass in the Spotify Artist ID
curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "": "5K4W6rqBFWDnAN6FQUkS6x"} }'
-Edit-
Just to show that the code isn't all totally wrong, I am able to make a call through the external adapter to this url https://jsonplaceholder.typicode.com/posts/5, passing in the 5 with this command.
curl -X POST -H "content-type:application/json" "http://localhost:8080/" --data '{ "id": 0, "data": { "": "5"} }'
The issue was with this line, making the artist ID all uppercase.
const artistID = validator.validated.data.artist.toUpperCase() // Changed this
const artistID = validator.validated.data.artist // To this
I'm trying to call an API using javascript that contains a file in the POST request. The file is located at another URL that I have to grab before calling the API. I think I need to use a fetch to get the file data as a blob and then pass it along to the post request.
I have a working example in CURL but can't work out the syntax to translate it into JS.
Working example in CURL:
curl -X POST -H 'Authorization: Token token=****' -H 'Content-Type: multipart/form-data'
-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW' -F file=#/User/somefile.pdf -F file_name=nameForFile
-F is_shared=true -F targetable_id=1 -F targetable_type=Lead -X POST "https://endpoint.com/api/documents"
Javascript:
var formData = new FormData();
fetch("http://wheremyfileis.com/file.pdf")
.then(response => response.blob())
.then(fileData => {
var fileBlob = new Blob((fileData );
formData.append("targetable_id", 1);
formData.append("targetable_type", "Lead");
formData.append("file", fileBlob);
var headers = {"Authorization": "Token token=***", "Content-Type":"multipart/form-data"};
var options = { headers: headers, body: "Hello world"};
var url = "https://endpoint.com/api/documents";
client.request.post(url, options)
.then (
function(data) { console.log(data); },
function(error) {console.log(error);}
);
I'm getting a JSON parsing error when I try to fetch data from a server endpoint.
It's the first time that Axios cannot decode the JSON response automatically.
Debugging my code, I've seen that Axios catch some unexpected character in the server response that makes the JSON not valid.
7F5
{
"message": "OK"
...cut
}
0
Error:
(node:14940) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token F in JSON at position 1
I suppose that could be a charset encoding problem.
Axios client configuration:
const pclClient = axios.create({
baseURL: "http://server/endpoint",
responseType: "json",
responseEncoding: "utf8",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
charset: "utf-8"
}
});
Using tools like postman or Chrome Extension Advanced Request Client, the problem is not present.
Can someone help me?
The problem comes from transfer-encoding: chunked response header.
RFC 7230 tells that "A recipient MUST be able to parse and decode the chunked transfer
coding."
At the moment, Axios don't handle chunked responses (transfer-encoding chunked not handled for application/json)
To resolve this issue, I've made a chunk parser using regex to removing chunk's info.
const pclClient = axios.create({
baseURL: "http://server/",
responseType: "json",
headers: {
Accept: "application/json"
}
});
const chunksParser = body => {
return body
.replace(/^(\w{1,3})\r\n/, "") // replace header chunks info
.replace(/\r\n(\w{1,3})\r\n/, "") // replace in-body chunks info
.replace(/(\r\n0\r\n\r\n)$/, ""); // replace end chunks info
};
const getData = async () => {
response = await pclClient.get("data.json");
const { data } = response;
const body = chunksParser(data);
const json = JSON.parse(body);
return json;
};
I was looking for a built-in function inside Axios. I hope it will be available in the future.
Thank you for commenters that helped me to understand what was the problem.
I'm getting an error from dropbox api:
Error in call to API function "files/download": HTTP header "Dropbox-API-Arg": could not decode input as JSON.
let url = 'https://content.dropboxapi.com/2/files/download'
let headers = new Headers({ });
headers.append('Authorization', 'Bearer ...');
headers.append('Dropbox-API-Arg', '/readme.txt');
let options = new RequestOptions({ headers: headers });
this.http
.get(url, options)
.subscribe(this.fileContent)
this is the example they put on their api:
curl -X POST https://content.dropboxapi.com/2/files/download \
--header "Authorization: Bearer <get access token>" \
--header "Dropbox-API-Arg: {\"path\": \"/Homework/math/Prime_Numbers.txt\"}"
I might have gotten the headers wrong in angular I've never used them before.
Edit: path variable is a string equal to a file path. i.e. "readme.txt"
Did a quick google and found this: https://www.dropboxforum.com/t5/API-support/HTTP-header-quot-Dropbox-API-Arg-quot-could-not-decode-input-as/td-p/173822
Essentially the format for the variable path isn't in accordance to what the api expects.
I've added the utility function the link provides:
var charsToEncode = /[\u007f-\uffff]/g;
function http_header_safe_json(v) {
return JSON.stringify(v).replace(charsToEncode,
function(c) {
return '\\u'+('000'+c.charCodeAt(0).toString(16)).slice(-4);
}
);
}
EDIT
Your path variable should look like this:
var path = {
path: '/readme.txt'
};