JavaScript HTTP requests fail on amazon ec2 instance - node.js

I am running a node express server on Amazon ec2 instance. I can connect to the website on my local machine from within the browser, and can view pages with only local files, but when accessing a page that makes an external HTTP request, it just hangs. I figure it has something to do with my inbound or outbound rules are prohibiting it somehow, but don't know enough about networking to solve it on my own.
These are the functions that are failing behind the scenes:
const axios = require('axios').default;
const freelancer = axios.create({
baseURL: 'https://www.freelancer.com/api/',
headers: {
'freelancer-oauth-v1': process.env.FREELANCER_TOKEN
}
});
/* Get User By Id */
async function getUserById(user_id) {
const result = await freelancer.get(`/users/0.1/users/${user_id}/`)
return result.data.result;
}
const GitHub = require('github-api');
const gh = new GitHub({
username: process.env.GHUSER,
password: process.env.GHPASS
});
const getRepos = async function () {
const user = await gh.getUser();
return new Promise(async (resolve, reject) => {
await user.listStarredRepos(function (err, repos) {
if (err) reject(err);
resolve(repos);
});
});
}
My routers look like this:
var express = require('express');
var router = express.Router();
const freelancer = require('../service/Freelancer');
/* GET home page. */
router.get('/', async (req, res, next) => {
const reviews = await freelancer.getMyReviews();
const self = await freelancer.getSelfData();
res.render('contact', {
header: 'Check out all my reviews!',
lead: '',
paragraphtext: 'Your review could be next on this list!',
reviews,
self
});
});

Based on the comments.
The issue was caused by using HTTP for www.github.com. The solution was to use HTTPS.

Related

Get external api with axios and req body to url for search and ajax NodeJS express

