Passing in an array of values to an express POST route - arrays

I have a mongoose model called Todo that looks like this:
content: [{
contentType: {
type: String,
default: null
},
contentValue: {
type: String,
default: null
}
}]
My express POST route looks like this:
app.post('/todos', authenticate, (req, res) => {
var todo = new Todo({
content: req.body.content
});
res.send(todo)
//I am sending instead of sending the result for testing
});
When I send int test data using Postman the content array is coming back empty "content": []
I have tried several formats of Body in postman including:
{
"content[contentType]": "reminder",
"content[contentValue]": "Will it blend"
}
and
{
"content": {
"contentType": "reminder",
"contentValue": "Will it blend"
}
}
However both come back with empty array.
{
"content": []
}
Do I need to change something on my POST route and\or send in teh data in an alternate format?

content here is a todo sub document, so you should treat it like the following:
app.post('/todos', authenticate, (req, res) => {
var content = req.body.content;
var todo = new Todo();
todo.content.push(content);
todo.save(function(err) {
if (err) throw err;
res.json(todo.toJSON())
//I am sending instead of sending the result for testing
});
});
See: Mongoose SubDocuments

Related

NextJS API routes how to handle multiple requests with MongoDB

I have an API route. Inside of this route I handle requests coming from my components with MongodDB. My problem is that I am sending a PUT request from one of my components to that route and it is working. But now I want to send another PUT request from another component. How will I achieve this?
if (req.method === "PUT") {
try {
const { _id, id, change } = req.body;
let set = `settings.$[el].${id}`;
const data = await db
.collection("Todos")
.updateOne(
{ _id: _id },
{ $set: { [set]: change } },
{ arrayFilters: [{ "el._id": id }] }
);
res.status(201).json(data);
} catch (err) {
res.status(500).json({ message: "Unable to instert the data." });
}
}
This is for my one request and now I want to send another one but also with another data. If I send it there will conflict so it fails. Some basic solutions I found but they are not sustainable.
One way is to create a new route /api/newRoute.
Another way is when you send the request add to its body a variable that differentiates between the two. For example:
body: {
// your original data
type: "newType" // this variable can be named anything you like
}
In the api route you can use the following code example:
if (req.method === "PUT" && req.body.type == "newType") {
try {
// your new code
} catch (err) {
// your new code
}
}

Get the image from the server

I uploaded an image file using axios post method and it was successfully uploaded to the server...
On return to the POST method, it returned the Image URL as:
{imageUrl: "/root/TTAppJava/images/players/Screenshot from 2020-11-24 16-38-57.png"}
Now, I want to display the image onto my screen.
How can I get that image?
I am using React.js to implement this.
The URL I used to post the image is:
http://139.59.16.180:8269/player/details/${id}
I am doing this to upload my data:
var formData = new FormData()
formData.append("file", image);
const theWrapper = {
"data": {
"name": name,
"age": age,
"email": email,
"gender": gender
}
}
formData.append("theWrapper", JSON.stringify(theWrapper))
Axios.post("http://139.59.16.180:8269/player/add",
formData,
{ headers: { Authorization: "Bearer " + localStorage.getItem("token") } }
).then(res => {
console.log(res)
alert("Player added successfully.")
history.push("/players")
})
.catch(err => alert(err.messge))
And the response I am getting is:
{id: 14, name: "shreyas", email: "asdfjka#gmail.com", gender: "Male", imageUrl: "/root/TTAppJava/images/players/Screenshot from 2020-11-24 16-38-57.png", …}
I will give you an example how its done in Node app, since the underlying concept will be the same as I am not a Java developer.
First please note your image_url/download_url should be saved as follows,
https://yourdomain/folder/image_name
example: http://localhost:3000/uploads_folder/my_image_name.jpg
and then you need a route in Java Spring which figures out what image to send to the front-end as Stream like below,
router.get("/:folder/:image_name", async (req, res) => {
const { folder, image_name } = req.params;
// find an image based on the downloadUrl in the folder where files are saved.
// Please note, after uploading file successfully generate a download url
// appropriately so that this route can help figure out which image you
// are looking for.
const file = path.join(`path/to/${folder}`, `${image_name}`);
// Figure out a way how stream works in your context.
// Providing MIME type is important!
const type = mime[path.extname(file).slice(1)] || "image/jpg";
const s = fs.createReadStream(file);
s.on("open", () => {
res.set("Content-Type", type);
s.pipe(res);
});
s.on("error", (err) => {
// Handle Error
});
});

Passing through an array with axios

