Browser Fetch() API Is Not Posting Body To Backend Node Server - node.js

Client Side Browser:
API
class API {
constructor() {
this.api = "http://localhost:3000";
}
async authenticate(product_id) {
const url = this.api + '/api/auth';
const body = {
"product_id": product_id,
}
console.log(body);
const request = {
method: 'POST',
body: body,
}
return await fetch(url, request);
}
}
module.exports = API;
INDEX
const account = await this.API.authenticate("56729b6b77c82288f746c0cf");
console.log(account)
In my console i get
Response {type: "cors", url: "http://localhost:3000/api/auth",
redirected: false, status: 401, ok: false, …} body : (...) bodyUsed :
false headers : Headers {} ok : false redirected : false status : 401
statusText : "Unauthorized" type : "cors" url :
"http://localhost:3000/api/auth"
Fetch failed loading: POST "http://localhost:3000/api/auth".
Server Side:
app.ts
import express from 'express';
import logger from 'morgan';
import bodyParser from 'body-parser';
import mongoose from 'mongoose';
import passport from 'passport';
import cors from "cors";
import Routes from './routes';
import Config from './config/config';
class App {
public app: express.Application;
public config: any;
constructor() {
this.app = express();
this.environment();
this.database();
this.middleware();
this.routes();
}
private environment(): void {
this.config = new Config();
}
private database(): void {
const uri: string = this.config.db.uri;
const options: any = this.config.db.options;
mongoose.connect(uri, options).then(
() => {
console.log("MongoDB Successfully Connected On: " + this.config.db.uri)
},
(err: any) => {
console.error("MongoDB Error:", err);
console.log('%s MongoDB connection error. Please make sure MongoDB is running.');
process.exit();
}
);
}
private middleware(): void {
this.app.use(cors());
this.app.use(logger('dev'));
this.app.use(express.json());
this.app.use(express.urlencoded());
this.app.use(passport.initialize());
}
private routes(): void {
const routes = new Routes(this.app);
}
}
export default App;
api/auth Route
public store(req, res) {
console.log(req.body)
}
the req.body is empty.

You should try adding in the request mode: cors in your request. The body should be a string and you might want to set header with content-type to application/json:
let headers = new Headers();
headers.set('Content-type', 'application/json');
const request = {
method: 'POST',
body: JSON.stringify(body),
mode: 'cors',
credentials: 'include',
headers: headers
}
It would also be helpful to see what happens in your browser network tab.

Related

How to set cookies using apollo server express