I use node.js expess with MVC pattern and use axios for get json url. The all logic request api i wrote it in Controller , I try to create some get api with axios like this.
this my chartController.js , it's some logic for get json from url with req.body.symbol (it's just symbol of stock from user submitted input form , I want to get that symbol to my axios get url in code below in const chartChartPage )
'use strict';
const axios = require('axios');
const request = require('request');
/* For Get my Api Token Data */
const dataTokens = require('../config/apitokens');
const chartChartPage = async (req,res) => {
try {
const symbol = req.body.symbol;
const url = `https://${dataTokens.sandbox}.iexapis.com/stable/stock/${symbol}/chart/1m?token=${dataTokens.tokens}`;
const fetchData = await axios.get(url);
res.status(200).json(fetchData.data);
}
catch (error){
res.status(400).send(error.message);
}
}
module.exports = {
chartPage,
chartChartPage
}
Now, i have to added some routes in my chart.js
i think i should add router.post('/', chartChartPage) for get that symbol in input when user submitted Maybe i'm wrong.
var express = require('express');
var router = express.Router();
var {chartPage , chartChartPage} = require('../controllers/chartControllers');
router.get('/', chartPage);
router.post('/', chartChartPage);
module.exports = router;
and in my chartChartPage.js (it's just js file for my template)
and use ajax to get that data from url above (with chartChartPage) to get data for build chart stock
and try to console.log that data but that's not work in console
$(function(){
chartChartPage();
});
const chartChartPage = async () => {
await $.ajax({
url: '/chart',
type: 'POST',
dataType: 'json',
success: (response) => {
if (response != null) {
console.log(response);
}
},
error: (err) => {
console.log(err);
}
});
}
and when i submitted form i got that all json data in my page, but i want when submitted it's render to same page and work in console.log in ajax get url above. How can i fix.?
enter image description here

My socket io is working but when I add new data, it's not real time, ReactJS, Express, Mongoose

I really can't find an answer in the internet so I want to ask here. My socket io works, cause I can display data from the backend on the first load of my page, but when I add new data, I still have to refresh my page so that my frontend would be updated, it's not yet real time. I use express router/rest api to add new data to the database. And I also want to ask, why I have to add { transports: ['websocket', 'polling', 'flashsocket'] } on my frontend? I see others do it without the transports thing, but when I do CORS error occurs. Thank you!
This is my React JS code on file App.js. (I didn't include the const App = () => {....}, but the state and useEffect is inside of the const App)
import io from "socket.io-client";
const socket = io("http://localhost:3001", { transports: ['websocket', 'polling', 'flashsocket'] });
const [rooms,setRooms] = useState([]);
useEffect(() => {
socket.emit("rooms");
socket.on("rooms", rooms=> {
setRooms(rooms);
})
},[])
This is my app.js (node/express)
const http = require('http').createServer(app);
const io = require("socket.io")(http);
const viewRooms = require("./events/rooms");
const onConnection = (socket) => {
viewRooms(io,socket);
}
io.on("connection",onConnection);
This is rooms.js file on my events folder
const Rooms= require("./../models/Rooms");
module.exports = (io,socket) => {
const view = () => {
Rooms.find()
.then(rooms=> {
io.emit("rooms",rooms);
})
}
socket.on("rooms",view);
}
The submit function I use to add data to the database
const submitHandle = (e) => {
e.preventDefault();
const formData = new FormData();
formData.append('name',addForm.name);
addForm.description.forEach((val,key) => {
formData.append("article[" + key + "]" + "[" + Object.keys(val) + "]",val.paragraph);
})
addForm.images.forEach(val => {
formData.append("image",val);
})
formData.append('date',addForm.date);
let token = "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjYwNDU2ZmNhNTI3ZTdhMGEwODY0NjVjNSIsImlhdCI6MTYxODI3NzIyNX0.w6eBHJC72xo-NRPtzJ3gKu_hIY70eCk_-K3-pkO4bAc";
fetch("http://localhost:3001/rooms/upload",{
method : "POST",
body : formData,
headers : {
"Authorization" : token
}
})
.then(data => data.json())
.then(rooms=> {
console.log(rooms);
alert(rooms.message);
})
}
And this is my code on my express route (post)
const router = require("express").Router();
const Rooms = require("./../models/Rooms ");
const auth = require("./../authorization");
const passport = require("passport");
const multer = require("multer");
require("./../passport-setup");
// IMAGE DESTINATION AND FILENAME
const storage = multer.diskStorage({
destination : (req,file,cb) => {
cb(null,"public/images")
},
filename : (req,file,cb) => {
cb(null, Date.now() + "-" + file.originalname)
}
})
// upload
const upload = multer({ storage : storage});
// upload rooms
router.post("/upload",upload.array("image",10),passport.authenticate("jwt",{session : false}),auth,(req,res,next) => {
let allDescription = req.body.description;
req.body.images = req.files.map(file => {
return(
{
roomName : req.body.name,
image : "/public/" + file.filename
}
)
})
Rooms .create(req.body)
.then(rooms=> {
res.send({
message : "Rooms uploaded!",
success : true,
rooms
})
})
.catch(next);
})
For the first part of your question, we'd have to see a lot more logging info to now exactly what is going on. It seems possible that your client-side socket.emit("news"); is perhaps happening too early before your socket.io connection is fully established and perhaps before the server is ready for the incoming request. You can fully log every single socket.io event and probably determine what's going on.
And I also want to ask, why I have to add { transports: ['websocket', 'polling', 'flashsocket'] } on my frontend?
If you don't list websocket as the first transport, then socket.io starts with a few http polling requests and those http requests are subject to CORS. The webSocket transport is not subject to CORs, so if you force it to use that first, then no CORs. FYI, the http polling that socket.io uses is only really there to detect situations where the webSocket transport is not supported or is blocked. If you aren't concerned about that, then you can really just do this in the front-end:
{ transports: ['websocket'] }
Or, you could remove the transports option completely from the client and then implement support for CORs on your server so that the CORs polling request will be allowed.

POST http://localhost:3000/login/aa/aa 404 (Not Found)

I have an angular app and a nodejs backend server. I want to get data from my backend but when I try to connect to it with Angular HTTPClient, it says: POST http://localhost:3000/login/aa/aa 404 (Not Found).However, when I put the link manually into the browser, it works perfectly fine. Here is some code:
service.ts
addUser(user: IUser): Observable<IUser> {
return this.httpClient.post<IUser>(`http://localhost:3000/login/${user.email}/${user.passwort}`, user, {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
})
.pipe(catchError(this.handleError));
}
index.js
var mysql = require('mysql');
var express = require('express');
var app = express();
const port = process.env.PORT || 3000;
[...]
app.get('/login/:email/:pw',function(req,res) {
res.setHeader('Content-Type', 'application/json');
var passwort = new Passwort(''+req.params.pw);
passwort.comparePasswort();
con.query("SELECT u.Email, u.Hash FROM User u WHERE u.Email LIKE "+ "'" + req.params.email+ "'", function(err, result ){
if(err) throw err;
console.log(result)
res.send("test")
})
});
Thanks for every answer and for your time!
Your route in your backend is set as a get request and not a post request.
You should either convert your request to a get in your service with this.httpClient.get... or convert to a post request in your backend with app.post.
The reason it works in your browser is that the browser performs a GET request when acessing something using the address bar.
In backed you declared a get method and from frontend you are calling post. your code in service should be :-
addUser(user: IUser): Observable<IUser> {
return this.httpClient.get<IUser>(`http://localhost:3000/login/${user.email}/${user.passwort}`, {
headers: new HttpHeaders({
'Content-Type': 'application/json'
})
})
.pipe(catchError(this.handleError));
}
before using /:email you need to subscribe this particular element
const mongoose = require("mongoose");
const User = mongoose.model("User");
const userParams = (req, res, next, email) => {
User.findOne({email:email})
.then((user)=> {
if (!user) {
return res.sendStatus(404);
}
req.user = user;
return next();
})
.catch(next);
};
module.exports = userParams;
then use that in express router by typing
router.param("email", userParams);
this way your router will get to know what the params you are trying to send
In your index.js file, you are creating a handler for a GET request (which is the default request sent by your browser while accessing your webpage)
But in your service.ts file you are trying to send a post request to the server which is not handled, so the simple solution would be to replace the line
return this.httpClient.post<IUser> `http://localhost:3000/login/${user.email}/${user.passwort}`, user, {
with:
return this.httpClient.get<IUser> `http://localhost:3000/login/${user.email}/${user.passwort}`, user, {
For more info you can read this: https://angular.io/guide/http

Adding a new js file to my lambda function using Serverless

I'm trying to create an API on AWS Lambda, and using Serverless framework for deployment.
I'm a complete noob at it, so I'm not sure I'm doing the right thing. So here's the old favorite, hello world (index.js):
const serverless = require('serverless-http');
const express = require('express');
const app = express();
const Promise = require('promise');
app.get('/', function (req, res) {
res.send('Hello World!')
})
That works fine as is. But when I add the following:
const serverless = require('serverless-http');
const express = require('express')
const app = express()
const Register = require('./controller/registryController');
app.get('/', function (req, res) {
res.send('Hello World!')
})
app.get('/createUserName', function (req, res) {
var prom = Register.createUser();
prom.then((message) => {
res.status(201).json(message);
})
.catch((message) => {
res.status(400).json(message);
});
})
module.exports.handler = serverless(app);
I get:
"Cannot find module './controller/registryController'"
Which is strange, cause the file is right there, when I look in lambda. Here's its contents:
const dbConnMysql = require('./dbMngrMysql');
var methods = {
createUser: function() {
return new Promise((resolve, reject) => {
let connection = dbConnMysql.createConnection();
dbConnMysql.startConnection(connection)
.then((fulfilled) => {
let table = 'userNamePool';
return dbConnMysql.selectFrom(connection, table, null);
})
.then((fulfilled) => {
return dbConnMysql.closeConnection(connection).then(function() {
let result = fulfilled;
let response = {
"statusCode": 200,
"headers": {"my_header": "my_value"},
"body": JSON.stringify(result),
"isBase64Encoded": false
};
resolve(response);
});
})
.catch((error) => {
let response = {
"statusCode": 404,
"headers": {"my_header": "my_value"},
"body": JSON.stringify(error),
"isBase64Encoded": false
};
resolve(response);
});
});
}
};
module.exports = methods;
Here's the project structure / directory:
And here's my serverless.yml for good measure:
service: sample-api
provider:
name: aws
runtime: nodejs8.10
stage: dev
region: yapyap
deploymentBucket: yadayada
role: blahblahblah
functions:
app:
handler: index.handler
events:
- http: ANY /
- http: 'ANY {proxy+}'
createUserName:
handler: index.handler
events:
- http: 'GET /createUserName'
What am I doing wrong? Anything I can do to fix this?
There's a typo:
controller instead of controllers. 😊
Sorry, I can't comment because of the reputation restriction.
The problem may be because you haven't created controller folder.
To create it properly
create a folder. Name it controller. Create your registryController.js and put your code in it.
now you will be able to call it as
const Register = require('./controller/registryController');
Also on a side note, if you want to use a serverless architecture, separate your server side and client side code completely. Put your HTML files and client-side scripts in an S3 bucket. put your server-side code in lambda function and connect it with API Gateway. then use a JavaScript function to call the API. Keep server-side calls as less as possible.

Node/Express - How to send get request to check a status code

I am trying to make a URL shortener. I need to take a given URL as a parameter and send a request to that URL just to get the status code. If status = 200, I know I've got a functioning URL, and I'll go ahead and add it to the DB and shorten it.
Problem is, when I make that request, the connection times out.
const express = require('express')
const mongoose = require('mongoose')
const cors = require('cors')
const nofavicon = require('express-no-favicons')
const Shortener = require('./shortener')
const app = express()
app.disable('x-powered-by')
app.use(cors())
app.use(nofavicon())
app.use(express.static(__dirname + '/static'))
mongoose.connect(
process.env.MONGODB_URI || 'mongodb://heroku_x7hcc5zd:39c8i70697o7qrpjn4rd6kslch#ds123371.mlab.com:23371/heroku_x7hcc5zd'
)
app.get('/url/:urlParam(*)', (request, response) => {
let urlParam = request.params.urlParam
let urlRegEx = /[A-Za-z]+[://]+[A-Za-z0-9-_]+\.[A-Za-z0-9-_:%&;?#/.=]+/g
if (urlRegEx.test(urlParam)) {
let shortRandomNum = Math.floor(Math.random() * 10000).toString()
// Shortener here refers to a mongoose Schema in external file
let lmao = new Shortener({
url: urlParam,
urlmao: 'localhost:8080/lol/' + shortRandomNum,
})
// Request header from passed URL to verify legitimacy
// Check statusCode and end request.
app.head(urlParam, (req, res) => {
let end = res.end
// Override standard res.end function with custom function
res.end = () => {
if (res.statusCode == 200) {
lmao.save((error) => {
if (error) {
response.send('Unable to write to collection')
}
})
console.log('pass')
response.json({lmao})
}
}
res.end = end
res.end()
})
} else {
// If passed URL does not satisfy regEx, return error message.
urlParam = 'unfunny url. http(s):// prefix required. check url and retry.'
console.log('invalid url')
response.json({
url: urlParam,
})
}
})
app.listen(process.env.PORT || 8080, () => {
console.log('live connection')
})
Most baffingly, the code shown here worked on Friday. Tested it last night, no dice. Any insight would be greatly, greatly appreciated.
app.head(urlParam, [Function]) doesn't make a request to the url, it defines a new route on your application so that it responds to HEADrequests on that url.
To check if the URL is alive you need to use another package to make requests. One of my favourites is Request. To use it simply replace app.head with request and add the require('request') to the top of your file.

Resources