I am having an issue passing through an array through axios post call. The issue is that on the api endpoint the data received is null, when I try posting using postman it works fine so the endpoint is working. Example of the array
I need to pass the data in this format:
{
"UpdateItemList": [
{
"Text": 1,
"Value": "5"
},
{
"Text": 1,
"Value": "5"
}
]
}
Code:
export function createLogEntry(postData) {
let payload = {
UpdateItemList: postData
};
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', {
data: payload
});
return {
type: CREATE_LOG,
payload: request
}
}
Is there any issue with the way I am passing through the data with my current code?
Try with
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry',payload);
This worked for me!
The issue is that you are confusing two ways axios can be used. Currently you are actually posting your data nested in an object within and the key data:
{
data: {
UpdateItemList: postData
}
}
If you are using the axios.post function, you should just pass your object with the data to post as the second object like this:
const request = axios.post('https://localhost:44312/api/Audit/AddLogEntry', payload);
If you are using the config object method, you should just pass one single object with url, method and data as keys.
// Send a POST request
axios({
method: 'post',
url: 'https://localhost:44312/api/Audit/AddLogEntry',
data: payload
});
This behaviour is explained in the axios Readme here: https://github.com/axios/axios#axios-api

Passing an object from React to Express and creating a new Airtable record

I’m having trouble passing an object from React to Express, and then creating an airtable record in Express.
In react, i am sending an http request to Express via:
finalSubmit() {
const airtableObj = {
title: 'hi',
}
fetch('api/submit',{
method: 'POST',
body: JSON.stringify(airtableObj),
headers: {"Content-Type": "application/json"}
})
}
My Express code is:
app.post('/api/submit', jsonParser, async (req, res) => {
const newStudy = JSON.stringify(req.body);
await console.log(newStudy);
table.create(newStudy, function(err, record) {
if (err) {console.log(err); res.json(err)} else {console.log(record), res.json('Success!')}
});
})
However, I keep getting errors back from the airtable api. IF I replace the 4th line of my express code with:
table.create({“title”:“hi”}
instead of
table.create(newStudy)
, everything works fine. It seems like this should work according to the airtable documentationt... (https://airtable.com/api). Is there something I am doing wrong with how I am manipulating my data in and out of JSON?
Thanks
This appears to be happening because you're calling JSON.stringify(req.body), which you don't need to do.
table.create takes an object, not a string, so you'll want to do something like this:
const newStudy = req.body;
table.create(newStudy, function(err, record) {
// ...
});
I found a solution, not sure if it's a very good one tho...
app.post('/api/submit', jsonParser, async (req, res) => {
table.create({
"title": `${req.body.post0.title}`} ...

Loopback4 File upload Storage component Example

I’m looking for an example for a file store using loopback4, could someone provide the controller configuration for file crud operations?
LoopBack 4 does not provide a built-in parser for multipart file upload requests. Instead, we provide extension points allowing applications to use a 3rd party parsers like multer.
There are two options how to write a controller accepting file uploads. You can learn more about this topic in our docs, see Parsing requests and Extending request body parsing
1. Handle file uploads in the controller method
Instruct LoopBack to pass the raw body stream to your controller method. In the controller method, call the file-upload parser to process the multi-part stream.
Benefits: different endpoints may want to process the uploaded files differently. By implementing file-upload parsing in a controller method, it's easy to customize all aspects of this process.
Cross-posting an example from file-upload.acceptance.ts:
import * as multer from 'multer';
class FileUploadController {
#post('/show-body', {
responses: {
// (left out for brevity)
},
})
async showBody(
#requestBody({
description: 'multipart/form-data value.',
required: true,
content: {
'multipart/form-data': {
// Skip body parsing
'x-parser': 'stream',
schema: {type: 'object'},
},
},
})
request: Request,
#inject(RestBindings.Http.RESPONSE) response: Response,
): Promise<Object> {
const storage = multer.memoryStorage();
const upload = multer({storage});
return new Promise<object>((resolve, reject) => {
upload.any()(request, response, err => {
if (err) reject(err);
else {
resolve({
files: request.files,
fields: (request as any).fields,
});
}
});
});
}
2. Implement & register a body parser for multi-part file uploads
In this option, all file-uploads are processed at transport layer in the same way for all controller methods. Controller methods receive parsed data.
Example body parser implementation from file-upload-with-parser.acceptance.ts:
class MultipartFormDataBodyParser implements BodyParser {
name = 'multipart/form-data';
supports(mediaType: string) {
// The mediaType can be
// `multipart/form-data; boundary=--------------------------979177593423179356726653`
return mediaType.startsWith('multipart/form-data');
}
async parse(request: Request): Promise<RequestBody> {
const storage = multer.memoryStorage();
const upload = multer({storage});
return new Promise<RequestBody>((resolve, reject) => {
upload.any()(request, {} as any, err => {
if (err) reject(err);
else {
resolve({
value: {
files: request.files,
fields: (request as any).fields,
},
});
}
});
});
}
}
An example controller leveraging this body parser:
class FileUploadController {
#post('/show-body', {
responses: {
// (left out for brevity)
},
})
async showBody(
#requestBody({
description: 'multipart/form-data value.',
required: true,
content: {
'multipart/form-data': {
schema: {type: 'object'},
},
},
})
{files, fields}: any,
) {
return body;
}
}

Resources