AxiosError with Get Method give me 404 Error Page - reactjs

When I request data from Mongoose, it shows me an error and tells me that the page does not exist, knowing that I tested the back-end in Postman and it succeeded. I also tested the react by fetching data from an external link and it succeeded. I do not know what the problem is?!
I try with this code
This is my back-end code
const app = require("./app");
const mongoose = require("mongoose");
app.set("port", process.env.PORT || 3000);
const mongoURI = "mongodb://localhost:27017/get-now";
mongoose.connect(mongoURI, {
    useNewUrlParser: true,
    useUnifiedTopology: true
})
.then(() => console.log(`database connected`))
.catch(err => console.log(err));
const port = process.env.PORT || 3000;
app.listen(port, () => {console.log(`the server is ${port}`)});
routes.get("/alldata" , async (req, res) => {
try {
const foodDatas = await Data.find({})
res.send(foodDatas);
console.log(foodDatas)
} catch (error){
res.status(500).json({
Error: error
})
}
});
This is my front-end (Reactjs) code
const fetchData = async () => {
    axios.get('http://localhost:3000/alldata')
  .then((res) => {
    console.log(res.data)
}).catch (err => {
console.log(err)
})
    }
  useEffect(() => {
    fetchData()
  }, [])
All these don't work it give me Error 404 page with data: undefined

did you configure the cors in the app file?
if don't, please install cors.
and add:
const cors = require('cors')
also:
app.use(
cors({
origin: "*",
})
);
Note:
Cross-Origin Resource Sharing (CORS) is an HTTP-header based mechanism that allows a server to indicate any origins (domain, scheme, or port) other than its own from which a browser should permit loading resources

Related

Notion.so API always throws CORS error while developing React application locally

Today I faced with an issue where any solution found in interned could not handle it.
I am trying to create a blog app using amazing Notion.so note-taking app. Of course, for this stuff I need their API.
Before implementing in React code I tested everything in Insomnia (postman like app). Everything worked smoothly.
When I started to implement first request in react-redux... boom everything is ruined.
This is where request is made:
export const notionApi = createApi({
reducerPath: "notionApi",
baseQuery: fetchBaseQuery({
baseUrl: "https://api.notion.com/v1",
prepareHeaders: headers => {
headers.set("Authorization", process.env.REACT_APP_NOTION_SECRET);
headers.set("Notion-Version", " 2022-02-22");
return headers;
}
}),
endpoints: builder => ({
getMenu: builder.query({
query: id => `/blocks/${id}/children`
})
})
});
export const { useGetMenuQuery } = notionApi;
This is in browser:
Access to fetch at 'https://api.notion.com/v1/blocks/c5886e5e15d04d4bb8112bafcec8475b/children' from
origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight
request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is
present on the requested resource. If an opaque response serves your needs, set the
request's mode to 'no-cors' to fetch the resource with CORS disabled.
Believe or not, I tried everything: Cors Chrome App to imitate, CRA proxy to in package.json, express sever to imitate proxy and 5 hours of desperate search.
First thanks to Shahriar for the valuable tip in comment. The only variant to execute Notion's API is proxying it so far. Here is how I made Notion.so API work in browser.
First I started an Express server.
// server.js
const app = express();
const server = http.createServer(app);
app.use(express.json());
app.use(cors());
app.get('/getmenu', async (req, res) => {
const data = await NotionApi('uuid');
res.status(200).json(data);
});
const PORT = process.env.PORT || 5000;
server.listen(PORT, console.log(`Server started # ${PORT}`));
Using axios I created function to make calls to Notion API:
// utils/NotionApi.js
require('dotenv').config();
const axios = require('axios');
async function NotionApi(id) {
return await axios
.get(`https://api.notion.com/v1/blocks/${id}/children`, {
headers: {
Authorization: `Bearer ${process.env.NOTION_SECRET}`,
'Notion-Version': ' 2022-02-22',
},
})
.then(async (res) => {
return res.data;
})
.catch((err) => {
NotionApi = undefined;
console.log(err);
});
}
module.exports = NotionApi;
Then I deployed this beauty to Heroku and Voilà!
Project url where Notion needed: https://jsadvanced.github.io/

React/Socket.io chat app not working on heroku

