Can't upload file to YouTube using API - reactjs

I keep getting a 401 error when I try to upload a file to YouTube on my application. This is the YouTube docs: https://developers.google.com/youtube/v3/docs/videos/insert
I'm using HTTP as the method for uploading. This is what YouTube suggests you to upload a video as you can do this without any meta data:
POST https://youtube.googleapis.com/youtube/v3/videos?key=[YOUR_API_KEY] HTTP/1.1
Authorization: Bearer [YOUR_ACCESS_TOKEN]
Accept: application/json
Content-Type: application/json
I have my application setup in a react/typescript environment, with a node/express backend.
This is how I have written the api call using axios:
export const UploadNewYouTubeVideo = (uploadFile: File, token: string) => {
return axios.post(
`https://youtube.googleapis.com/youtube/v3/videos?key=${process.env.REACT_APP_YOUTUBE_API_KEY}`,
uploadFile,
{
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/octet-stream",
},
}
);
};
I know the access token passed is correct for the YouTube channel as it successfully allows me to view/delete existing videos with that token.
For the frontend, I have a very simple useState hook that changes to the inputted file on input:
<input
id="file-upload"
name="file-upload"
type="file"
className="sr-only"
onChange={(e) =>
e?.target.files !== null &&
setUploadFile(e?.target?.files[0])
}
/>
This corresponds to a simple function that calls that api when a button called "Upload" is pushed:
const UploadVideo = () => {
if (uploadFile) {
setIsUploading(true);
return UploadNewYouTubeVideo(uploadFile, token)
.then((res) => console.log(res))
.catch((e) => console.log("Error Uploading", e.message));
}
};
This is the 401 error I keep getting (note: I hid my secret key here with XXXX):
xhr.js:210 POST https://youtube.googleapis.com/youtube/v3/videos?key=XXXXXXXXXXXXXX net::ERR_FILE_NOT_FOUND
The file is definitely being saved to state and passed to the post request:
I'd appreciate any help you guys may have.
EDIT: I'm getting a 400 error now, which I think is the mediaBodyRequired error. Which im puzzled about as I'm passing through the file for upload. Any thoughts?

Related

Axios returns NetworkError / CORS Headers enabled

I build a ionic-react android application with Axios to get a server response. Two weeks ago my code was working fine. Now the axios request always returns a NETWORK_ERR (HttpError or Axios Error).
I tried to use all CORS Headers possible in my api, but the request is not sent to the webservice.
I hope anyone can help me:
This is the Code I was using:
const api = axios.create({
baseURL: "http://192.168.0.145:8080/RestFulTest-1.0-SNAPSHOT/api",
});
function callApi(){
api.get("/verification")
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log(error);
});
}
Just directly opening the API Url in browser is not loading it...
Sot it seems either the backend is down or blocking and requires an authorization header with the axios request, like
let tokenStr = "Your TOKEN";
axios.get("/verification", { headers: {"Authorization" : `Bearer ${tokenStr}`} });
Hope it helps..

Axios post blocked by CORS. Using CLoudinary api

I am trying to do a post request with axios to upload a image to cloudinary from my frontend React app. I am getting this error from the axios code below:
http://localhost:3000 has been blocked by CORS policy: Request header field x-access-token is not allowed by Access-Control-Allow-Headers in preflight response.
Using axios, doesnt work gives me cors error
await axios({
method: "POST",
url: "https://api.cloudinary.com/v1_1/******/image/upload/",
data: {
file: img,
upload_preset: "*****",
cloud_name: "****",
},
})
.then((res) => {
console.log("response");
console.log(res);
})
.catch((err) => console.log(err));
Meanwhile when i use fetch using the same api request, the post request works and doesnt give me error. Anyone know why and how to call the api using axios?
const data = new FormData();
data.append("file", img);
data.append("upload_preset", "*****");
data.append("cloud_name", "*****");
await fetch(
" https://api.cloudinary.com/v1_1/****/image/upload/",
{
method: "post",
body: data,
}
)
.then((resp) => resp.json())
.then((data) => {
setUrlArray((prevState) => [...prevState, data.url]);
})
.catch((err) => console.log(err));
Extra info: My upload preset is unsigned.
Also got this from the console after making the axios api call
{
error: {
message: "Upload preset must be specified when using unsigned upload"
}
}
To create an Axios request equivalent to your working fetch() one, you need to
Craft a FormData instance and set it as the request data so your content-type is multipart/form-data
Make sure you're not using a previously created Axios instance with unwanted default headers
If custom headers have been set on the default Axios instance, eg
axios.defaults.headers.common["x-access-token"] = TOKEN
you may need to override / delete them in transformRequest
To avoid any interceptors defined on the default Axios instance, create a new separate instance for un-intercepted requests
import axios from "axios" // import the default instance
// create a new instance without interceptors.
// you could also create this in its own module and import from there
const instance = axios.create()
const data = new FormData()
data.append("file", img);
data.append("upload_preset", "*****");
data.append("cloud_name", "*****");
const res = await instance.post(
"https://api.cloudinary.com/v1_1/******/image/upload/",
data
)
Ideally, if your app is going to customise requests, you should always use an Axios instance (or multiple instances) to avoid messing around with the defaults.

