ReactJS: POST 400 (Bad Request) using Axios - reactjs

I am using axios to hit an API to upload a .apk file onto a 3rd party app which is running locally on my computer. Using the API on Postman is giving the desired result but while integrating it with my React app I am getting POST http://localhost:8000/api/v1/upload 400 (Bad Request) error.
I have the following with structure:
src/httpRequest.js
import axios from "axios";
export default axios.create({
baseURL: "http://localhost:8000",
headers: {
"Content-type": "application/json",
Authorization: <API_KEY>
}
});
src/services/Upload.js
import http from "../httpRequest";
const upload = (file, onUploadProgress) => {
const formData = new FormData();
formData.append("file", file);
return http.post("/upload", formData, {
headers: {
"Content-Type": "multipart/form-data",
Authorization:
<API_KEY>
},
onUploadProgress,
});
};
export default {
upload,
};
src/components/ApkUpload.js
import React, { useState, useEffect } from 'react';
import axios from 'axios';
const ApkUpload = () => {
const [selectedFiles, setSelectedFiles] = useState(undefined);
// eslint-disable-next-line no-unused-vars
const [currentFile, setCurrentFile] = useState(undefined);
const [progress, setProgress] = useState(0);
const [message, setMessage] = useState('');
const [fileDetails, setFileDetails] = useState([]);
const handleUpload = async () => {
const data = new FormData();
data.append('file', selectedFiles);
try {
const res = await axios.post('http://localhost:8000/api/v1/upload', data, {
headers: {
'Content-Type': 'multipart/form-data',
Authorization: <API_KEY>,
},
onUploadProgress: (progressEvent) => {
setProgress(parseInt(Math.round((progressEvent.loaded * 100) / progressEvent.total), 10));
},
});
} catch (err) {
if (err.response.status === 500) {
setMessage('There was a problem with the server');
} else {
setMessage(err.response.data.message);
}
}
};
const handleChange = (e) => {
setSelectedFiles(e.target.files);
setCurrentFile(e.target.files[0]);
};
useEffect(() => {
axios.get("http://localhost:8000/api/v1/scans", {
headers: {
Authorization:
<API_KEY>,
},
}).then(res => {
setFileDetails(res.data.content);
});
},[]);
return (
<div className="container">
// simple button calling above methods
</div>
);
};
export default ApkUpload;
I am using MobSF as my third party app and for upload they require multipart/form-data.
While using postman I was able to get the desired result but I'm not able to do so with my frontend. Any help regarding this issue will be highly appreciated!

const data = new FormData();
data.append('file', selectedFiles[0]);
Inside your handleUpload function selectedFiles state is of type FileList but it should be File.
If you are handling single file then you can use:
data.append('file', selectedFiles[0]);
For multiple files you can do:
for(let i=0;i<selectedFiles.length;++i){
data.append('file',selectedFiles[i])
}

Related

Infinite rendering of component while fetching data with useEffect hook in reactjs

When i want to fetch collections from api, infinite rendering in useEffect happening on the console. How can fix it?
const Collections = () => {
const [collections, setCollections] = useState([]);
const token = window.localStorage.getItem("token");
useEffect(() => {
fetchUsers();
},[setCollections]);
const fetchUsers = async () => {
const response = await fetch(
"https://itransition-capstone.herokuapp.com/collections/allCollections",
{
method: "GET",
headers: {
"Content-Type": "application/json",
Authorization: "Bearer " + token,
},
}
);
const data = await response.json();
setCollections(data);
console.log("Collections", data);
};
};
export default Collections;

Why I need to refresh manually to fetch data api in react?

