Angular post request to NodeJS JSON error - node.js

So i am sending a POST request to a nodeJS app, my request in Angular looks like this:
export class SearchComponent {
constructor(private http: HttpClient) {}
newWord = '';
keyword = '';
onClick() {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
this.http
.post('http://localhost:3000/search', JSON.stringify(this.keyword), {
responseType: 'text',
headers: headers,
})
.subscribe((data) => {
this.newWord = data;
});
}
}
When i try to console.log the request i get an Unexpected token " in JSON at position 0 error even though i tried all the solutions i could find on stackoverflow this is how my NodeJS app is set and the error:
const bodyParser = require("body-parser");
const express = require("express");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.all("/*", function (req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,OPTIONS");
res.header(
"Access-Control-Allow-Headers",
"Content-Type, Authorization, Content-Length, X-Requested-With"
);
next();
});
app.listen(3000, () => {
console.log("Server is running on port 3000");
});
app.post("/search", (req, res) => {
res.send(req.body);
});
The error i get is this:
SyntaxError: Unexpected token " in JSON at position 0
at JSON.parse (<anonymous>)....
Note that the this.keyword gets its value from a input field if i dont use JSON.stringify no error is happening but the req variable is "undefined".

Assuming you are asking how to get back the data. I'm not sure if this will work, but you can give it a try:
Under comments, see that you mean this.keyword. Here is the change I would make
going by axis format, this may be incorrect
.post('http://localhost:3000/search', JSON.stringify(this.keyword), {
responseType: 'text',
headers: headers,
})
instead, try:
.post('http://localhost:3000/search', {
keyword: this.keyword, // changed this
responseType: 'text',
headers: headers,
})
also in your server, you can change to this:
const app = express();
app.use(express.json())
app.use(express.text())
app.use(express.urlencoded({ extended: true }))
(body parser included in express now)
new to the mern stack (have never used Angular) so kind of iffy but hopefully that can help

Related

Message received from background. Values reset

I'm sending post request from "angular->port 4200" to "expressjs server->port 8000".
As an example i'm folowing this example: https://github.com/kuncevic/angular-httpclient-examples/blob/master/client/src/app/app.component.ts
I'm getting two error :
1)undefined from Nodejs(data and req.body.text)
2)Message received from background. Values reset
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.post<string>(`http://127.0.0.1:8000/appculture`, culture, {
headers: headers
})
.subscribe(data => {
});
}
expressjs side:
const express = require('express');
const app = express();
const bodyParser = require('body-parser');
var path = require('path');
app.all("/*", function(req, res, next){
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS');
res.header('Access-Control-Allow-Headers', 'Content-Type, Authorization, Content-Length, X-Requested-With');
next();
});
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
app.post('/appculture', function (req, res) {
var currentCulture = `${req.body.text} from Nodejs`;
req.body.text = `${req.body.text} from Nodejs`;
res.send(req.body)
})
app.listen(8000, () => {
console.log('server started');
})
Either you are not sending anything of there is no value in body.text
Try to console.log(req.body) instead of req.body.text.
Try to console.log(culture) and this.getLangCookie() on the client side to see if you are actually sending something.
You can also make use of the network tab in the browser to inspect the request that you are sending.
Angular side:
callServer() {
const culture = this.getLangCookie().split("-")[0];
const headers = new HttpHeaders()
headers.set('Authorization', 'my-auth-token')
headers.set('Content-Type', 'application/json');
this.http.get(`http://127.0.0.1:8000/appculture?c=` + culture, {
headers: headers
})
.subscribe(data => {
});
}
Nodejs side:
app.get('/appculture', function (req, res) {
currentCulture = req.query.c;
res.send(req.body)
})

Post req.body is always empty object

I'm using Typescript Fetch wrapper to do post and get requests and getting empty object on post(get works fine) (Before I used Vanilla Js and all worked fine)
Nodejs:
const express = require('express');
const fs = require('fs');
const app = express();
app.use(function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header(
'Access-Control-Allow-Headers',
'Origin, X-Requested-With, Content-Type, Accept'
);
next();
});
app.use(express.json());
app.post('/login', (req, res) => {
let isLogged = login(req.body);
console.log(req.body);
res.status(200).json(isLogged);
});
My Typescript fetch Wrapper:
async function fetchWrapper<T>(path: string, config: RequestInit): Promise<T> {
const request = new Request(path, config);
const response = await fetch(request);
if (!response.ok) {
throw new Error(
`name: ${response.status}, message: ${response.statusText}`
);
}
// return empty object
return response.json().catch(() => ({}));
}
export async function post<T, U>(
path: string,
body: T,
config?: RequestInit
): Promise<U> {
const init = { method: 'post', body: JSON.stringify(body), ...config };
return await fetchWrapper<U>(path, init);
}
my post request:
const res = await fetch.post(`${url}/login`, {
body: inputData,
headers: { 'Content-Type': 'application/json' },
});
input data is not empty
The problem here that you are using wrong Content-Type header value. express.json parses application/json content type, while you are sending application/x-www-form-urlencoded. The solution is either to change the content-type you are sending, or add another middleware like bodyparser to parse application/x-www-form-urlencoded body.

Getting back empty response body when making a POST request using Angular + Express