How to handle POST request in reactjs?

I have my ReactJS app running in http://localhost:3000/. I am receiving below form data to my React page as a POST request
<form action="http://localhost:3000/" method="post">
Employee Id: <input type="text" name="eid"><br>
Department Id: <input type="text" name="did"><br>
<input type="submit" value="Submit">
</form>
My react app should be able to handle this POST request and render the UI as below
<h1>{eid}</h1>
<h1>{did}</h1>
I am able to handle GET request using react router but struggling to handle POST request. How can I achieve this?
That is not possible if your React app is static(not server side rendered).
When you send some POST request to your react app, nginx(or other server) will not allow that kind of action(you cannot post to static files)
Even if you bypass that restriction, react script will not have any data from your POST request, because nginx will process your request and return just a html with react script to you
It will not work like php.. you need to have something like backend (node or php to pass the data) or even some site to accept the request..
First, you need maybe some theoretical view:
https://pusher.com/tutorials/consume-restful-api-react
https://www.robinwieruch.de/react-hooks-fetch-data
You should firstly save data
You save them to the state
You display them in the part where it is rendered
To download data from api (GET)- you don't do it directly in form - you only use either ComponentDidMount or UseEffect.
componentDidMount() {
fetch(ApiURL)
.then(res => res.json())
.then(res => this.setState({ planets: res }))
.catch(() => this.setState({ hasErrors: true }));
}
useEffect(async () => {
const result = await axios(
ApiURL,
);
setData(result.data);
});
To send data to api (POST)- It's complicated - you need information about client-server communication
Straight from the React docs:
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})

"Network Error" with Axios and DjangoREST but request succeeds at the end

So, I am using ReactJS and DjangoRESTframework to build my app.
Now..when I send a request with Postman it works perfectly(ex. 127.0.0.1:8000/api/users/ GET request) and when I try to do it in React with Axios I get a network error but on my local development server console I see that it succeeded.
This is my get request with axios in react:
componentDidMount() {
axios.get('http://127.0.0.1:8000/api/users/', {
headers: {
'Accept': 'application/json'
}
})
.then(res => {
console.log(res.data);
}).catch(err => {
console.log(err);
})
}
And I get an Network Error. But as I said with Postman it works.
One more example is that I send POST request with Axios to http://127.0.0.1:8000/api/users/ and as response I get Network Error as well but on my backend, user IS created.
This is code for my POST request with axios:
let formData = new FormData();
formData.set('email', this.state.emailField);
formData.set('username', this.state.usernameField);
formData.set('password', this.state.passwordField);
axios({
method: 'POST',
data: formData,
url: 'http://127.0.0.1:8000/api/users/',
config: {headers: {'Content-Type': 'multipart/form-data'}}
}).then(request => {
console.log(request.data);
}).catch(err => {
console.log(err);
})
I googled for about an hour to fix this but nothing helps.
Can you be more clear on what you see as Network error? Attach some error messages / Stack trace.
This looks like a Cross-Origin Resource Sharing (CORS)
issue to me. Try configuring CORS on your DjangoRESTframework backend.
This might help you if that is the case.

Fetch request to Cloudinary API from with React Component fails

I want to make an HTTP request to the Cloudinary API for pictures in my account. The url necessary looks like this:
https://<<API KEY>>:<<API SECRET>>#api.cloudinary.com/v1_1/<<RESOURCE NAME>>/resources/image
and when I hit this url from the browser, I get what I'm looking for, a beautiful JSON object with all my pictures.
But when I hit the url from within a React component,
componentDidMount() {
this.props.fetchArt();
}
I get the following error:
TypeError: Failed to execute 'fetch' on 'Window': Request
cannot be constructed from a URL that includes credentials:
The action creator looks like
export function fetchArt() {
const url = 'https://'+CLOUDINARY_KEY+':'+CLOUDINARY_SECRET+'#api.cloudinary.com/v1_1/prints20/resources/image';
const request = fetch(url).then(res => res.json())
return {
type: FETCH_ART,
payload: request
}
}
Link to the repo: https://github.com/PantherHawk/prints20-2018
Thanks a million in advance!
If your endpoint requires some sort of authorization you'll need to pass that info inside the headers of your request.
Cloudinary Authentication is done using Basic Authentication over secure HTTP. Your Cloudinary API Key and API Secret are used for the authentication.
fetch('https://api.cloudinary.com/v1_1/CLOUD_NAME/resources/image', {
method: 'get',
headers: {
'Authorization': 'Basic ' + base64.encode(API_KEY + ":" + API_SECRET),
},
}).then(res => res.json())

Resources