POST and DELETE requests are working but PUT is not working even after passing {new: true} as other answers suggested.
I checked the documentation for mongoose and didn't find anything that might solve the problem.
Terminal log is: PUT /api/persons/5dfbb8677d7d960358dbdead 404 175 - 2.273 ms -
The request body is not logging and only a '-' is logged. This is not the case with POST.
Relevant code:
app.post('/api/persons', (request, response) => {
const body = request.body
const person = new Person({
name: body.name,
number: body.number,
})
person
.save()
.then(savedContact => {
response.json(savedContact.toJSON())
})
})
app.put('api/persons/:id', (request, response, next) => {
const body = request.body
const person = {
name: body.name,
number: body.number,
}
person
.findByIdAndUpdate(request.params.id, person, { new: true })
.then(updatedContact => {
response.json(updatedContact.toJSON())
})
.catch(error => next(error))
})
app.delete('/api/persons/:id', (request, response, next) => {
Person
.findByIdAndRemove(request.params.id)
.then(result => {
response.status(204).end()
})
.catch(error => {next(error)})
const errorHandler = (error, request, response, next) => {
if (error.name === 'CastError' && error.kind == 'ObjectId') {
return response.status(400).send({ error: 'malformatted id' })
}
next(error)
}
app.use(errorHandler)
})
Complete File:
require('dotenv').config()
const express = require('express')
const app = express()
app.use(express.static('build'))
const bodyParser = require('body-parser')
app.use(bodyParser.json())
const cors = require('cors')
app.use(cors())
const morgan = require('morgan')
morgan.token('req_body', function(req, res) {
if (req.method === 'POST' || req.method === 'PUT'){
return JSON.stringify(req.body);
}
});
morgan.token('req_key', function(req, res) {
if (req.method === 'GET' || req.method === 'PUT'){
return JSON.stringify(req.params.id);
}
});
app.use(morgan(':method :url :status :res[content-length] - :response-time ms :req_body :req_key'))
const Person = require('./models/person')
app.get('/api/persons', (request, response) => {
Person.find({}).then(persons => {
response.json(persons.map(person => person.toJSON()))
})
})
app.get('/api/persons/:id', (request, response) => {
Person
.findById(request.params.id)
.then(person => {
response.json(person.toJSON())
})
.catch(error => {
console.log(error)
response.status(404).end()
})
})
app.post('/api/persons', (request, response) => {
const body = request.body
const person = new Person({
name: body.name,
number: body.number,
})
person
.save()
.then(savedContact => {
response.json(savedContact.toJSON())
})
})
app.put('api/persons/:id', (request, response, next) => {
const body = request.body
const person = {
name: body.name,
number: body.number,
}
Person
.findByIdAndUpdate(request.params.id, person, { new: true })
.then(updatedContact => {
response.json(updatedContact.toJSON())
})
.catch(error => next(error))
})
app.delete('/api/persons/:id', (request, response, next) => {
Person
.findByIdAndRemove(request.params.id)
.then(result => {
response.status(204).end()
})
.catch(error => {next(error)})
})
const errorHandler = (error, request, response, next) => {
if (error.name === 'CastError' && error.kind == 'ObjectId') {
return response.status(400).send({ error: 'malformatted id' })
}
next(error)
}
app.use(errorHandler)
const PORT = process.env.PORT
app.listen(PORT, ()=>{console.log(`Server running on ${PORT}`)})
Your person object is wrong so not update record.
app.put('/api/persons/:id', (request, response, next) => {
const body = request.body
const person = {
name: body.name,
number: body.number,
}
Person
.findByIdAndUpdate(request.params.id, person, { new: true })
.then(updatedContact => {
response.json(updatedContact.toJSON())
})
.catch(error => next(error))
})
Related
const express = require("express");
const cors = require("cors");
const dotenv = require("dotenv");
const bodyParser = require("body-parser");
const mongoose = require("mongoose");
const app = express();
dotenv.config();
app.use(cors());
app.use(bodyParser.json());
const { Schema } = mongoose;
const userSchema = Schema({
imageUrl: { type: String },
description: { type: String },
title: { type: String },
price: { type: Number },
});
const Users = mongoose.model("users", userSchema);
app.get("/", (req, res) => {
res.send("started");
});
`get metod`
app.get("/users", (req, res) => {
Users.find({}, (err, docs) => {
if (!err) {
res.send(docs);
} else {
res.status(404).json({ message: err });
}
});
});
app.get("/users/:id", (req, res) => {
const { id } = req.params;
Users.findById(id, (err, doc) => {
if (!err) {
if (doc) {
res.send(doc);
}
} else {
res.status(404).json({ message: err });
}
});
});
`delete metod`
app.delete("/users/:id", (req, res) => {
const { id } = req.params;
Users.findByIdAndDelete(id, (err, doc) => {
if (!err) {
res.send("Succesfully deleted");
} else {
res.status(404).json({ message: err });
}
});
});
`post metod`
app.post("/users", (req, res) => {
const obj = {
imageUrl: req.body.imageUrl,
description: req.body.description,
title: req.body.title,
price: req.body.price,
};
console.log(obj);
let user = new Users(obj);
user.save();
res.send({ message: " Succesfully added" });
});
const PORT = process.env.PORT;
const url = process.env.URL.replace("<password>", process.env.PASSWORD);
mongoose.set("strictQuery", true);
mongoose.connect(url, (err) => {
if (!err) {
console.log("DB connected");
app.listen(PORT, () => {
console.log("Server start");
});
}
});
I'm trying to learn how exactly get post delete queries work
I'm trying to reduce the code here, but no matter what I do, small errors appear in the end. I have a json string, I want to pass it to POST method. But the 'execute', and 'executeMethod ' are throwing error as below:
"The method execute(HttpUriRequest) in the type HttpClient is not applicable for the arguments (PostMethod)". i have included the depencencies.
I have a component which calls a store called users:
Store:
import { defineStore } from 'pinia'
import axios from 'axios'
export const useUserApiStore = defineStore('userApiStore', {
state: () => ({
}),
actions: {
list(filter) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_LIST;
return new Promise((resolve, reject) => {
axios.get(url, {
params: {
filter: filter,
},
}).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
},
listPaginated(params) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_LIST_PAGINATE;
return new Promise((resolve, reject) => {
axios.get(url, {
params: params,
}).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
},
get(id) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_SHOW;
return new Promise((resolve, reject) => {
axios.get(url.replace(":id", id)).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
},
delete(id) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_DELETE;
return new Promise((resolve, reject) => {
axios.delete(url, { params: { id: id } }).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
},
/* TABS */
store(params) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_STORE;
return new Promise((resolve, reject) => {
axios.post(url, params).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
},
update(params) {
const url = import.meta.env.VITE_URL_GLOBALTANK_BASE_API + import.meta.env.VITE_EP_USERS_UPDATE;
return new Promise((resolve, reject) => {
axios.put(url, params).then(res => {
resolve(res)
}).catch(error => {
reject(error)
})
})
}
}
})
My component UsersView has the method onMounted that calls getData from store:
onMounted(() => {
getData();
});
const getData = (numPage = 0) => {
let params = {
paginate: model.paginate,
filter: model.filter,
page: model.current_page,
};
if (numPage > 0) {
params.page = numPage;
model.current_page = numPage;
}
userApiStore
.listPaginated(params)
.then((res) => {
model.data = res.data.data;
console.log("data", model.data);
})
.catch((err) => {
if (err.response.status === 401) console.log("UNAUTHORIZED");
notificationsStore.showToast(t("notifications.unknown_error"), "error");
});
};
And my UsersVew test:
it("should render users list", async () => {
const wrapper = mount(UsersView, {
global: {
plugins: [createTestingPinia({ createSpy: vi.fn, stubActions: false })]
}
})
await flushPromises()
const usersList = wrapper.findAllComponents('[data-test="users-list"]')
console.log(usersList)
})
The problem is that I have a previous login where I get the access_token and I put it globally in axios headers like this:
axios.defaults.headers.common['Authorization'] = Bearer ${res.data.access_token};
But I want to test my component but my component doesn't has the token globally when I throw the tests the list of users is empty
If anyone can help me I would be very grateful
Hi iam new to Vue and trying too build a MEVN application. What iam trying to do is when user adds item in cart it should store one document in mongoDB and if user adds more of same item only the price and quantity for the document should increase and not create new document.
Here is code for client when user adds item in cart,iam using Vue3:
async addToCart(state, product) {
console.log(state);
let dbProducts = await axios
.get(`http://localhost:1337/items/`)
.then((res) => res.data)
.catch((error) => console.log(error));
let item = dbProducts.find((i) => i.id === product.id);
console.log(item);
console.log('addTOcart');
if (item) {
console.log('put request');
item.quantity++;
console.log('quantity', item.quantity);
axios
//.put(`http://localhost:1337/items/${uniqueId}`, item)
.put(`http://localhost:1337/items/`, item)
.then((res) => {
console.log(res.data);
alert(res.data);
})
.catch((error) => console.log(error));
} else {
product = { ...product, quantity: 1 };
state.cart.push(product);
axios.post('http://localhost:1337/items', {
id: product.id,
title: product.title,
price: product.price,
quantity: product.quantity,
shortDesc: product.shortDesc,
category: product.category,
longDesc: product.longDesc,
imgFile: product.imgFile,
serial: product.serial,
});
}
},
And here is code for the server, iam using express js:
const express = require('express');
const app = express();
const Items = require('./Items');
const connection = require('./connection');
const Port = process.env.Port || 1337;
const cors = require('cors');
app.use(cors());
connection();
app.use(express.json());
app.post('/items', (req, res) => {
const data = new Items(req.body);
data
.save()
.then((Items) => {
console.log('item saved', Items);
res.json({ succcess: true, Items });
})
.catch((err) => {
console.log(err);
});
});
app.get('/items', async (req, res) => {
Items.find({}, (err, items) => {
res.json(items);
});
});
app.put('/items', function (req, res) {
console.log(req.body);
//Items.updateOne({ _id: req.body._id }, req.body);
Items.findOneAndUpdate({ _id: req.body._id }, req.body);
// Items.findOne({ _id: req.body._id });
});
app.listen(Port, () => {
console.log(`App running on port ${Port}`);
});
As #HeikoTheißen suggested, you should handle the logic of the operation on the server, using a single POST request:
const express = require('express');
const app = express();
const Items = require('./Items');
const connection = require('./connection');
const Port = process.env.Port || 1337;
const cors = require('cors');
app.use(cors());
connection();
app.use(express.json());
app.post('/items', async (req, res) => {
try {
let item = await Items.findById(req.body.id);
if (!item) {
item = await Items.create(req.body);
} else {
item.quantity++;
await item.save();
}
res.json({ succcess: true, item });
} catch (err) {
res.json({ succcess: false });
}
});
app.listen(Port, () => {
console.log(`App running on port ${Port}`);
});
You should simplify your client code as:
async function addToCart(state, product) {
try {
const { data } = await axios.post('http://localhost:1337/items', product);
// Add new product to card if necessary
if (!state.cart.some((p) => p.id === data.item.id)) {
state.cart.push(data.item);
}
} catch (err) {
console.log(err);
}
}
I'm trying to get Gifted Chat implemented in a realtime fashion with socket.io but I'm having issues. I'm able to get socket.io to connect, the message to be emitted, but it isn't showing up in real time when I have an android emulator and an iPhone simulator both running the app.
server.js
const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
// Attempt at Socket.io implementation
const socket = require('socket.io')
const io = socket(server)
const bodyParser = require('body-parser');
const Message = require("./models/message");
const SportsMessage = require('./models/sportsMessage')
const GamerMessage = require('./models/gamerMessage')
const mongoose = require('mongoose');
// MongoDB connection
mongoose.connect(
'mongodb+srv://yada:yada#cluster0.kt5oq.mongodb.net/Chatty?retryWrites=true&w=majority', {
useNewUrlParser: true,
useUnifiedTopology: true
}).then(() => {
console.log('Connected to the database!')
}).catch(() => {
console.log('Connection failed oh noooooo!')
});
// Parse the request body as JSON
app.use(bodyParser.json());
// GET messages, don't change these bro
app.get("/api/messages", (req, res) => {
Message.find({}).exec((err, messages) => {
if(err) {
res.send(err).status(500);
} else {
res.send(messages).status(200);
}
});
});
app.get("/api/sportsMessages", (req, res) => {
SportsMessage.find({}).exec((err, messages) => {
if(err) {
res.send(err).status(500);
} else {
res.send(messages).status(200);
}
});
});
app.get("/api/gamerMessages", (req, res) => {
GamerMessage.find({}).exec((err, messages) => {
if(err) {
res.send(err).status(500);
} else {
res.send(messages).status(200);
}
});
});
// POST messages
app.post('/api/messages', (req, res) => {
Message.create(req.body).then((message) => {
res.send(message).status(200);
}).catch((err) => {
console.log(err);
res.send(err).status(500);
});
});
app.post('/api/sportsMessages', (req, res) => {
SportsMessage.create(req.body).then((message) => {
res.send(message).status(200);
}).catch((err) => {
console.log(err);
res.send(err).status(500);
});
});
app.post('/api/gamerMessages', (req, res) => {
GamerMessage.create(req.body).then((message) => {
res.send(message).status(200);
}).catch((err) => {
console.log(err);
res.send(err).status(500);
});
});
// Socket.io connection
io.on('connection', socket => {
socket.emit('your id', socket.id)
socket.on('send message', body => {
console.log(body)
io.emit('send message', body)
})
console.log("connected to dat socket boiii")
})
server.listen(8000, () => console.log("server is running on port 8000"));
Chat Screen
import React, { useState, useEffect, useContext, useRef } from 'react'
import { View, Text, Button, StyleSheet } from 'react-native'
import io from 'socket.io-client'
import useMessages from '../hooks/useMessages'
import { Context as UserContext } from '../context/UserContext'
import { GiftedChat as GChat } from 'react-native-gifted-chat'
const GeneralChat = () => {
const [messages, ids, getMessages, randomId, setMessages] = useMessages()
const { state: { username } } = useContext(UserContext)
const socketRef = useRef()
socketRef.current = io('{MyIP}')
useEffect(() => {
getMessages()
randomId()
const socket = io('{MyIP}')
socket.on('your id', id => {
console.log(id)
})
}, [])
const onSend = (message) => {
let userObject = message[0].user
let txt = message[0].text
console.log(message)
setMessages(previousMessages => GChat.append(previousMessages, message))
const messageObject = {
text: txt,
user: userObject
}
socketRef.current.emit('send message', messageObject)
fetch("{MyIP}/api/messages", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(messageObject)
}).then((res) => {
return res.json();
}).catch((err) => {
console.log(err);
});
}
return (
<GChat
// isLoadingEarlier
scrollToBottom
infiniteScroll
loadEarlier
alwaysShowSend
renderUsernameOnMessage
inverted={true}
showUserAvatar
messages={messages}
onSend={message => onSend(message)}
user={{
_id: ids,
name: username,
avatar: 'https://placeimg.com/140/140/any'
}}
/>
)
}
GeneralChat.navigationOptions = () => {
return {
title: 'General Chat',
}
}
const styles = StyleSheet.create({
})
export default GeneralChat
So I have a mongodb database to which I have imported some json data to its collection.
When I do a db.posts.find(), the data imported successfully, but when I attempt a get request, I get an empty array [].
Here is my server.js file:
'use strict';
const express = require('express');
const morgan = require('morgan');
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const { DATABASE_URL, PORT } = require('./config');
const { BlogPost } = require('./models');
const app = express();
app.use(morgan('common'));
app.use(express.json());
app.get('/posts', (req, res) => {
BlogPost
.find()
.then(posts => {
res.json(posts.map(post => post.serialize()));
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went terribly wrong' });
});
});
app.get('/posts/:id', (req, res) => {
BlogPost
.findById(req.params.id)
.then(post => res.json(post.serialize()))
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went horribly awry' });
});
});
app.post('/posts', (req, res) => {
const requiredFields = ['title', 'content', 'author'];
for (let i = 0; i < requiredFields.length; i++) {
const field = requiredFields[i];
if (!(field in req.body)) {
const message = `Missing \`${field}\` in request body`;
console.error(message);
return res.status(400).send(message);
}
}
BlogPost
.create({
title: req.body.title,
content: req.body.content,
author: req.body.author
})
.then(blogPost => res.status(201).json(blogPost.serialize()))
.catch(err => {
console.error(err);
res.status(500).json({ error: 'Something went wrong' });
});
});
app.delete('/posts/:id', (req, res) => {
BlogPost
.findByIdAndRemove(req.params.id)
.then(() => {
res.status(204).json({ message: 'success' });
})
.catch(err => {
console.error(err);
res.status(500).json({ error: 'something went terribly wrong' });
});
});
app.put('/posts/:id', (req, res) => {
if (!(req.params.id && req.body.id && req.params.id === req.body.id)) {
res.status(400).json({
error: 'Request path id and request body id values must match'
});
}
const updated = {};
const updateableFields = ['title', 'content', 'author'];
updateableFields.forEach(field => {
if (field in req.body) {
updated[field] = req.body[field];
}
});
BlogPost
.findByIdAndUpdate(req.params.id, { $set: updated }, { new: true })
.then(updatedPost => res.status(204).end())
.catch(err => res.status(500).json({ message: 'Something went wrong' }));
});
app.delete('/:id', (req, res) => {
BlogPost
.findByIdAndRemove(req.params.id)
.then(() => {
console.log(`Deleted blog post with id \`${req.params.id}\``);
res.status(204).end();
});
});
app.use('*', function (req, res) {
res.status(404).json({ message: 'Yo stupido, Not Found' });
});
// closeServer needs access to a server object, but that only
// gets created when `runServer` runs, so we declare `server` here
// and then assign a value to it in run
let server;
// this function connects to our database, then starts the server
function runServer(databaseUrl, port = PORT) {
return new Promise((resolve, reject) => {
mongoose.connect(databaseUrl, err => {
if (err) {
return reject(err);
}
server = app.listen(port, () => {
console.log(`Your app is listening on port ${port}`);
resolve();
})
.on('error', err => {
mongoose.disconnect();
reject(err);
});
});
});
}
// this function closes the server, and returns a promise. we'll
// use it in our integration tests later.
function closeServer() {
return mongoose.disconnect().then(() => {
return new Promise((resolve, reject) => {
console.log('Closing server');
server.close(err => {
if (err) {
return reject(err);
}
resolve();
});
});
});
}
// if server.js is called directly (aka, with `node server.js`), this block
// runs. but we also export the runServer command so other code (for instance, test code) can start the server as needed.
if (require.main === module) {
runServer(DATABASE_URL).catch(err => console.error(err));
}
module.exports = { runServer, app, closeServer };
and here is my config.js file:
'use strict';
exports.DATABASE_URL =
process.env.DATABASE_URL || 'mongodb://localhost/seed_data';
exports.PORT = process.env.PORT || 8080;
In my models.js file, this is what my mongoose model looks like:
'use strict';
const mongoose = require('mongoose');
mongoose.Promise = global.Promise;
const blogPostSchema = mongoose.Schema({
author: {
firstName: String,
lastName: String
},
title: {type: String, required: true},
content: {type: String},
created: {type: Date, default: Date.now}
});
blogPostSchema.virtual('authorName').get(function() {
return `${this.author.firstName} ${this.author.lastName}`.trim();
});
blogPostSchema.methods.serialize = function() {
return {
id: this._id,
author: this.authorName,
content: this.content,
title: this.title,
created: this.created
};
};
const BlogPost = mongoose.model('BlogPost', blogPostSchema);
module.exports = {BlogPost};
The issue is with your first parameter in your mongoose.model(). Since you shared that the collection name is posts, that should be the name of your first parameter as a string 'posts'.
Checkout this documentation on how to declare collection name and model name:
How to declare collection name and model name in mongoose
So your mongoose.model() should look like this:
const BlogPost = mongoose.model('posts', blogPostSchema);
Give that a try.