I am using apollo server express on my backend and next js on frontend.
I have been trying to set cookies in backend using (response) from context but unfortunately it is not working. i would like your help.
here is my backend code.
import http from 'http';
import { ApolloServer } from 'apollo-server-express';
import express from 'express';
import cors from 'cors';
import { makeExecutableSchema } from '#graphql-tools/schema';
import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core';
import { execute, subscribe } from 'graphql';
import {
SubscriptionServer,
ConnectionParams,
ConnectionContext,
} from 'subscriptions-transport-ws';
import { connect } from './Config';
import { typeDefs } from './TypeDefs';
import { resolvers } from './Resolvers';
import { isAuthForSubscription } from './Helpers';
import cookieParser from 'cookie-parser';
const startServer = async () => {
const app = express();
app.use(
cors({
credentials: true,
origin: 'http://localhost:3000',
})
);
app.use(cookieParser());
const httpServer = http.createServer(app);
const subscriptionServer = SubscriptionServer.create(
{
schema: makeExecutableSchema({ typeDefs, resolvers }),
execute,
subscribe,
onConnect: async (
connectionParams: ConnectionParams,
_websocket: any,
context: ConnectionContext
) => {
let user = null;
if (connectionParams.Authorization) {
user = await isAuthForSubscription(connectionParams.Authorization);
}
return { context, user };
},
},
{
server: httpServer,
path: '/graphql',
}
);
const server = new ApolloServer({
schema: makeExecutableSchema({ typeDefs, resolvers }),
plugins: [
ApolloServerPluginDrainHttpServer({ httpServer }),
{
serverWillStart: async () => {
return {
drainServer: async () => {
subscriptionServer.close();
},
};
},
},
],
context: ({ req, res }) => ({ req, res }),
});
await server.start();
server.applyMiddleware({ app });
await new Promise<void>(resolve =>
httpServer.listen({ port: 4000 }, resolve)
);
await connect();
console.log(
`server started on port http://localhost:4000${server.graphqlPath}`
);
return { server, app };
};
startServer();
// and my resolver is this one
import { ApolloError } from 'apollo-server-express';
import {
TCreateAccountArgs,
TLoginArgs,
TContext,
CookieName,
} from '../../__generated__';
import { generate } from '../../Helpers';
import { userModel } from '../../Models';
import { CookieOptions } from 'express';
export const login = async(_: any, args: TLoginArgs, { res, req }: TContext) => {
try {
const find = await userModel.findOne({ username: args.username });
if (!find) {
return new ApolloError('Account not found');
}
const comparePassword = generate.comparePassword(
find.password,
args.password
);
if (!comparePassword) {
return new ApolloError('Incorrect password or username');
}
const generateToken = generate.generateToken({ _id: find._id });
const cookieOptions: CookieOptions = {
httpOnly: true,
maxAge: 1 * 60 * 60 * 24 * 1000,
secure: true
};
res.cookie(CookieName.token, generateToken, cookieOptions);
return {
token: generateToken,
data: {
username: find.username,
_id: find._id,
email: find.email,
profilePicture: find.profilePicture,
createdAt: find.createdAt,
updatedAt: find.updatedAt,
},
};
} catch (error: any) {
return new ApolloError(
`Unable to login due to internal server error ${error.message}`
);
}
};
on frontend I am receiving this error message. Cannot read property 'cookie' of undefined
This question has been there from several months ago.
Just in case you haven't been able to fix it yet, the reason why you're not seeing the cookies in the frontend is that you're using the option httpOnly, those cookies are not supposed to be readable by the browser (they are useful to handle authentication in the server while protecting you from cross site scripting).
If you really need to read these cookies in the browser, you should set the httpOnly option to false.

Axios and Oauth1.0 - 'status: 400, Bad Request'

I'm new on Nodejs and all the modules related with Node. I've been trying to use axios for send a Oauth1.0 Autorization signature, but i'm getting: response: { status: 400, statusText: 'Bad Request', ...}
import { BASE_URL } from '../../../config/config.js';
import axios from 'axios';
import status from 'http-status';
import OAuth from 'oauth-1.0a';
import { createHmac } from 'crypto';
import dotenv from 'dotenv';
dotenv.config();
const CONSUMERKEY = process.env.consumer_key;
const CONSUMERSECRET = process.env.consumer_secret;
const TOKENKEY = process.env.access_token;
const TOKENSECRET = process.env.token_secret;
export const oauth = OAuth({
consumer: {
key: CONSUMERKEY,
secret: CONSUMERSECRET,
},
signature_method: 'HMAC-SHA1',
hash_function(base_string, key) {
return createHmac('sha1', key)
.update(base_string)
.digest('base64')
},
})
export const token = {
key: TOKENKEY,
secret: TOKENSECRET,
}
const doRequest = async (query) => {
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
return await axios.get(request_data.url, request_data.params, { headers: authHeader });
};
const searchU = async (term) => {
return await doRequest(`${term}`);
};
export const userS = async (req, res, next) => {
try {
const { query } = req;
const { data } = await searchU(query.q);
const string = JSON.stringify(data);
const Rs = JSON.parse(string);
const response = {
code: 1,
message: 'sucess',
response: Rs
};
res.status(status.OK).send(response);
} catch (error) {
next(error);
if (error.response){
console.log("Response: ");
console.log(error.response);
} else if(error.request){
console.log("Request: ");
console.log(error.request)
} else if(error.message){
console.log("Message: ");
console.log(error.message)
}
}
};
I've been also trying the solution given On this post: but there's no way I can make this work, no idea what i could be doing wron...
When i try the following code (see below), using Request module (which is deprecated) works well, but I really need to do it with Axios...
const request_data = {
url: `${BASE_URL}`,
method: 'GET',
params: { q: `${query}` },
};
const authHeader = oauth.toHeader(oauth.authorize(request_data, token));
request(
{
url: request_data.url,
method: request_data.method,
form: request_data.params,
headers: authHeader,
},
function(error, response, body) {
console.log(JSON.parse(body));
}
)
Any thoughts on what I'm doing wrong on this?? Thank you very much!!
Refer to the following link for the Request Config for Axios. I believe you need to have the query params after the header in the axios.get()
Axios Request Config
Try, the following and see how it goes:-
return await axios.get(request_data.url, { headers: authHeader }, request_data.params);