I have a chat app I made using React for the frontend, DRF for the backend and I also have a node.js server within the React app for socket.io The issue is that the chat doesn't work basically (it works fine locally). When a message is sent it's not emitted and only shows up when I refresh since it's then pulled from the DB instead. I have gone through many threads on here for this issue but can't figure out what I'm doing wrong.
My server:
const server = require("http").createServer();
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
const PORT = process.env.PORT || 5000;
const NEW_CHAT_MESSAGE_EVENT = "newChatMessage";
io.on("connection", (socket) => {
console.log('Client connected')
// Join a conversation.
const {roomId} = socket.handshake.query;
socket.join(roomId);
// Listen for new messages
socket.on(NEW_CHAT_MESSAGE_EVENT, (data) => {
io.in(roomId).emit(NEW_CHAT_MESSAGE_EVENT, data);
});
// Leave the room if the user closes the socket
socket.on("disconnect", () => {
socket.leave(roomId);
});
});
server.listen(PORT, (error) => {
if (error) throw error;
console.log(`Listening on port ${PORT}`);
});
Hook I made for the frontend:
const NEW_CHAT_MESSAGE_EVENT = "newChatMessage"; // Name of the event
const SOCKET_SERVER_URL = `https://<my-react-frontend>.herokuapp.com`;
export const useChat = () => {
const socketRef = useRef();
const {messages, setMessages, activeConvo, headerConvo, reloadSideBar, setReloadSideBar} = useActiveConvo()
const roomId = activeConvo
useEffect(() => {
console.log('useChat useEffect ran')
// Creates a WebSocket connection
socketRef.current = socketIOClient(SOCKET_SERVER_URL, {
query: {roomId},
});
// Listens for incoming messages
socketRef.current.on(NEW_CHAT_MESSAGE_EVENT, (message) => {
const incomingMessage = {
message: message.body,
created_by: localStorage.getItem('currentUserID'),
};
console.log('messages set in useChat useFfect')
setMessages((messages) => [...messages, incomingMessage]);
});
// Destroys the socket reference
// when the connection is closed
return () => {
socketRef.current.disconnect();
};
}, [roomId]);
// Sends a message to the server that
// forwards it to all users in the same room
const sendMessage = (messageBody) => {
socketRef.current.emit(NEW_CHAT_MESSAGE_EVENT, {
body: messageBody,
senderId: socketRef.current.id,
});
const fetchContents = {
message: messageBody,
created_by: localStorage.getItem('currentUserID'),
convo_id: activeConvo ? activeConvo : headerConvo
}
fetch(`https://<my-drf-backend>.herokuapp.com/api/save-message/`, authRequestOptions(('POST'), fetchContents))
.then(response => response.json())
.then(setReloadSideBar(reloadSideBar + 1))
.catch(error => console.log(error))
};
return {messages, sendMessage};
};
The issue in most of the threads appeared to be either still using the localhost url on the frontend or not using process.env.PORT in the server but it's still busted after fixing that. I also saw someone mention in another thread that the folder structure was the issue so I tried having the server file in the root of the react app and having it in it's own folder under "src", no dice.
In case anyone faces this same issue, I solved it by putting the server in a separate app on heroku

sending token to backend server but couldn't connect to it with react-google-recaptcha

I'm trying to send token to my backend server to let it verify the token with Google recaptcha. However, my frontend does not seem to connect with my backend.
Error Message I'm getting: POST http://localhost:3000/post 404 (Not Found)
Apparently, my FE could not find the port to BE.
I have tried to use frontend for API request with the URI provided by google but I ran into CORS issue, and it is not secure.
By console.log(token), I find nothing wrong with the library itself because I have successfully get a success response from Google using the token with POSTMAN.
Here is my frontend:
const handleVerify = async (token) => {
console.log(token)
const captchaToken = token;
await axios.post("/post", { captchaToken })
.then(res => console.log(res)
.catch((error) => {
console.log(error)
}))
setIsVerified(true)
setActiveStep(activeStep + 1);
}
.....
<ReCAPTCHA
ref={recaptchaRef}
sitekey={process.env.REACT_APP_SITE_KEY}
onChange={(token) => handleVerify(token)}
size="normal"
onExpired={(expire) => handleShowExpired(expire)}
>
</ReCAPTCHA>
.....
Here is my backend:
const express = require("express");
const cors = require("cors");
const axios = require("axios");
const app = express();
const port = process.env.PORT || 5000;
app.use(cors());
app.use(express.urlencoded({ extended: true }));
app.use("/", router);
//POST route
router.post("/post", async (req, res) => {
const { captchaToken } = req.body;
//sends secret key and response token to google
await axios.post(
`https://www.google.com/recaptcha/api/siteverify?secret=${process.env.SECRET_KEY}&response=${captchaToken}`
);
//check response status and send back to client
if (res.data.success) {
res.send("Human");
} else {
res.send("Robot");
}
});
If your server runs on port 5000 you should await axios.post("http://localhost:5000/post", { captchaToken })
Also, you have to validate the axios response.
router.post("/post", async (req, res) => {
const { captchaToken } = req.body;
//sends secret key and response token to google
const axiosResponse = await axios.post(
`https://www.google.com/recaptcha/api/siteverify?secret=${process.env.SECRET_KEY}&response=${captchaToken}`
);
//check response status and send back to client
if (axiosResponse.data.success) {
res.send("Human");
} else {
res.send("Robot");
}
});

