How to serve index.html file with Apollo Server? - html

I have this code in index.js:
const PORT = process.env.PORT || 5000;
server.listen(PORT).then({ url }) => {
console.log(`Server running at url: ${url}`);
});
In local development, when I went to localhost:5000 on my browser, I could test with the GraphQL playground.
Now, I just finished deploying with Heroku. When I go to my URL, I see:
GET query missing. I assume this happens because apollo is trying to open the GraphQL playground, but it is blocked in production mode.
How can I tell apollo to serve client/index.html instead?
Note: I tried putting index.html in the root directory as well, but nothing changed.
I saw in a tutorial video that the answer to this question in express is:
app.use(express.static('client'));
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client','index.html'));
});
I don't know how to do this in Apollo.

The standalone Apollo Server cannot be used for serving static files or exposing other endpoints. If you need this functionality, you need to use an HTTP framework like Express, Hapi or Koa and then use the appropriate Apollo Server integration.
Example using Express:
const server = new ApolloServer({ ... });
const app = express();
server.applyMiddleware({ app });
app.listen({ port: 4000 }, () =>
console.log(`🚀 Server ready at http://localhost:4000${server.graphqlPath}`)
);

Related

Connecting to a remote MySQL database from Stackblitz Node.js project

I have a Node.js Stackblitz project that I am trying to connect to a remote MySQL database. It is not possible to have a MySQL database within Stackblitz, hence trying the remote approach. However I get "Error: connect ETIMEDOUT" whenever I attempt a connection. Any help or pointers much appreciated.
I am using the code below. The remote database is accessible with the credentials I am using and returning data when used outside of Stackblitz. Is remote database access not possible with Stackblitz or am I missing something?
const express = require('express');
const mysql = require('mysql2/promise');
const app = express();
const port = 3010;
const path = require('path');
app.use(express.static('static'));
app.get('/', async function (req, res) {
try {
// create connection
const connection = await mysql.createConnection({
host: process.env.DB_HOST,
port: process.env.DB_PORT,
database: process.env.DB_DATABASE,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
});
// query database
const [rows, fields] = await connection.execute('SELECT * FROM `user`');
res.send({
rows,
fields,
});
} catch (err) {
console.log('err:', err);
}
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
For anyone looking for an explanation.
Currently a mysql database cannot reside in StackBlitz. Additionally, neither can it connect to an external mysql database on its own either.
You therefore required a backend API outside of StackBlitz to make the database calls, negating the reason for building the backend on StackBlitz in the first place (IMO). Therefore, the suggested setup currently would be a localhost backend API accessed from a frontend in StackBlitz via an ngrok secure address.
StackBlitz are working on getting basic server requests running in the future. So, watch this space.
I hope this answer helps save others time.

How can I fix this CORS with Socket.io?

I'm having trouble migrating my locally hosted chat application using Socket.io to my live cloud server. I am aware there are solutions out there, however, I cannot find anything that solves my problem.
I am receiving "Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at.... (Reason: CORS request did not succeed)"
'''
const io = require('socket.io')(3000)
io.on('connection', socket => {
socket.on('new-user', name => {
users[socket.id] = name
socket.broadcast.emit('user-connected', name)
})
socket.on('send-chat-message', message => {
socket.broadcast.emit('chat-message', {message: message, name:
users[socket.id]})
})
socket.on('disconnect', () => {
socket.broadcast.emit('user-disconnected', users[socket.id])
delete users[socket.id]
})
})
Above is the server.js file.
const socket = io('<url>:3000')
const messageForm = document.getElementById('send-container')
const messageInput = document.getElementById('message-input')
const messageContainer = document.getElementById('message-container')
This is the script my app is using, the is replaced by mine, it just masked on here.
Things I have tried:
Setting headers using "Header set Access-Control-Allow-Origin" in my Apache & Nginx config
Changing the url on the script
Changing the ports
So far I've no luck, please help me!!
Try
// Allow all origins
io.origins('*');
source

Upload image URL to SFTP server using Cloud Function

I am working on a task that uploads image to SFTP server with Firebase Function. But the image source is not from my local computer but a http URL such as https://image.com/abc.jpg. I am using ssh2-sftp-client npm package. Currently I am using my mac both for client and server and it is working fine when I am accessing local file(/Users/shared/abc.jpeg) and uploading it to local server(/Uesrs/shared/sftp-server/abc.jpeg). But when I tried to have access to https://image.com/abc.jpg. and upload it to local server I got the error that says "ENOENT: no such file or directory/ ...". And below is my code
const functions = require('firebase-functions');
let Client = require('ssh2-sftp-client');
exports.sftpTest = functions.https.onRequest((request, response) => {
let sftp = new Client();
const config = {
host: '192.***.***.***',
port: '22',
username: '****',
password: '****'
}
let localFile = 'https://images.unsplash.com/photo-1487260211189-670c54da558d?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=934&q=80';
let remoteFile = '/Users/Shared/unsplash.JPG';
sftp.connect(config)
.then(() => {
sftp.fastPut(localFile, remoteFile);
})
.catch(err => {
console.error(err.message);
});
});
My first time to have access to sftp server and anyone's advice will be much appreciated.
The method you are using from this library does not support usage in the way you are trying to set it up. the method fastPut usually is to upload local files to a remote server, I think you should use the fastGet method in order to download files from a remote server, however, please note that there are no notes that indicate that you can use these methods with the URL in the way you are trying to achieve.

Express bodyParser not working properly

I have a problem with bodyparser that I can't figure out.
A few weeks ago I created a REST API with Express and used bodyParser to read JSON data from the client. Everything worked well but this morning I tried to launch my application and all my req.body.data are undefined, in fact the body is equal to {}.
Here is my configuration :
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
And then I configure my routes. I've seen that you must declare that in this order, ie bodyParser before your route and this is what I do. I thought that it was a version problem but after a few upgrades the problem is still present.
I use HttpRequester to simulate the client. Everything worked fine till this morning.
Example of data sent:
{
"username": "david",
"password": "bowie",
"email": "db#sfr.fr"
}
Then there is this code for responding:
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(logger('dev'));
app.use(expressValidator());
app.use(cookieParser());
app.use('/users', users);
then in users I just create a user:
// Creation of a user.
router.post('/create', function(req, res) {
// We check current mistakes like username or password empty.
if (!userhelper.checkCreateUserRequest(req, res)) {
return;
}
// Save the user in BDD
}
In the checkCreateUserRequest I do this:
if (req.body.username == null || req.body.password == null || req.body.email == null) {
res.status(400).json({message: "malformed request", code: 1});
return false;
}
I do other things like check if username is empty for example but I don't think it's important to paste it.
Thanks you for your responses and sorry for my bad english...
You could set the correct HTTP header if you use JSON request.
Content-Type: application/json
For anyone using Express v4.16+, body-parser is no longer needed as a third-party dependency. Express has its own built-in body parser that can be used like so:
Server.js
const express = require('express')
const app = express()
app.use(express.json())
app.use(express.urlencoded({extended: false}))
In my case, initializing my app this way still resulted in an empty object (i.e. {}) being logged for req.body. I found the following packages to also be helpful
npm i cors
npm i path
And those can be used by including the following in server.js (or your respective file)
app.use(cors())
app.use(express.static(path.join(__dirname, 'public')))
You may also find it necessary to include the 'Content-Type': 'application-json' header in your fetch request from your client.

while using MySql, express, angular, nodejs, will the ports be different for express and node

While looking into express + node + mysql, tutorials suggest to start express server by using node server.js (here server.js contains logic to connect to mysql db), which calls upon app.listen() and angular+node tutorials start node server using npm start.
Are they different and I have to start both?
In case, yes, do I need to use diff ports?
In case, no, how to call upon mysql db? Please give some reference or elaborate.
server.js is as follows:
var express = require("express");
var mysql = require("mysql");
var app = express();
var connection = mysql.createConnection({
host : "localhost",
user : "userid",
password : "password",
database : "sakila"
});
connection.connect(function(error){
if(error) {
console.log("Problem with MySQL"+error);
} else {
console.log("Connected with Database");
}
});
app.use(express.static(__dirname + '/bower_components/angular'));
app.get('/app/#/actors_load',function(req,res){
connection.query("SELECT * from actor",function(err,rows){
if(err) {
console.log("Problem with MySQL"+err);
} else {
res.end(JSON.stringify(rows));
}
});
});
app.listen(8000,function(){
console.log("It's Started on PORT 8000");
});
My phonecatapp has following routers:
phonecatApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider.
when('/phones', {
templateUrl: 'partials/phone-list.html',
controller: 'PhoneListCtrl'
}).
when('/phones/:phoneId', {
templateUrl: 'partials/phone-detail.html',
controller: 'PhoneDetailCtrl'
}).
when('/actors_load', {
templateUrl: 'partials/actors.html',
controller: 'ActorsCtrl'
}).
otherwise({
redirectTo: '/phones'
});
}]);
and controller looks like this:
phonecatControllers.controller('ActorsCtrl',function($scope, $http, $interval){
load_names();
console.log("ActorsCtrl");
/*
$interval(function(){
load_names();
},300);
*/
function load_names(){
$http.get('http://localhost:8000/actors_load').success(function(data){
console.log("kdfhg"+data);
$scope.actors=data;
});
};
});
the partials of html has a link to populate the db data as:
<div>actors</div>
npm install doesn't start a server. It is a command to install packages.
In this particular example the createServer function will accept connection on port 8000. it's taken from node.js docs.
https.createServer(options, function (req, res) {
res.writeHead(200);
res.end("hello world\n");
}).listen(8000);
As soon as the above code is executed the server is ON. express is a framework for node.js. express creates server on the top of node.js so the express configuration (along with port number) will be executed by node.js. Specified port of express server will run an instance of node.js server, that's the end of the story
To connect to mysql you can use one of the mysql packages for node e.g.:
var mysql = require('mysql');
var connection = mysql.createConnection({
host : 'localhost',
user : '< MySQL username >',
password : '< MySQL password >',
database : '<your database name>'
});
connection.connect();
In above case you are using localhost as a adress of your database.
You can find plethora of mysql packages on npm site: https://www.npmjs.com/search?q=mysql
You may also use mysql.createClient for costumised connection:
var client = mysql.createClient({
user: '??',
password: '??',
port: 8889
});
Note: remember to require your packages otherwise they just simply won't work.
After doing trial and error, I found that srever.js is on server side, angular part of the project is on client side. from angular part, only way to recieve data is using REST API. This role of providing REST API will be facilitated by server.js and hence shall be run on diff port. It means I had to call npm start as well as node server.js. Then I was facing CORS issue, which I resolved by providing
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header ("Access-Control-Allow-Credentials", true);
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header('Access-Control-Allow-Methods', 'POST, GET, PUT, DELETE, OPTIONS');
next();
});
in server.js. NOte that to see the effect of this code, you need to start the two servers. This was really a pain point for me. I spent whole day trying various combinations in various places to resolve CORS issue. It seemed not to be working. For some reasons, I stopped the servers and restarted, it was working. After few trials, I realized that even after removing above code, it was working. So, I stopped servers again and this time it was not working, that is how I realized it.
One more thing that I was mingling the two thinking them as one project having client and server side. Any newbie, please understand that client side accesses server side as REST API, so develop them as separate module/project. Do not develop as single module/project.