I make react app using react router v5, and axios as api instance. I fetch the data in AppRouter file.
Here is my approuter.tsx
const AppRouter = () => {
const dispatch = useAppDispatch();
const token = useAppSelector((state) => state.user.token);
const getUser = useCallback(async () => {
const { data } = await Services.getUser();
dispatch(userAction.setUser(data));
}, [dispatch]);
useEffect(() => {
const localStorage = new LocalStorageWorker();
const storageToken = localStorage.get('token');
dispatch(userAction.setToken(storageToken));
}, [dispatch]);
useEffect(() => {
if (token) {
getUser();
console.log('Worked');
}
}, [token, getUser]);
return (
...
)
}
Actually the function work properly, but I need to refresh the page manually to run these functions. How can I make the function run without refreshing the page?
Update:
The problem is because my axios create instance. I should use interceptors to keep the data fetching in useEffect.
My instance looks like this:
(before update)
const token = localStorage.get('token');
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.defaults.headers.common.Authorization = `Bearer ${token}`;
return instance;
};
(after update)
const createInstance = () => {
const instance = axios.create({
baseURL: BASE_URL,
headers: {
'content-type': 'application/json',
Accept: 'application/json',
},
});
instance.interceptors.request.use(
(config) => {
const token = window.localStorage.getItem('token');
if (token) {
return {
...config,
headers: { Authorization: `Bearer ${token}` },
};
}
return null;
},
(err) => Promise.reject(err)
);
return instance;
};
And now the data fetching is work properly. Thank you

React Typescript file getting converted to a video format

I have a small React project that I am in the process of converting to typescript. I am currently trying to convert a Context file into Typescript. For reference, here is the original JS code:
import { createContext, useCallback, useState } from "react";
import netlifyIdentity from 'netlify-identity-widget';
export const AppContext = createContext()
export function useAppContext() {
const [user, setUser] = useState(netlifyIdentity.currentUser())
const genericAuthedFetch = useCallback((
endpoint,
method = 'GET',
body = null,
) => {
if (!(!!user && !!user.token && !!user.token.access_token)) {
return Promise.reject('no user token found');
}
const options = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method,
body: body === null ? null : JSON.stringify(body),
};
return fetch(endpoint, options);
}, [user]);
const getStockData = (ticker, target) => {
var url = new URL('.netlify/functions/get-price', window.location.origin)
url.search = new URLSearchParams({ ticker, target }).toString()
return genericAuthedFetch(url);
}
const createAccount = (params) => {
return genericAuthedFetch(
new URL('.netlify/functions/create-account', window.location.origin),
'POST',
params);
}
const listAccounts = (date) => {
var url = new URL('.netlify/functions/list-accounts', window.location.origin);
url.search = new URLSearchParams({ timestamp: date.getTime() }).toString()
return genericAuthedFetch(url);
}
const loginUser = useCallback((user) => {
fetch(
new URL('.netlify/functions/make-user', window.location.origin),
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method: 'POST'
}).then((_) =>
setUser(user))
}, [setUser])
const logoutUser = useCallback((user) => setUser(null), [setUser])
netlifyIdentity.on("login", loginUser);
netlifyIdentity.on("logout", logoutUser);
const loginPopup = () => netlifyIdentity.open('login')
const signupPopup = () => netlifyIdentity.open('signup')
const logout = () => netlifyIdentity.logout();
return {
user,
logout,
loginPopup,
signupPopup,
getStockData,
listAccounts,
createAccount
}
}
And here is the associated TS code
import React, { createContext, useCallback, useState } from "react";
import netlifyIdentity, { User } from 'netlify-identity-widget';
import { CreateAccountRequest, CreateAccountResponse, GetPriceRequest, GetPriceResponse, ListAccountsRequest, ListAccountsResponse } from "../types/types";
export interface Context {
user?: User
logout: () => void
loginPopup: () => void
signupPopup: () => void
getStockData: (req: GetPriceRequest) => Promise<GetPriceResponse>
listAccounts:(req: ListAccountsRequest) => Promise<ListAccountsResponse>
createAccount: (req: CreateAccountRequest) => Promise<CreateAccountResponse>
}
export const AppContext: React.Context<Context> = createContext({} as Context)
export function useAppContext() {
const [user, setUser] = useState(netlifyIdentity.currentUser())
const genericAuthedFetch = useCallback((
endpoint: URL,
method = 'GET',
body: any = null,
) => {
if (!user?.token?.access_token) {
return Promise.reject('no user token found');
}
const options = {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user.token.access_token,
},
method,
body: body === null ? null : JSON.stringify(body),
};
return fetch(endpoint, options);
}, [user]);
const getStockData = (req: GetPriceRequest) => {
var url = new URL('.netlify/functions/get-price', window.location.origin)
url.search = new URLSearchParams({ ticker: req.ticker, target: req.target }).toString()
return genericAuthedFetch(url);
}
const createAccount = (req: CreateAccountRequest) => {
return genericAuthedFetch(
new URL('.netlify/functions/create-account', window.location.origin),
'POST',
req);
}
const listAccounts = (req: ListAccountsRequest) => {
var url = new URL('.netlify/functions/list-accounts', window.location.origin);
url.search = new URLSearchParams({ timestamp: req.timestamp.toString() }).toString()
return genericAuthedFetch(url);
}
const loginUser = useCallback((user: User) => {
fetch(
new URL('.netlify/functions/make-user', window.location.origin),
{
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
Authorization: 'Bearer ' + user?.token?.access_token,
},
method: 'POST'
}).then((_) =>
setUser(user))
}, [setUser])
const logoutUser = useCallback(() => setUser(null), [setUser])
netlifyIdentity.on("login", loginUser);
netlifyIdentity.on("logout", logoutUser);
const loginPopup = () => netlifyIdentity.open('login')
const signupPopup = () => netlifyIdentity.open('signup')
const logout = () => netlifyIdentity.logout();
return {
user,
logout,
loginPopup,
signupPopup,
getStockData,
listAccounts,
createAccount
}
}
The problem I am encountering is that when I use the dev server or create a production build using npm run build, the typescript version of this file becomes mangled in a strange way.
Specifically, the contents of the typescript file becomes
module.exports = "data:video/MP2T;base64,<base64 encoded typescript file>"
//////////////////
// WEBPACK FOOTER
// ./src/AppContext.ts
// module id = 115
// module chunks = 0
I have done some research, and the only thing I have found is that .ts is also the extension of MPEG transport stream, so that could partially explain it. Something thinks my typescript code is a video file, but I have no idea what is doing that or why.
How do I get this to compile correctly?