How do I get Axios to hit routes in monorepo?

I am using a monorepo-styled build and I am struggling to get routes to hit properly. I am clicking my button:
const handleSubmit = () => {
console.log("button clicked");
axios.get('/', {
params: {
username: "John1904",
}
})
.then((res) => {
console.log(res.data);
});
};
And I am getting the index.ts file, which makes sense. When I attempt to use '/users or /users/, it doesn't work. I get
>GET http://localhost:3000/users?username=John1904 404 (Not Found)
>Uncaught (in promise) AxiosError {message: 'Request failed with status code 404'
This is in the browser console, while nothing else shows in my terminal.
My index.ts that is handling routes is:
const app: Express = express();
const port = process.env.PORT;
app.use(helmet());
app.use(cors());
app.use(express.json());
app.use('/users', usersRouter);
app.use('/', (_req, res) => res.status(200).send('Service online'));
app.use(errorHandler);
app.use(notFoundHandler);
And my server/src/routes/users/router.ts file is:
const router = express.Router();
router.get('/', async (_req: Request, res: Response) => {
try {
const items = await UserService.findAll();
res.status(200).send(items);
} catch (e) {
res.status(500).send(unwrapRouterErrorMessage(e));
}
});
So why is my request not going into the app.use('/users', usersRouter);?
Okay, thanks for asking about the ports, because I checked the URL requests in the dev tools and it was all going through to the frontend and not hitting the backend. Everything was going to the port 3000 instead of 3006. For now I hardcoded the route to go to http://localhost:3006/ and it worked. Thanks again.

unexpected token in json at position 0 reactjs mongodb

///component
function Home() {
const [show, setShow]= useState([{name:'', info:'', airingDate:'', poster:''}])
useEffect(()=>{
fetch("/home")
//.then(res=> res.json())
.then(res => res.text())
.then(text => console.log(text))
})
return (
<div>
{show.map(a=>
<div>
<h2>{a.title}</h2>
</div>
)}
</div>
)
/////index.js
const TvShows = require("./models/TvShows");
const express = require("express");
const app = express();
const mongoose= require("mongoose")
const dotenv= require("dotenv");
const authRoute = require("./routes/auth");
const { application } = require("express");
const userRoute = require("./routes/users");
const commentRoute = require("./routes/comments");
const tvshowsRoute = require("./routes/tvshows");
const cors = require("cors");
app.use(cors());
console.log(".");
dotenv.config();
app.use(express.json());
mongoose.connect(process.env.MONGO_URL,{
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(console.log("connected to mongoDB"));
app.use("/auth", authRoute);
app.use("/users", userRoute);
app.use("/comments", commentRoute);
app.post("/api/home", tvshowsRoute);
app.use("/api/home", tvshowsRoute);
/*
app.get('/api/home', (req,res)=>{
TvShows.find().then((result)=>{
res.send(result);
})
})
*/
/*
app.use("/",(req,res)=>{
console.log("main url")
})*/
app.listen("3001",()=>{
console.log("backend running");
})
//////route
const router = require("express").Router();
const TvShows = require("../models/TvShows");
router.post("/api/home", async (req, res) => {
console.log("here")
try{
const newTvShow = new TvShows({
title: req.body.title,
poster: req.body.poster,
info: req.body.info
});
const savedTvShows = await newTvShow.save();
res.status(200).json(savedTvShows);
}catch (err) {
res.status(500).json(err);
}
}
);
router.route("/api/home").get((req, res)=>{
TvShows.find()
.then(foundShows=> res.json(foundShows))
})
module.exports = router;
when I change res.json with res.text I see my index.html page on console not the data I want to fetch from mongodb. This error is probably because I didn't use /api/ on root url but I couldn't figure it out where I should write it. I tried but didn't work. It would be so good if someone could've helped. Thank you so much.
Indeed, you are fetching the /home page of your front-end app.
Assuming the api is on a different server, you would need to call the address of that server.
If you have a set up locally with a nodejs server and a react app running separately, you should have them run on two different ports.
If you have react app on http://localhost:3000 (default), then change your api to listen on 3001, then in your react code above, you can use the full uri
http://localhost:3001/api/home
in your fetch call.
I'm making a lot of assumptions about how you have this set up, based on my own experience of local development for similar problems.

Resources