POST with Next.js and MongoDB - javascript

I'm getting a 500 when trying to make a POST with my Next.js Application. I can't seem to figure out why.
I'm using Next.js, and MongoDB and the GET requests are working fine.
Posts.js
import clientPromise from "../../lib/mongodb";
export default async function handler(req, res) {
const client = await clientPromise;
const db = client.db("quick_ticker_db");
switch (req.method) {
case "POST":
let bodyObject = JSON.parse(req.body);
let myPost = await db.collection("posts").insertOne(bodyObject);
res.json(myPost.ops[0]);
break;
case "GET":
const allPosts = await db.collection("posts").find({}).toArray();
res.json({ status: 200, data: allPosts });
break;
}
}
create.js
export default function CreateTicker() {
// Handles the submit event on form submit.
const handleSubmit = async (event) => {
// Stop the form from submitting and refreshing the page.
event.preventDefault()
// Get data from the form.
const data = {
ticker: event.target.ticker.value
}
// Send the data to the server in JSON format.
const JSONdata = JSON.stringify(data)
// API endpoint where we send form data.
const endpoint = '/api/posts'
// Form the request for sending data to the server.
const options = {
// The method is POST because we are sending data.
method: 'POST',
// Tell the server we're sending JSON.
headers: {
'Content-Type': 'application/json',
},
// Body of the request is the JSON data we created above.
body: JSONdata,
encodeBodyAsJSON: true
}
// Send the form data to our forms API on Vercel and get a response.
const response = await fetch(endpoint, options)
// Get the response data from server as JSON.
// If server returns the name submitted, that means the form works.
const result = await response.json()
result
}
return (
// We pass the event to the handleSubmit() function on submit.
<form onSubmit={handleSubmit}>
<label htmlFor="ticker">Ticker</label>
<input type="text" id="ticker" name="ticker" required />
<button type="submit">Submit</button>
</form>
)
}
ERROR:
POST http://localhost:3000/api/posts 500 (Internal Server Error)
Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON
"message":"Unexpected number in JSON at position 1"
RESPONSE:
<!DOCTYPE html>
<html>
<head>
<style data-next-hide-fouc="true">
body {
display: none
}
</style><noscript data-next-hide-fouc="true">
<style>
body {
display: block
}
</style>
</noscript>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width" />
<meta name="next-head-count" content="2" /><noscript data-n-css=""></noscript>
<script defer="" nomodule="" src="/_next/static/chunks/polyfills.js?ts=1664669437061"></script>
<script src="/_next/static/chunks/webpack.js?ts=1664669437061" defer=""></script>
<script src="/_next/static/chunks/main.js?ts=1664669437061" defer=""></script>
<script src="/_next/static/chunks/pages/_app.js?ts=1664669437061" defer=""></script>
<script src="/_next/static/chunks/pages/_error.js?ts=1664669437061" defer=""></script>
<script src="/_next/static/development/_buildManifest.js?ts=1664669437061" defer=""></script>
<script src="/_next/static/development/_ssgManifest.js?ts=1664669437061" defer=""></script><noscript
id="__next_css__DO_NOT_USE__"></noscript>
</head>
<body>
<div id="__next" data-reactroot=""></div>
<script src="/_next/static/chunks/react-refresh.js?ts=1664669437061"></script>
<script id="__NEXT_DATA__" type="application/json">
{"props":{"pageProps":{"statusCode":500}},"page":"/_error","query":{"__NEXT_PAGE":"/api/posts"},"buildId":"development","isFallback":false,"err":{"name":"SyntaxError","source":"server","message":"Unexpected number in JSON at position 1","stack":"SyntaxError: Unexpected number in JSON at position 1\n at JSON.parse (\u003canonymous\u003e)\n at handler (webpack-internal:///(api)/./pages/api/posts.js:12:35)\n at processTicksAndRejections (internal/process/task_queues.js:95:5)\n at async Object.apiResolver (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/api-utils/node.js:366:9)\n at async DevServer.runApi (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/next-server.js:481:9)\n at async Object.fn (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/next-server.js:735:37)\n at async Router.execute (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/router.js:247:36)\n at async DevServer.run (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/base-server.js:347:29)\n at async DevServer.run (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/dev/next-dev-server.js:709:20)\n at async DevServer.handleRequest (/Users/Projects/Personal/quick-ticker-web/node_modules/next/dist/server/base-server.js:285:20)"},"gip":true,"scriptLoader":[]}
</script>
</body>
</html>
For the record GET requests are working just fine.

