I'm trying to post an image to restdb media archive, I followed the instructions on their website https://restdb.io/blog/a-picture-is-worth-a-1000-lines-of-code
but all I get is a error
here is my code:
async function fetchPost(url, data) {
let answer
try {
const response = await fetch(url, {
method: 'post', // *GET, POST, PUT, DELETE, etc.
headers: {
'content-type': false,
'x-apikey': '62050e461b941c73ff397a3f',
},
processData: 'false',
body: data,
})
answer = await response.json()
} catch (err) {
console.log(err)
} finally {
return answer
}
}
let formData = new FormData()
formData.append('myFile', e.target.files[0], e.target.files[0].name)
fetchPost('https://mikey-f985.restdb.io/media', formData)
And Here is my API key (CORS)
Just in case you are on the free plan: I had the same issue with GET requests, so i asked restdb directly for help and they answered:
"Yes you can store images for use in development. But to serve them public you need a paid account."
Related
TL;DR: How to actually change a request header in http-proxy-middleware?
To get around some CORS errors I set up a local proxy using the http-proxy-middleware module. In addition to setting the mode of my request to "no-cors" I need to change an additional header: "Content-Type". However, this seems to be not working. In fact, I cannot even change the response headers on a redirected (through my proxy) request. For local requests (fetching pages etc) I am able to change the response headers but even then I am unable to change the request headers.
This is my setupProxy.js:
const { createProxyMiddleware } = require("http-proxy-middleware");
module.exports = function (app) {
app.use((req, res, next) => {
req.header("Content-Type", "application/json");
res.header("Access-Control-Allow-Origin", "*");
next();
});
function onProxyReq(proxyReq, req, res) {
console.log("test 1");
proxyReq.setHeader("Content-Type", "application/json");
req.header("Content-Type", "application/json");
}
app.use(
"/api",
createProxyMiddleware({
target: "https://my-domain.com/",
changeOrigin: true,
onProxyReg: { onProxyReq },
// secure: true,
// on: {
// proxyReq: requestInterceptor(async (buffer, proxyReq, req, res) => {
// console.log("test 2");
// }),
// },
logger: console,
})
);
};
And this is the code that sends the request:
try {
let requestOptions: RequestInit = {
method: "POST",
mode: "no-cors",
headers: {
accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
email: { username },
password: { password },
}),
};
fetch("https://localhost:3000/api/path/to/login/api", requestOptions)
.then(async function (response) {
console.log(response);
if (!response.ok) {
setError("Error code: " + response.status.toString());
}
return response.json();
})
.then(function (response) {
console.log(response);
});
} catch (e) {
console.log(e);
}
I'm getting an error back from the API itself (the CORS avoidance is working):
Content type 'text/plain;charset=UTF-8' not supported
And indeed, when I use the Chrome inspector to look at the request, the request header is set to "text/plain;charset=UTF-8". I tried setting the response header content type to "text/plain" but even that remains untouched. But how can this be after routing the request through my proxy?
EDIT:
Ok so I found out part of the problem. Setting the mode to "no-cors" in my fetch request alters the headers. But this still doesn't explain why my proxy can't edit the request headers. When I remove the "no-cors" mode but copy the headers it produced, the server is giving me error 400 (bad request). This means it is not receiving the same request as before, but this baffles me since I copied all the headers manually.
EDIT2:
Actually, I found out that when I remove mode: "no-cors" and set the "Sec-Fetch-Mode" header to "no-cors" manually, it is still set to "cors" in the actual request!
EDIT3:
I tried sending my request through ReqBin and it works there :)! So at least we know my request is correct.
I found out that changing the "content-type" header in cors mode is simply not allowed. The solution is to first send a preflight request with the options. When this has been accepted, you can send the actual request.
You can send the request through ReqBin, it will take the necessary steps to complete the request succesfully. It will even generate code to reproduce the request for you.
var url = "https://thedomain.com/path/to/api";
var xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.setRequestHeader("Content-Type", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.status);
console.log(xhr.responseText);
}
};
var data_ = '{"email": "*************", "password": "******"}';
xhr.send(data_);
And this works! :)
I have problem with CORS: Access-Control-Allow-Origin when try to exchange the code for access token from Instagram API.
Instagram API documentation Step 5 : https://developers.facebook.com/docs/instagram-basic-display-api/getting-started#step-5--exchange-the-code-for-a-token
Body parametars:
const body = {
'client_id': 'xxxxxxxxxxxxxx',
'client_secret': 'xxxxxxxxxxxxxx',
'grant_type': 'authorization_code',
'redirect_uri': 'https://localhost:3000/',
'code': instaCode
};
My request:
axios.post(`https://api.instagram.com/oauth/access_token`, qs.stringify(body), {
headers: {'content-type': 'application/x-www-form-urlencoded'}
});
Đ¢his code worked 2 months ago.
edit: you can try this axios post request to send form data first which seems better, below worked for me though
That won't work, you have to send the body in a form data.
I believe fetch API would work but that's available since node 17, if you're using earlier version this is what worked for me.
SOURCE https://www.section.io/engineering-education/integrating-instagram-basic-display-api/
const { post } = require("request");
const { promisify } = require("util");
const postAsync = promisify(post);
const form = {
client_id: NUMBER,
client_secret: STRING,
grant_type: "authorization_code",
redirect_uri: STRING,
code: req.body.code,
};
let { body, statusCode } = await postAsync({
// let result = await postAsync({
url: "https://api.instagram.com/oauth/access_token",
form,
headers: {
"content-type": "multipart/form-data",
host: "api.instagram.com",
},
});
npm i request
and use that inside a try/catch of course
i need send this request with axios.
i need header as multipart request, like below
headers: {
"Content-type": "multipart/form-data",
},
I used spring boot for backend. It expect maltipart not application/json. I tried below code, But it not worked for multipart.
axios.delete(URL, {
headers: {
Authorization: authorizationToken
},
data: {
source: source
}
});
Thanks a lot #Sinan Yaman. I generated it using POSTMAN. Answer is
var axios = require('axios');
var FormData = require('form-data');
var data = new FormData();
data.append('keyName', 'project/photoes/1613388881570-note1.txt');
var config = {
method: 'delete',
url: 'localhost:8080/storage/deleteFile',
headers: {
...data.getHeaders()
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Typically before make frontend we test our backend with postman. For any type of frontend http calls code can automatically generate using postman. This is awesome feature of POSTMAN. Follow below steps.
Press the code button
Select the your backend code environment
I'm trying to put a video file to my bucket using a pre-signed url in angular4.
Node:
let s3 = new AWS.S3();
s3.config.update({
accessKeyId: process.env.VIDEO_ACCESS_KEY,
secretAccessKey: process.env.VIDEO_SECRET_KEY
})
let videoId = await Video.createVideo()
let params = {
ACL: "public-read",
Bucket: process.env.BUCKET_NAME,
ContentType: 'video/mp4',
Expires: 100,
Key: req.jwt.username+"/"+videoId,
}
return s3.getSignedUrl('putObject', params, function (err, url) {
if(!err) {
console.log(url);
res.status(200);
res.json({
url: url,
reference: `${process.env.BUCKET_NAME}/${req.jwt.username}/${videoId}`,
acl: params.ACL,
bucket: params.Bucket,
key: params.Key,
contentType: params.ContentType,
});
} else {
console.log(err);
res.status(400);
res.json({
message: "Something went wrong"
})
}
});
This successfully generates a url for me, and I try to use it in my post request in the front end.
Angular:
this.auth.fileUpload().subscribe((result) => {
console.log(result["key"], result["acl"], result["bucket"], result["contentType"])
if(!result["message"]) {
let formData = new FormData();
formData.append('file', file.files[0]);
const httpOptions = {
headers: new HttpHeaders({
"Key": result["key"],
"ACL": result["acl"],
"Bucket": result["bucket"],
"Content-Type": result["contentType"],
})
};
this.http.post(result["url"], formData, httpOptions ).subscribe((response) => {
console.log("response");
console.log(response);
let reference = `https://s3.amazonaws.com/${result["reference"]}`
this.auth.makeVideo(result["reference"]).subscribe((result) => {
console.log(result);
});
}, (error) => {
console.log("error");
console.log(error);
})
But this generates an error.
SignatureDoesNotMatch
The request signature we calculated does not match the signature you provided. Check your key and signing method
Here's the URL that I generate
https://MY_BUCKET_HERE.s3.amazonaws.com/admin/87f314f1-9f2e-462e-84ff-25cba958ac50?AWSAccessKeyId=MY_ACCESS_KEY_HERE&Content-Type=video%2Fmp4&Expires=1520368428&Signature=Ks0wfzGyXmBTiAxGkHNgcYblpX8%3D&x-amz-acl=public-read
I'm pretty sure I'm just making a simple mistake, but I can't figure it out for the life of me. Do I need to do something with my headers? Do I need to change the way I read the file for the post? I've gotten it to work with a public bucket with FormData and a simple post request with no headers, but now that I'm working with Policies and a private bucket, my understanding is much less. What am I doing wrong?
If you generate a pre-signed URL for PutObject then you should use the HTTP PUT method to upload your file to that pre-signed URL. The POST method won't work (it's designed for browser uploads).
Also, don't supply HTTP headers when you invoke the PUT. They should be supplied when generating the pre-signed URL, but not when using the pre-signed URL.
i am trying to send a POST request from my angularjs controller to the nodejs server which should then send a full POST request to the external API and this way avoid CORS request as well as make it more secure as i'm sending relatively private data in this POST request.
My angularjs controller function for making the post request to the nodejs server looks like this and it works fine:
var noteData = {
"id":accountNumber,
"notes":[
{
"lId":707414,
"oId":1369944,
"nId":4154191,
"price":23.84
}
]
}
var req = {
method: 'POST',
url: '/note',
data: noteData
}
$http(req).then(function(data){
console.log(data);
});
Now the problem lies in my nodejs server where i just can't seem to figure out how to properly send a POST request with custom headers and pass a JSON data variable..
i've trierd using the nodejs https function since the url i need to access is an https one and not http ,i've also tried the request function with no luck.
I know that the url and data i'm sending is correct since when i plug them into Postman it returns what i expect it to return.
Here are my different attempts on nodejs server:
The data from angularjs request is parsed and retrieved correctly using body-parser
Attempt Using Request:
app.post('/buyNote', function (req, res) {
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
},
data = JSON.stringify(req.body);
};
request(options, function (error, response, body) {
if (!error) {
// Print out the response body
// console.log(body)
console.log(response.statusCode);
res.sendStatus(200);
} else {
console.log(error);
}
})
This returns status code 500 for some reason, it's sending the data wrongly and hence why the server error...
Using https
var options = {
url: 'https://api.lendingclub.com/api/investor/v1/accounts/' + accountNumber + '/trades/buy/',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': apiKey
}
};
var data = JSON.stringify(req.body);
var req = https.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.log(`problem with request: ${e.message}`);
});
req.write(data);
req.end();
Https attempt return a 301 status for some reasons...
Using the same data, headers and the url in Postman returns a successful response 200 with the data i need...
I don't understand how i can make a simple http request...
Please note: this is my first project working with nodejs and angular, i would know how to implement something like this in php or java easily, but this is boggling me..
So after a lot of messing around and trying different things i have finally found the solution that performs well and does exactly what i need without over complicating things:
Using the module called request-promise is what did the trick. Here's the code that i used for it:
const request = require('request-promise');
const options = {
method: 'POST',
uri: 'https://requestedAPIsource.com/api',
body: req.body,
json: true,
headers: {
'Content-Type': 'application/json',
'Authorization': 'bwejjr33333333333'
}
}
request(options).then(function (response){
res.status(200).json(response);
})
.catch(function (err) {
console.log(err);
})