I'm trying to make a simple POST request but I'm getting an empty response back from the server. I've sifted through all the SO questions regarding this topic and tried the solutions posted but to no avail.
I've tried changing the request header options to use 'application/x-www-form-urlencoded' and set bodyParser in my express app as app.use(bodyParser.urlencoded({ extended: true })); but that didn't work either.
auth-service.service.ts
login(loginInfo: object) {
return this.http.post<loginInfo>(this.loginUrl, { "test": "test" })
.pipe(
catchError(this.handleError)
);
}
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
console.log('An error occured:', error.error.message);
} else {
console.log(`Backend returned code ${error.status}, ` +
`body was ${error.error}`);
}
return throwError('Something bad happened; please try again later.')
}
login.component.ts (calls the login service method)
onSubmit() {
const loginInfo = { username: this.username.value, password: this.password.value };
this.authService.login(loginInfo).subscribe(
resp => { console.log(resp); },
err => { console.log(err); }
)
}
server.js (I've defined routes here but they're not relevant)
const express = require('express');
const bodyParser = require('body-parser');
const api = require('./routes/api');
const app = express();
const port = process.env.port || 3000;
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
next();
})
app.use(bodyParser.json());
app.use('/api', api)
app.get('/', function (req, res) {
res.send(JSON.stringify('Hello from server'));
})
app.post('/login', (req, res) => {
let userData = req.body
res.send('Request body: ' + JSON.stringify(userData));
})
app.listen(port, function () {
console.log('Server running on localhost: ' + port);
});
I'm console logging the following:
Backend returned code undefined, body was undefined
Something bad happened; please try again later.
When I try using Postman, however, I get the response I expect (i.e. Request body: {})
I'm not sure as to why a response is retrieved when done through Postman but not when done through the app.
Any help is appreciated. Thanks!
You need to set body for POST request in auth-service.service.ts:
import { HttpParams } from '#angular/common/http';
login(loginInfo: object) {
const body = new HttpParams()
.set('test', 'test');
return this.http.post<loginInfo>(this.loginUrl, body)
.pipe(
catchError(this.handleError)
);
}
try using express.json its missing
app.use(express.json());
and
app.use(bodyParser.urlencoded({
extended: true
}));

NodeJS server can't retrive post data from Angular

I have a backend server writen in NodeJS, which use express.
I have the latest Angular as frontend, I post a data (GPG file) to the nodeJS server, and I try to get that data in NodeJS code, and print it out in the server console, but all I get is an empty object.
All I want to do is to either pass the Blob data to node server, or to pass a plain text to node server, and read it from node code.
const express = require('express'),
app = express(),
port = process.env.PORT || 3000;
app.listen(port);
const cors = require('cors');
app.use(cors());
//create a cors middleware
app.use(function (req, res, next) {
//set headers to allow cross origin request.
res.header("Access-Control-Allow-Origin", "*");
res.header('Access-Control-Allow-Methods', 'PUT, GET, POST, DELETE, OPTIONS');
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
const bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: true
}));
app.post('/decrypt', (res, req) => {
// Here I try to access the data that I passed by POST method
console.log(res.body);
return 'data back';
})
This is my Angular Code:
import { Injectable, Input } from '#angular/core';
import { HttpClient, HttpResponse, HttpHeaders } from '#angular/common/http';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/do';
import { Observable } from 'rxjs/Observable';
import { saveAs } from 'file-saver/FileSaver';
#Injectable()
export class DatabaseService {
private API_GET_LIST_FILES = 'http://localhost:3000/files';
private API_GET_FILE = 'http://localhost:3000/download?name=';
private BASE_URL = 'http://localhost:3000/';
constructor(private http: HttpClient) { }
getFile(key: string) {
return this.http.get(this.API_GET_FILE + key, {
responseType: 'blob'
})
.map(res => {
return {
filename: key.split('/').pop(),
data: res
};
})
.subscribe(res => {
console.log('start download:', res);
// no matter what I pass here to the decrypt function, I can't get it in nodeJS server
this.decrypt(res.filename)
.subscribe(
next => console.log(next)
);
saveAs(res.data, res.filename);
}, error => {
console.log('download error:', JSON.stringify(error));
}, () => {
console.log('Completed file download.');
});
}
decrypt(res): Observable<any> {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/octet-stream'
})
};
return this.http.post(this.BASE_URL + 'decrypt', res, httpOptions);
}
}
If I pass the ***res*** to the decrypt function, I will get a lot info but looks weird to me.
Do what Anand suggested, set headers to application/json (or just skip httpOptions completely as that is default) and send {name: res}. Request body then should be just that.
For file upload you should use Express middleware like Multer or Multiparty. On Angular side for example ng2-file-upload.
Express method callback signature is (req, res, next) not (res, req), it is confusing when reading your code :(
And if you just return from callback, it will hang until http request times out (I think). You should do res.status(200).end() or res.json({done: true}) or anything similar.

Getting axios data from post request in my node-js back-end

I send a post request in my vue component file :
axios.post('/add-couple', {
word_key: this.word_key,
word_value: this.word_value
})
.then((response) => {
this.word_key = ''
this.word_value = ''
})
And handle that in dev-server.js(using express):
app.post('/add-couple', (req,res) => {
newCouple(req.word_key,req.word_value)
console.log(req.word_key,req.word_value) //undefined undefined
res.end()
})
So, i want to use word_key and word_value vars, but cant, because they're both undefined. What am i doing wrong?
You should use body-parser middleware and req.boby object to get sent params:
var bodyParser = require('body-parser');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.post('/add-couple', (req, res) => {
console.log(req.body.word_key, req.body.word_value);
...
});

Resources