I think that is because your post logic throwing error:
let bodyObject = JSON.parse(req.body);
let myPost = await db.collection("posts").insertOne(bodyObject);
run this code in try/catch block.
your code is not reaching res.json(myPost.ops[0])

Related

how can i print a response from server using express and fetch?

i am getting object response when trying to use the response from express,this is the HTML and client js i am using
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body>
<form method="post">
<input id="names" name="names" type="text" />
</form>
<button id="send">send</button>
<p id="text"></p>
<script>
document.getElementById("send").addEventListener("click", () => {
let datos = {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
names: document.getElementById("names").value,
}),
};
fetch("/myaction", datos)
.then(function (response) {
document.getElementById("text").innerHTML = response;
})
.catch(() => {
document.getElementById("text").innerHTML = "Error";
});
});
</script>
</body>
</html>
i am trying to use the response of the server.js in the "text" element, the server is
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
app.use(express.json())
//Note that in version 4 of express, express.bodyParser() was
//deprecated in favor of a separate 'body-parser' module.
app.use(bodyParser.urlencoded({ extended: true }));
//app.use(express.bodyParser());
app.get('/', function(req, res) {
res.sendFile(__dirname + "/index.html");
});
app.post('/myaction', function(req, res) {
res.send(req.body.names);
});
app.listen(8088, function() {
console.log('Server running');
});
when fetch request myaction express return the name query but i cant use it on the fetch then because it print "[object Response]" instead the name form value, what can i do ?
The global fetch function returns a Promise that resolves to a Response object. This object contains all the information about the response, like headers, status, body, etc. To get the body of the response you'll need to decode the response first.
In your case you need to read the body as a string so we'll use response.text(). This is a method on the Response object. It also returns a promise which resolves to a string.
fetch("/myaction", datos)
.then(function (response) {
return response.text();
})
.then(function (text) {
document.getElementById("text").textContent = text;
})
.catch(() => {
document.getElementById("text").textContent = "Error";
});
The "response" that comes back from the fetch is an object that has more than just the data in the response. It's a Response object which means it contains the status code (like 200) as well as the data. Typically you can get the data from the response using response.json() if it's JSON format, or response.text() if it's text. These functions are asynchronous so also return a Promise. So your code can look like this:
fetch("/myaction", datos)
.then(function (response) {
return response.text(); // a Promise that will resolve to the data
})
.then(function (text) {
document.getElementById("text").innerHTML = text;
})
.catch(() => {
document.getElementById("text").innerHTML = "Error";
});
Whenever you see a string looking like [object Object] it means you are seeing a Javascript object that doesn't have a meaningful toString() function so that's the best it can do to show you the value. If you're not sure what kind of object it is, a good debugging technique is to output it using console.log(obj) so you can see what it looks like. That usually gives you a clue about what you really are working with.

Dropbox API Javascript - uploadFile() results in 400 Bad Request

I'm trying to upload a file using the Dropbox API. I am using React for the front end where I take the file from an HTML input element and store in the react state. After clicking a button, the file should be sent using the uploadfile() method in the Dropbox API. Here's a snippet of my code:
import Head from 'next/head'
import { useState } from 'react'
import {Dropbox} from 'dropbox'
export default function Home() {
const [file, setFile] = useState(null);
const fileHandler = (e) => {
setFile(e.target.files[0]);
}
const uploadFile = () => {
const UPLOAD_FILE_SIZE_LIMIT = 150 * 1024 * 1024;
var ACCESS_TOKEN = process.env.DROPBOX_TOKEN;
var dbx = new Dropbox({ accessToken: ACCESS_TOKEN });
console.log(file);
if (file.size < UPLOAD_FILE_SIZE_LIMIT) { // File is smaller than 150 Mb - use filesUpload API
console.log('Attempting to upload file');
dbx.filesUpload({path: '/' + file.name, contents: file})
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.error(error);
});
}
}
return (
<div>
<Head>
<title>Create Next App</title>
<link rel="icon" href="/favicon.ico" />
</Head>
<main>
<h1>Upload video</h1>
<div>
<input type="file" onChange={fileHandler}/>
<button onClick={uploadFile}>Submit</button>
</div>
</main>
</div>
)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
I literally took the code from their GitHub example, so I can't figure out why the request is bad. I have checked the file sent is correct, and that the Access Token is correct too.
Thanks.
EDIT: Adding request info from dev tools for reference.
Request Headers
Chrome was not loading the response message on dev tools, so I tried on Firefox. There, I found out that my problem was that permissions were not set up in the application on Dropbox. After setting up the permissions and regenerating a new access token it worked fine.