I am trying to fetch users using Github API, but it says the token is wrong

I am try to fetch users information using github API
import React, { useEffect } from "react";
function UserResults() {
useEffect(() => {
fetchUsers();
}, []);
const fetchUsers = async () => {
const response = await fetch(`${process.env.REACT_APP_GITHUB_URL}/users`, {
headers: {
Authorization: `token ${process.env.REACT_APP_GITHUB_TOKEN}`,
},
});
const data = response.json();
};
return <div>Hello</div>;
}
export default UserResults;
And here is what I put in my env:
REACT_APP_GITHUB_TOKEN="<token>"
REACT_APP_GITHUB_URL = "https://api.github.com"
I am sure the token is correctly generated and copied.
But it seems I can't fetch the data due to some "JSON" error as it shows in the console like this.
Can anyone offers any help with this?
You need to await response.json() and update your header request
import React, { useEffect } from "react";
function UserResults() {
useEffect(() => {
fetchUsers();
}, []);
const fetchUsers = async () => {
const response = await fetch(`${process.env.REACT_APP_GITHUB_URL}/users`, {
headers: {
'Authorization': `token ${process.env.REACT_APP_GITHUB_TOKEN}`,
'Content-Type': 'application/json',
'Accept': 'application/json'
},
});
const data = await response.json();
};
return <div>Hello</div>;
}
export default UserResults;

Little help needed with Spotify api

Working on my first project and need some help. I succeeded with React to use Spotify API to fetch my playlists. Now I want to build a search component, but I am getting a 401 returned. I assume that the problem is in my headers (Content-Type??).
import React, {useEffect, useState} from "react";
import axios from "axios";
import {useOptionContext} from "../context/SelectedOptionsProvider";
export default function ArtistOnSpotify() {
const [token, setToken] = useState("");
const [data, setData] = useState({});
const {
selectedArtist,
} = useOptionContext();
console.log("localstorage", localStorage);
console.log("token", token);
useEffect(() => {
if (localStorage.getItem("accessToken")) {
console.log(localStorage);
setToken(localStorage.getItem("accessToken"));
}
}, []);
async function ArtistOnSpotify() {
try {
console.log(token);
const response = await axios.get(`https://api.spotify.com/v1/search?query=${selectedArtist}`, {
headers: {
Authorization: "Bearer " + token,
Accept: "application/json",
"Content-Type" : "application/json",
// Content-Type : "application/json",
},
})
;
console.log(response.data);
// setData(response.data);
} catch (error) {
console.log(error);
}
;
};
return (
<div>
<button onClick={() => ArtistOnSpotify()}>klik</button>
</div>
)
}

Resources