I have created an API in Nodejs. I have tried creating a call which returns HTML to display a site in the browser.
My Call looks like this:
router.get('/displayHTML', checkAccessToken, (req, res, next) => {
if (req.query.data === undefined) {
return res.status(900).json({
message: 'Data does not exist'
});
}
Data.find({ data: req.query.data}).exec()
.then(data => {
if (data.length < 1) {
return res.status(400).json({
message: "Nothing found"
});
}
// I need to return HTML here so the user sees something in his browser
return res.status(200).json({
data: data
});
}).catch(error => {
return res.status(500).json({
message: error
});
});
});
Check the fs_library: https://nodejs.org/docs/v0.3.1/api/fs.html
var http = require('http'),
lib = require('fs');
lib.readFile('./page.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8000);
});
Related
I built a REST API using Express, a JSON file (database), and deployed it on Heroku. I consume this API from my React.JS app which I run on localhost. It seems my data is not persist after I restart my React.JS app.
Here is my server.js file:
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const fs = require('fs');
const port = process.env.PORT || 3000;
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, PATCH, OPTIONS');
if (req.method === 'OPTIONS') {
res.send(200);
} else {
next();
}
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// GET ALL TODOS
app.get('/api/todos', (req, res) => {
let data = '';
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
data = JSON.parse(resp);
res.send(data.todos);
});
});
// GET A TODO
app.get('/api/todos/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
let data = JSON.parse(resp);
let todoData = data.todos.filter(todo => todo.id === parseInt(req.params.id))
if (todoData.length > 0) {
res.status(200).send(todoData[0]);
} else {
res.status(500).send({ message: 'Error: not found any task with that id' });
}
});
});
// POST A TODO
app.post('/api/todo', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
const { id, task, status } = req.body
if (id && task && status) {
let json = JSON.parse(resp);
json.todos.push(req.body);
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(json), err => {
if (err) return console.log('Error::writing task to the data.json file ', err);
});
res.status(200).send({ message: 'Success: data have been added' });
} else {
res.status(500).send({ message: 'Error: all fields must be filled with data' })
}
});
});
// EDIT A TODO
app.put('/api/todo/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
const id = parseInt(req.params.id)
const { task, status } = req.body
if (task && status) {
let json = JSON.parse(resp);
let newTodo = json.todos.map(todo => {
if(todo.id === id) {
return {
id,
task,
status
}
} else {
return todo
}
})
let result = {
todos: newTodo
}
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(result), err => {
if (err) return console.log('Error::editing task to the data.json file ', err);
res.status(200).send({ message: 'Success: task have been edited' });
});
} else {
res.status(500).send({
message: 'Error: all fields must be filled with data'
})
}
});
});
// DELETE A TODO
app.delete('/api/todo/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
let json = JSON.parse(resp);
let isDataExist = json.todos.some(todo => todo.id === parseInt(req.params.id))
if (isDataExist) {
let leftTodo = json.todos.filter(todo => todo.id !== parseInt(req.params.id))
let result = {
todos: leftTodo
}
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(result), err => {
if (err) return console.log('Error::deleting task to the data.json file ', err);
res.status(200).send({ message: 'Success: a task has been deleted' });
});
} else {
res.status(500).send({ message: 'Error: a task you want to delete is not exist' })
}
});
});
app
.listen(port, () => {
console.info(`Your api server is running on http://localhost:${port}`);
})
.on('error', () => {
console.error('Error::server ', error);
});
I save the data in data.json file. You could see the logic in every API block URL / route. What are wrong in my server code?
Note: If you want to see my repo for this project: https://github.com/ridoansaleh/api
a JSON file (database)
A JSON file isn't a proper database, and Heroku's ephemeral filesystem makes this an especially bad choice: any changes you make to it will be lost the next time your dyno restarts. This happens frequently (at least once per day).
If you want to persist data permanently you need to use a proper client-server database. Heroku provides a hosted PostgreSQL service that has a free tier. I recommend starting there.
I am making a http request from my angular2+ code to database present in node.js file. The ajax call from angular2+ hits the controller.js file and then redirects to service.js file which has the connection to the database:
angular.ts ==> controller.js ==> service.js
From the database the service.js file gives the output to controller.js file and then answers the ajax call to angular.ts file:
service.js ==> controller.js ==> angular.ts
However, I am getting the error:
POST http://localhost:8096/dashboard/abcEntireSuccess1/ 404 (Not Found)
UPDATED
Cannot GET /dashboard/experianEntireSuccess1/
And one more issue -
UnauthorizedError: No authorization token was found
And one more issue -
After coming back from the hit in service.js which has the data i want ==> to => controller.js , here the data is acquired is undefined. As seen below -
The output on Nodejs -
output -
service.js
closed connection
yessss [ RowDataPacket { ....
controller.js
we are coming back to controller undefined
some error occured of abcEntireSuccess1
My Entire Code:
UPDATED
abc.component.ts
viewAbcEntireSuccess1() {
var url = config.url;
var port = config.port;
this.http.post("http://" + url + ":" + port + "/dashboard
/abcEntireSuccess1/", this.emptyObj
, { headers: new Headers({ 'Authorization': 'Bearer ' +
localStorage.getItem('Token') }) })
.map(resultConnection => this.resultConnection =
resultConnection.json(), )
.subscribe((res: Response) => {
this.records = res;
this.resultConnectionlength = this.resultConnection.length;
});
}
abc.controller.js
router.post('/experianEntireSuccess1',experianEntireSuccess1);
module.exports = router;
function abcEntireSuccess1(req, res) {
dashboardService.abcEntireSuccess1(req.body)
.then(function (result) {
console.log("we are coming back to controller",result)
if (result.length > 0) {
console.log("we get data in node of abcEntireSuccess1 ::
" + Object.values(result));
console.log(result.length + " record found ");
res.send(result);
}
else {
result=[];
res.send(result);
}
})
.catch(function (err) {
res.status(400).send(err);
console.log("some error occured of abcEntireSuccess1");
});
}
abc.service.js
async function abcEntireSuccess1() {
console.log("function called")
const db = new Database();
await db.query(`select * from TRANSACTION_PAYLOAD where INTERFACE_NAME
= 'Abc' AND (STATUS ='SUCCESS_RESPONSE')`
).then(rows => {
console.log("closed connection");
console.log("yessss",rows)
return rows;
});
};
class Database {
constructor() {
this.connection = mysql.createConnection({
host: "127.0.0.1",
user: "abc",
password: "abc",
database: "DB"
});
}
query(sql, args) {
console.log("sql is", sql)
return new Promise((resolve, reject) => {
this.connection.query(sql, (err, rows) => {
console.log("connection function called")
if (err) {
console.log("error is", err)
return reject(err);
}
console.log("rows are",rows);
resolve(rows);
});
});
}
close() {
console.log("calling connection close")
return new Promise((resolve, reject) => {
console.log("called connection close")
this.connection.end(err => {
if (err){
return reject(err);
}
resolve();
});
});
}
}
I am trying to figure out how I can catch an error when a requested id is not found in the Database records.
My code is:
router.get('/users/:id', function(req, res) {
getId = req.params.id
db.con.query('SELECT * FROM employees where id=?', getId, function(err, results) {
if (err) {
console.log('error in query')
return
} else {
obj = {
id: results[0].id,
name: results[0].name,
location: results[0].location
// error should be cached here when a requested results[0].id is not found
}
res.render('showuser');
}
})
});
In the console, I get the following error when a non-existed id is requested as it should be, however I cannot catch this error programmatically.
throw err; // Rethrow non-MySQL errors
^
ReferenceError: id is not defined
at Query._callback (C:\NodeJS\CRUD\CRUD-4\routes\add.js:21:13)
Node: v8.8.0
Express: v4.15.5
Try this:
try{
obj = {
id: results[0].id,
name: results[0].name,
location: results[0].location
}
}catch(err){
//handle error
}
try {...}catch... is how you handle exceptions in JavaScript. You can read more about it here.
// Error handler
app.use(function(err, req, res, next) {
res.status(500).end(err.message);
});
...
router.get('/users/:id(\\d+)', function(req, res, next) {
var id = req.params.id;
db.con.query('SELECT * FROM employees where id= ?', id, function (err, results) {
if (err)
return next(err);
if (results.length == 0)
return next(new Error('Incorrect id: ' + id));
obj = {
id: results[0].id,
name: results[0].name,
location: results[0].location
}
res.render('showuser', obj);
});
})
Try the code below:
router.get('/product/:id', function(req, res, next){
try {
const { idProduct } = req.body
const [detailProduct] = await Product.detail(idProduct);
if (detailProduct.length === 0) {
return res.status(404).send({
status: "404",
msg: "Not found",
data: null
});
}
return res.status(200).json(detailProduct[0])
} catch (error) {
if (!error.statusCode) {
error.statusCode = 500
}
next(error)
}
}
I'm working with HTTP requests on a MEAN stack.
When I'm developing on localhost, all of the requests work.
But, when I try to do the same requests via production, they do not work.
Here's the error I am getting when trying to POST...
ERROR SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
I'm also getting an error with GET after sending my POST request.
GET http://atozinsurance.herokuapp.com/post 503 (Service Unavailable)
I know this means I'm receiving HTML instead of JSON. What am I doing wrong in my code to be requesting HTML?
Here is my NodeJS route for posts
var express = require('express');
var router = express.Router();
var jwt = require('jsonwebtoken');
var Post = require('../models/post');
router.get('/', function(req, res, next) {
Post.find()
.exec(function(err, posts){
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Success',
obj: posts
});
});
});
// router.use('/', function (req, res, next) {
// jwt.verify(req.query.token, 'secret', function (err, decoded) {
// if (err) {
// return res.status(401).json({
// title: 'Not Authenticated',
// error: err
// });
// }
// next();
// })
// });
router.post('/', function (req, res, next) {
const post = new Post({
title: req.body.title,
content: req.body.content,
date: req.body.date
});
post.save(function(err, result) {
if (err) {
return res.status(500).json({
title: 'An error occured',
error: err
});
}
res.status(201).json({
message: 'Post saved',
obj: result
});
});
});
router.patch('/:id', function (req, res, next) {
Post.findById(req.params.id, function (err, post) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!post) {
return res.status(500).json({
title: 'No Post Found!',
error: {message: 'Post not found'}
});
}
post.title = req.body.title;
post.content = req.body.content;
post.date = req.body.date;
post.save(function(err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Updated post',
obj: result
});
});
});
});
router.delete('/:id', function(req, res, next) {
Post.findById(req.params.id, function (err, post) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
if (!post) {
return res.status(500).json({
title: 'No Post Found!',
error: {post: 'Post not found'}
});
}
post.remove(function(err, result) {
if (err) {
return res.status(500).json({
title: 'An error occurred',
error: err
});
}
res.status(200).json({
message: 'Deleted post',
obj: result
});
});
});
});
module.exports = router;
And here is my service that is sending the requests via Angular.
import { Http, Response, Headers } from "#angular/http";
import { Injectable, EventEmitter } from "#angular/core";
import 'rxjs/Rx';
import { Observable } from "rxjs";
import { Post } from "./blog.model";
#Injectable()
export class PostService {
private posts: Post[] = [];
inputEditMessage = new EventEmitter<Post>();
url = 'http://atozinsurance.herokuapp.com/post';
devUrl = 'http://localhost:8080/post/';
constructor(private http: Http) {
}
addPost(post: Post) {
const body = JSON.stringify(post);
const headers = new Headers({'Content-Type': 'application/json'});
// const token = localStorage.getItem('token')
// ? '?token=' + localStorage.getItem('token')
// : '';
return this.http.post(this.url, body, {headers: headers})
.map((response: Response) => {
const result = response.json();
const post = new Post(
result.obj.title,
result.obj.content,
result.obj.date,
result.obj._id);
this.posts.push(post);
return post;
})
.catch((error: Response) => Observable.throw(error.json()));
}
getPosts() {
return this.http.get(this.url)
.map((response: Response) => {
const posts = response.json().obj;
let transformedPosts: Post[] = [];
for (let post of posts) {
transformedPosts.push(new Post(
post.title,
post.content,
post.date,
post._id)
);
}
this.posts = transformedPosts;
return transformedPosts;
})
.catch((error: Response) => Observable.throw(error.json()));
}
editPost(post: Post) {
this.inputEditMessage.emit(post);
}
updatePost(post: Post) {
const body = JSON.stringify(post);
const headers = new Headers({'Content-Type': 'application/json'});
const token = localStorage.getItem('token')
? '?token=' + localStorage.getItem('token')
: '';
return this.http.patch(this.url + '/' + post.postId + token, body, {headers: headers})
.map((response: Response) => response.json())
.catch((error: Response) => Observable.throw(error.json()));
}
deletePost(post: Post) {
this.posts.splice(this.posts.indexOf(post), 1);
const token = localStorage.getItem('token')
? '?token=' + localStorage.getItem('token')
: '';
return this.http.delete(this.url + '/' + post.postId + token)
.map((response: Response) => response.json())
.catch((error: Response) => Observable.throw(error.json()));
}
}
As I stated before, with localhost (called devUrl) it works fine. But when I switch to url or production mode, it fails.
Anyone know where the bug is?
EDIT *** This is the HTML error I am receiving.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="utf-8">
<title>Application Error</title>
<style media="screen">
html,body,iframe {
margin: 0;
padding: 0;
}
html,body {
height: 100%;
overflow: hidden;
}
iframe {
width: 100%;
height: 100%;
border: 0;
}
</style>
</head>
<body>
<iframe src="//www.herokucdn.com/error-pages/application-error.html"></iframe>
</body>
</html>
EDIT ***
Here is my server.js file
const express = require('express');
const path = require('path');
const cookieParser = require('cookie-parser');
const bodyParser = require("body-parser");
const mongoose = require('mongoose');
const appRoutes = require('./routes/app');
const mailRoutes = require('./routes/mail');
const userRoutes = require('./routes/user');
const postRoutes = require('./routes/post');
const app = express();
const uristring =
process.env.MONGOLAB_URI ||
process.env.MONGOHQ_URL ||
'localhost:27017/atoz';
mongoose.connect(uristring, function (err, res) {
if (err) {
console.log ('ERROR connecting to: ' + uristring + '. ' + err);
} else {
console.log ('Succeeded connecting to: ' + uristring);
}
});
app.set('views', path.join(__dirname, './dist'));
app.set('view engine', 'ejs');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, './dist')));
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');
res.header('Access-Control-Allow-Methods', 'POST, GET, PATCH, DELETE, OPTIONS');
next();
});
app.use('/user', userRoutes);
app.use('/post', postRoutes);
app.use('/mail', mailRoutes);
app.use('/', appRoutes);
//catch 404 and forward error handler
app.use('*', appRoutes);
app.listen(process.env.PORT || 8080);
module.exports = app;
EDIT ***
Here is the error I am receiving from heroku logs
at=error code=H12 desc="Request timeout" method=POST path="/post" host=atozinsurance.herokuapp.com request_id=c4e340d3-8ee3-4c2f-ae12-e56e7439c0f1 fwd="68.111.238.205" dyno=web.1 connect=1ms service=30001ms status=503 bytes=0 protocol=http
Macs-MacBook-Pro-2:atoz-app joncorrin$
For anyone having this issue. You're receiving HTML from Heroku. The first character in HTML is a < which explains why it is definitely not JSON.
MY SOLUTION:
I did not set my environment variable for MONGOLAB_URL. Therefor heroku could not connect to the database correctly and the request was timing out.
Set it as MongLab addon and worked perfectly.
This is my app.js generated by express js while installing:
// catch 404 and forward to error handler
app.use(function(req, res, next) {
console.log("coming to this use func");
var err = new Error('Not Found');
err.status = 404;
next(err);
});
// error handlers
// development error handler
// will print stacktrace
if (app.get('env') === 'development') {
app.use(function(err, req, res, next) {
console.log("Dev request sent");
console.log(err.message);
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: err
});
});
}
// production error handler
// no stacktraces leaked to user
app.use(function(err, req, res, next) {
console.log("testing this function");
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});
// I wrote this code to detect '127.0.0.1:3000/enter' in the url
// correspondingly fetches questions from the database
app.post('/enter', function(req, res, next) {
console.log("Coming here.");
connection.query('SELECT * from questions_table', function(err, rows, fields) {
if (!err) {
console.log('The solution is: ', rows);
var myData = JSON.stringify(rows);
res.render('display', {myData:rows })
}
else {
console.log('Error while performing Query.');
res.render('display', { title: 'The index page!'})
}
});
});
The control never comes to the chunk that I wrote, rather it gets into the if loop that says :
if (app.get('env') === 'development')
ALWAYS and throws some error. Front end is a mere form submission. What am I doing wrong here?
Thanks in advance.