await fetch in flask not getting required return

I'm trying to use await fetch in JS to use a function that I created in Flask.
My code for the JS is:
let dictionary = await fetch("/getName");
let user_name = await dictionary.name;
and my code in flask is:
#app.route("/getName")
def getName():
output = {"name": ""}
print("hello")
if NAME_KEY in session:
output["name"] = session[NAME_KEY]
print(output)
return jsonify(output)
why does this not work?
to be specific to causes the website to have a 400 bad request.
I removed the await feature from both of the variables, and instead it creates the error:
'Request' object has no attribute 'is_xhr'
I downgraded werkzeug to 0.16.1, and no nothing just shows up. There aren't any errors, but nothing comes and nothing gets printed by the system.
Here is my new code for JS. (Flask stays the same)
let dictionary = fetch("/getName");
console.log("start");
console.log(dictionary);
let user_name = dictionary.name;
Most likely you haven't wrapped the await code inside a function that has been declared with async. Or you have declared the async function incorrectly. This example works:
Your Flask view/route:
#app.route('/getName')
def get_name():
print("in getName view....")
output = {"name": ""}
return jsonify(output)
Your client side code calling the above /getName route:
<head>
<title>REST</title>
<script>
const getName = async () => {
try {
const response = await fetch('/getName')
const resp = await response.json();
console.log("Obj returned from server", resp)
} catch (error) {
console.log('Fetch error: ', error);
}
}
</script>
</head>
<body>
<button onclick="getName()">getName</button>
</body>
For a full working example (e.g. including a Flask app.py file and a Flask template) see:
https://github.com/lfernandez55/REST-auth/tree/stack-overflow-67606023

POST request not working -- sending empty objects [NodeJS]