Angular: Error while fetching data from Node API?

I am trying to fetch json data from my Nodejs API using URL - localhost:3000/articles/publicationData which is running successfully in Postman app but don't know why is giving error with same url in angular app, but in Angular app it is giving an error -
HttpErrorResponse {headers: HttpHeaders, status: 404, statusText: "Not Found", url: "http://localhost:3000/articles/publicationData", ok: false, …}
error: "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n<meta charset=\"utf-8\">\n<title>Error</title>\n</head>\n<body>\n<pre>Cannot GET /articles/publicationData</pre>\n</body>\n</html>\n"
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
message: "Http failure response for http://localhost:3000/articles/publicationData: 404 Not Found"
name: "HttpErrorResponse"
ok: false
status: 404
statusText: "Not Found"
url: "http://localhost:3000/articles/publicationData"
My app-service.ts file is -
import { Injectable } from '#angular/core';
import { HttpClient} from '#angular/common/http';
import { AppSetting } from './appsetting'
#Injectable({
providedIn: 'root'
})
export class AppServiceService {
private SERVERURL = AppSetting.API;
constructor(private http: HttpClient) { }
login(user){
console.log(user);
return this.http.post<any>(this.SERVERURL+"users",user);
}
getPublication(){
let url = "http://localhost:3000/articles/publicationData";
return this.http.get(url);
}
}
My app.component.ts file
import { Component, OnInit } from '#angular/core';
import { DatepickerModule } from 'ng2-datepicker';
import { HttpClient } from '#angular/common/http';
import { Router } from '#angular/router';
import { DatepickerOptions } from 'ng2-datepicker';
import { AppServiceService } from './../app-service.service';
import { Subscriber } from 'rxjs';
#Component({
selector: 'app-main',
templateUrl: './main.component.html',
styleUrls: ['./main.component.css']
})
export class MainComponent implements OnInit {
constructor(private http: HttpClient,private auth : AppServiceService, private _router: Router) {
this.auth.getPublication().subscribe(data => {
console.warn(data);
})
}
ngOnInit(): void {
$("#menu-toggle").click(function(e) {
e.preventDefault();
$("#wrapper").toggleClass("toggled");
});
}
}
Controller.js
var db = require("../db.js");
var ObjectId = require('mongodb').ObjectID;
var mysql = require('mysql');
var connection = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'pass',
database: 'name'
});
var publicationData = (req, res) => {
var sql = `select pub_master.PubId, pub_master.Title,
pub_master.MastHead, pub_master.Circulation, pub_master.WebSite,
pub_master.Issn_Num, pub_master.Place, picklist.Name as city
from pub_master
join picklist on picklist.id = pub_master.Place
and picklist.id <> 0`;
connection.query(sql,[], function (error, results, fields) {
if (error) {
res.send({
"code":400,
"failed":"error ocurred"
})
}else{
if(results.length >0){
res.send({
"code":200,
result : results
});
}
else{
res.send({
"code":204,
"success":"Email and password does not match"
});
}
}
});
}
module.exports = {
publicationData: publicationData
}
Publication route
var express = require("express");
var articlescontroller = require("../controller/articlesController")
var articlesrouter = express.Router();
articlesrouter.route('/publicationData')
.post(articlescontroller.publicationData);
app.js
var express = require("express");
const serverless = require('serverless-http');
var moviesrouter = require("./routes/movierouter");
var articlesrouter = require("./routes/articlesrouter");
// var mailarticlerouter = require('./routes/mailarticlerouter');
var bodyParser = require("body-parser");
var mongoos = require("mongoose");
/*****************MYSQL CONNECTION*********************/
var mysql = require('mysql');
var connection = mysql.createPool({
host : '',
user : '',
password : '',
database : ''
});
/************************************* */
mongoos.set("debug", (collectionName, method, query, doc) => {
console.log(JSON.stringify(query));
});
mongoos.Promise = Promise;
var db = mongoos.connect("mongodb+srv://aamadmin:Rix2Jag8#irmpl-zame7.mongodb.net/impact?retryWrites=true&w=majority",{useUnifiedTopology: true,useNewUrlParser:true});
console.log("connected to mongodb");
var app = express();
var cors = require('cors');
const userrouter = require("./routes/userrouter");
app.use(cors());
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(bodyParser.json());
var server = app.listen(3000,()=>{
console.log("server is running on port 3000");
});
server.timeout = 600000;
module.exports.handler = serverless(app);
app.use('/articles',articlesrouter);
From your Postman screen, you need to send a POST request to localhost:3000/articles/publicationData, not a GET request. You have the 404 error with your code and when trying to access localhost:3000/articles/publicationData in browser because you're sending GET requests.
In your Angular code, change from :
getPublication(){
let url = "http://localhost:3000/articles/publicationData";
return this.http.get(url);
}
to :
getPublication(){
let url = "http://localhost:3000/articles/publicationData";
return this.http.post(url, {});
}