I am building this school project where we have to create out own API in NodeJs and free-choice frontend. I wrote the following code:
[In public map] app.js
function getAll() {
console.log("Get all")
makeRequest("/poems", "GET")
}
async function getRandomPoem() {
const ids = [1, 2, 3, 4, 5, 6, 7]
const randomId = ids[Math.floor(Math.random() * ids.length)]
const arrayofPoems = await fetch("/poems/" + randomId, {method: "GET"})
const data = await arrayofPoems.json()
const titleBox = document.getElementById("title")
const authorBox = document.getElementById("author")
const textBox = document.getElementById("text")
titleBox.innerText = data.title
authorBox.innerText = data.author
textBox.innerText = data.text
}
function addPoem() {
event.preventDefault();
let title = document.getElementById("titleInput").value
let author = document.getElementById("authorInput").value
let text = document.getElementById("textInput").value
let newPoem = [{
id: 8,
title: "Aaa",
author: "Ccc",
text: "Ddd"
}]
makeRequest("/poems/", "post", newPoem)
}
async function makeRequest(url, reqMethod, body) {
const response = await fetch(url, {
// headers = { "Content-Type": "application/json" },
method: reqMethod,
body:JSON.stringify(body)
})
console.log(response)
const data = await response.json()
console.log(data)
}
[Here the requests to local server] server.js
const express = require('express');
const { poems } = require('./Poems/poemsArray');
const app = express();
const port = 8080;
const allPoems = require('./Poems/poemsArray')
app.use(express.json())
app.use("/", express.static('public'))
app.listen(port, console.log(`App listening on port ${port}`))
// ---------------- POEMS RESOURCE, All endpoints ------------------ //
// Get all
app.get('/poems', (req, res, next) => {
res.json(allPoems)
})
// Get specific
app.get('/poems/:id', (req, res, next) => {
const id = req.params.id
const onePoem = allPoems.find((poem) => poem.id == id)
if(onePoem) {
res.json(onePoem)
} else {
res.status(404).json({ status: "Poem not found! "})
}
})
// Post a poem
app.post('/poems', (req, res, next) => {
allPoems.push(req.body)
res.json({ status: "A new poem has been posted!"})
})
[And last, the HTML with the input fields, where the values should be sent with the POST req] index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Poems from outer space</title>
<script src="app.js"></script>
</head>
<body>
<div id="container">
<div id="poem-container">
<h1 style="color:red;text-align:center;">Poems</h1>
<p style="text-align: center;">Generate a random poem about space!
<button onclick="getRandomPoem()">Generate my poem!</button>
</p>
<div id="showPoem">
<h1 id="title"><!-- Title of poem injected --></h1>
<h2 id="author"><!-- Author of poem injected --></h2>
<p id="text"><!-- Text of poem injected --></p>
</div>
<div id="image-container">
<!-- INJECTED BY EXTERNAL NASA API -->
<!-- EXAMPLE IMAGE TO TEST DELETE WHEN API WORKS -->
<img src="img/apod.jpg" alt="Test Image" width="600px" id="img">
</div>
</div>
<div id="form-container">
<form method="post" action="/poems">
<h1>Send us your poem!</h1>
<label>Your title:</label> <br>
<input type="text" requirede name="title" id="titleInput"> <br>
<label>Your name:</label> <br>
<input type="text" required name="author" id="authorInput"> <br> <br>
<label>Your poem:</label> <br>
<input type="text" required name="text" id="textInput" style="width:500px;height:500px">
<br>
<button type="submit" onclick="addPoem()">Send</button>
</form>
</div>
</div>
</body>
</html>
In the function addPoem() the let newPoem is for testing purposes. The title, author and text should be coming from the form.
Anyone can see what I did wrong?
EDIT: in the makeRequest function the header is commented out, that is because if I leave it in my code, suddenly none of the request work anymore?
Thanks to everybody!
you use headers = which is not valid . try headers : {} .
When you get empty object , try logging the request. It is also possible that the body get sended as a string,which express.json() middleware cannot parse the data. As a result, you get empty object.
async function makeRequest(url, reqMethod, body) {
const response = await fetch(url, {
headers : { "Content-Type": "application/json" },
method: reqMethod,
body:JSON.stringify(body)
})
console.log(response)
const data = await response.json()
console.log(data)
}
If you are trying to access postman after a while it can also cause issue while sending body.
In my case I had done all changes in API, added router,removed validation etc
but at last the culprit was postman as whatever data I was sending, it was showing request.body as {}(empty).
After I re-installed postman it worked!
I just could felt more joyful, it took my 3-4 hours
So you can consider this option as well.

Getting error: 'Stich is not defined' in JavaScript password reset function

I am trying to develop a password reset webpage to use in my email/password authentication for MongoDB Stitch, this is my code:
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<!-- Stitch JavaScript SDK -->
<!-- Base Stitch Browser SDK -->
<script src="https://s3.amazonaws.com/stitch-sdks/js/bundles/4.0.0/stitch.js"></script>
<script>// Parse the URL query parameters
const url = window.location.search;
const params = new URLSearchParams(url);
const token = params.get('token');
const tokenId = params.get('tokenId');
const newPassword = "test";
// Confirm the user's email/password account
const emailPassClient = Stitch.defaultAppClient.auth
.getProviderClient(UserPasswordAuthProviderClient.factory);
emailPassClient.resetPassword(token, tokenId, newPassword).then(() => {
console.log("Successfully reset password!");
}).catch(err => {
console.log("Error resetting password:", err);
});
</script>
</body>
</html>
I am getting an error like the following:
Uncaught ReferenceError: Stitch is not defined
Perhaps I am importing the stitch bundles incorrectly?
Call stitch.Stitch.initializeDefaultAppClient(ID)
Note that you have to initialize a default app client, you can't just call stitch.Stitch.defaultappClient
const client = stitch.Stitch.initializeDefaultAppClient('<<app-id>>');
var emailClient = client.auth.getProviderClient(window.stitch.UserPasswordAuthProviderClient.factory);
emailPassClient.resetPassword(token, tokenId, newPassword).then(() => {
console.log("Successfully reset password!");
}).catch(err => {
console.log("Error resetting password:", err);
});

Categories