I am using socketio with react as the frontend and node with express js to make an app

When I am trying to connect using socketio client in the front end to the backened it is showin the error Access to XMLHttpRequest at 'http://localhost:8080/socket.io/?EIO=4&transport=polling&t=NOk7Aq9' 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.
front end code
import React, { Component, Fragment } from "react";
import openSocket from "socket.io-client";
import Post from "../../components/Feed/Post/Post";
import Button from "../../components/Button/Button";
import FeedEdit from "../../components/Feed/FeedEdit/FeedEdit";
import Input from "../../components/Form/Input/Input";
import Paginator from "../../components/Paginator/Paginator";
import Loader from "../../components/Loader/Loader";
import ErrorHandler from "../../components/ErrorHandler/ErrorHandler";
import "./Feed.css";
class Feed extends Component {
state = {
isEditing: false,
posts: [],
totalPosts: 0,
editPost: null,
status: "",
postPage: 1,
postsLoading: true,
editLoading: false,
};
componentDidMount() {
fetch("http://localhost:8080/feed/status", {
headers: {
Authorization: "Bearer " + this.props.token,
},
})
.then((res) => {
if (res.status !== 200) {
throw new Error("Failed to fetch user status.");
}
return res.json();
})
.then((resData) => {
console.log("status fetched ", resData.status);
this.setState({ status: resData.status });
})
.catch(this.catchError);
this.loadPosts();
console.log("openSocket", openSocket);
const socket = openSocket("http://localhost:8080/", {
transports: ["polling", "websocket"],
transportOptions: {
polling: {
extraHeaders: { "Access-Control-Allow-Origin": "*" },
},
},
});
socket.emit("connection", { data: "data" });
socket.on("posts", (data) => {
if (data.action === "create") {
this.addPost(data.post);
}
});
}
backend code
mongoose
.connect(
"mongodb://chitesh:pass123#cluster0-shard-00-00.ulx1q.mongodb.net:27017,cluster0-shard-00-01.ulx1q.mongodb.net:27017,cluster0-shard-00-02.ulx1q.mongodb.net:27017/feed?ssl=true&replicaSet=atlas-demxn2-shard-0&authSource=admin&retryWrites=true&w=majority",
{ useNewUrlParser: true, useUnifiedTopology: true }
)
.then((result) => {
const server = app.listen(8080); // this basically return us the server
const io = require("./socket.js").init(server);
// websockets uses http protocols the basis
//so we are passing our http based server to the function
// to create a websocket connection
// we are setting up a function
// to be executed whener a new connection is made
io.on("connection", (socket) => {
console.log("Client connected");
});
})
.catch((error) => {
console.log(error);
});
socket.js
const { listenerCount } = require("./models/post");
let io;
module.exports = {
init: (httpServer) => {
io = require("socket.io")(httpServer);
return io;
},
getIO: () => {
if (!io) {
let error = new Error("Socket.io is not initialized");
throw error;
}`enter code here`
return io;
},
};
Take a look at express CORS middleware.
You'll need to allow localhost:3000 to be used as origin.
You can use something like
var express = require('express')
var cors = require('cors')
var app = express()
var corsOptions = {
origin: 'http://localhost:3000',
}
app.use(cors(corsOptions))

How to pass parameters in headers

I need to call an API from my Angular Node application.For that i have to pass username and password along with header request.How to pass parameters?
I tried below code
From Angular service,
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json')
.set('userName','prismtest')
.set('password','12345678');
return this.http.post('/upload/checkUserApi/', { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
In Node,
router.post('/checkUserApi',function(req,res,next){
var proxyUrl = 'http://cors-anywhere.herokuapp.com/';
Request.post({
"headers": { "userName": "prismtest","password":"12345678" },
"url": proxyUrl+"https://example.com",
"body": {}
}, (error, response, body) => {
if(error) {
return console.log(error);
}
res.send(response);
});
});
You can pass the form parameters as the second attribute to post request:
checkUserApi(url: string): Observable<any> {
const headers = new HttpHeaders()
.set('Authorization', 'my-auth-token')
.set('Content-Type', 'application/json');
return this.http.post('/upload/checkUserApi/', {username: 'prismtest', password: '123'}, { headers })
.map((response: Response) => {
console.log(response);
return response;
})
}
You can do it by using interceptors which is Angular Service.
this should be helpfull :How to pass a param to HttpInterceptor?
Can you try below code following
/* SERVICE ANGULAR*/
import {Injectable} from '#angular/core';
import {HttpClient, HttpHeaders} from '#angular/common/http';
import {Observable,of} from 'rxjs';
import { map,catchError } from 'rxjs/operators';
import {User} from '../_models';
const httpOptions = {
headers:new HttpHeaders({'Content-Type':'application/json'})
};
const API_URL = "http://localhost/app/api";
#Injectable({
providedIn:'root',
})
export class UserService{
constructor(private http:HttpClient){}
/**
* POST LOGIN USER
*/
login(user: any) {
return this.http.post<any>(API_URL+"/login", user,httpOptions)
.pipe(map(user => {
return user;
}));
}
}
/*NODEJS*/
/* 1) install $ npm install body-parser --save*/
var bodyParser = require('body-parser');
app.use(bodyParser.json()); // support json encoded bodies
app.use(bodyParser.urlencoded({ extended: true })); // support encoded bodies */
/ POST http://localhost:8080/api/users
// parameters sent with
app.post('/api/login', function(req, res) {
var user_id = req.body.id;
var token = req.body.token;
var geo = req.body.geo;
res.send(user_id + ' ' + token + ' ' + geo);
});
Can you seen : Use ExpressJS to Get URL and POST Parameters
Login State Angular + Laravel
const headerOptions = {
headers : new HttpHeaders({
'Constent-Type' : 'application/json',
'Authorization : 'you token here'
})
}
http.post('you action', {body Params}, headerOptions, function(res){
console.log('your respose is ', res);
})

Resources