Server side or Clint side API call? - javascript

If you're working with React.js, what is the best way to make an API call? For example, if I'm trying to get some book data from google books API should I do this on the client side with React.js or on the server side. Why would it be better to do it on one side vs the other? Thanks.

You can do something like this.
const express = require('express');
const app = express();
const path = require('path');
const fs = require('fs');
const proxy = require('http-proxy-middleware');
app.use(
'/api',
proxy({
target: 'http://api.books.com',
changeOrigin: true,
ws: true,
pathRewrite: { '^/api': '' },
})
);
const index = fs.readFileSync(path.resolve('./build', 'index.html'), { encoding: 'utf-8' });
app.get('*', (req, res) => {
res.contentType('text/html').send(index);
});
const server = app.listen(3000, function() {
const host = server.address().address;
const port = server.address().port;
console.log('The server is running at http://%s:%s/', host, port);
});
And call like this (throw proxy), to not have problems with CORS or to replace server after.
fetch('/api/get-books')

Related

Nextjs custom server.js proxy to api

im trying to proxy to backend api which is running on port 5000. i have created a custom server.js file for my nextjs app. but its not working im getting 'Application error: a client-side exception has occurred (see the browser console for more information)' error. and when i check the console, indeed the data is not fetching from backend.
server.js:
const express = require('express')
const next = require('next')
const { createProxyMiddleware } = require("http-proxy-middleware")
const port = 3000
const app = next({})
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.use('/api/products', createProxyMiddleware({ target:
'http://198.51.100.255:5000', changeOrigin: true }))
server.all('*', (req, res) => {
return handle(req, res)
})
server.listen(port, () => {
console.log(`app running on port ${port}`)
})
})

Is this Express + HTTPS spdy + socket.io server correctly initialized?

I've been working on a project a while and I'm not sure that my https is correctly mounted since I'm not fully aware of the sentences that are invoked in the code, could someone bring some light into this?
const express = require('express')
const spdy = require('spdy')
const cors = require('cors')
const fs = require('fs')
const app = express()
const serverCertificates = {
key: fs.readFileSync(__dirname + '/cfg/cert/localhost-private.pem'),
cert: fs.readFileSync(__dirname + '/cfg/cert/localhost-cert.pem')
}
const corsOptions = {
cors: {
origin: "https://localhost:3200",
transports: ['websocket'],
upgrade: false
}
}
Up to here is just require, mounting express on app and declaring some server options
After the classic app.use statements comes the trouble, I need to run HTTPS and Socket.io in the same server, and the only role that express is doing is serving statics directories
app.use(express.json())
app.use(cors())
app.use('/', express.static('./public'))
app.get('/favico.ico', (req, res) => res.sendFile(__dirname + '/public/favico.ico'))
let server = spdy.createServer(serverCertificates, app)
let io = app.io = require('socket.io')(server, corsOptions)
io.attach(server)
server.listen(3200, (error) => {
if (error) {
return process.exit(1)
} else {
console.log('Escuchando en *:' + PORT)
}
})
server.on('error', err => console.log(err))
Now I'm not using express routing as an API because the communication with client is done by Express.IO but eventually the project must contain a database that would be handled by express.
The question is "am I doing the right things here? is there a better way of mounting this type of server?"
Thanks in advance

Respond to client after receiving client to server POST request (Node.JS)

I have been attempting to respond to a client-side request with Node.JS. I have discovered Node JS - call function on server from client javascript, which seems to explain what I want, except that I can't seem to translate it to my program.
Here is the request via POST in index.html:
$.post("/", {data: 'hi'}, function(result){
$("body").html(result);
});
what I was hoping it would do would be write the result of the call, from my server.js (Node):
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/*', (req, res) => res.sendFile('static/index.html', { root: BUILDPATH }));
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
try this code:
const express = require('express');
const path = require('path');
const http = require('http');
const fs = require('fs');
function handler(data, app){
if(req.method == "POST"){
app.setHeader('Content-Type', 'text/html');
app.writeHead(200);
app.end(data);
}
}
const BUILDPATH = path.join(__dirname);
const { PORT = 3000 } = process.env;
const app = express();
app.set('port', PORT);
app.use(express.static(BUILDPATH));
app.get('/', (req, res) => {
res
// best practice is to always return an status code
.status(200)
// just return an json object
.json({"msg": "ok, it all works just fine"})
});
const httpServer = http.createServer(app);
httpServer.listen(PORT);
console.info(`🚀 Client Running on: http://localhost:${PORT}`);
The issue is, is that the only route your Node server listens to is the one you define with /*. As you can see, that route returns your index.html file to the client. You did not specify a route that listens for a request that comes from the client.
To solve the issue, you will have to define a route that listens on a specific route for the request you are trying to make from your client.
I see you are using ExpressJS. here is the documentation on writing routes.

Implementing socket.io in mongoDB and Angular it is throwing errors Cannot GET /socket.io/

I am developing an angular application which I need to use notifications for example.
I have a user which can add friends and then I can sent a friend request as in facebook and then the other user will be notificate in realtime for example You have one new notification, this user wants to be friends.
If anyone has better idea than socket.io I am free to listen and to learn
The problem it is that I get everytime Cannot GET /socket.io/
Request URL: http://localhost:4200/socket.io/?EIO=3&transport=polling&t=NVvJf99
Request Method: GET
Status Code: 404 Not Found
Remote Address: 127.0.0.1:4200
I can show the list who sent me friend but I need everytime to reload page to see new requests.
I am using socket.io in both frameworks.
Angular I have installed with npm and the same in the mongoDB.
My server.js that is what I use for the requests and responses in frontend.
Server.js
const express = require('express');
const mongoose = require('mongoose');
const http = require('http');
const cors = require('cors');
const routes = require('./src/app/routes/routes');
const path = require('path');
const socketIO = require('socket.io');
const app = express();
const server = http.Server(app);
mongoose.connect('mongodb+srv://vip:admin#test-name-sn4qu.mongodb.net/test?retryWrites=true&w=majority'
, {
useNewUrlParser: true,
useUnifiedTopology: true,
useFindAndModify: false
});
app.use(cors());
const io = socketIO(server);
app.set(io);
app.use(express.json({limit: '50mb'}));
app.use(express.urlencoded({limit: '50mb', extended: true}));
app.use('/images', express.static(path.resolve(process.cwd(), '../images')));
app.use(routes);
mongoose.set('useNewUrlParser', true);
mongoose.set('useFindAndModify', false);
mongoose.set('useCreateIndex', true);
app.get("/", (req, res) => {
res.json({ message: "Welcome to application." });
});
const PORT = process.env.PORT || 5000;
server.listen(PORT);
And then in the friendController I use something like this.
function createNewRequest(req, res, next) {
const io = req.app.get('io');
friendService.createNewRequest(req.body)
.then(res.status(200).json({ message: 'Friend added successfully' }),
io.emit('newTaskAdded'))
.catch(err => next(err));
}
And then in the frontend I do have something like this.
And I am having an error which says
Cannot find namespace 'SocketIOClient'. private socket:SocketIOClient.Socket;
import * as io from "socket.io-client";
constructor() {
this.socket = io();
}
ngOnInit(): void {
this.LoadRequestingFriends();
this.socket.on('newTaskAdded', () => {
this.LoadRequestingFriends();
})
}

Enabling HTTPS on an express server

I'm trying to configure my express server to use HTTPS but I am running into some issues. I followed the documentation to setup my HTTPS server but I am still encountering some errors.
Here's my app.js
var express = require('express');
var app = express();
var server = require('https').createServer(options, app);
var io = require('socket.io')(server);
var port = process.env.PORT || 3000;
var fs = require('fs');
var options = {
key: fs.readFileSync('/test/key.pem'),
cert: fs.readFileSync('/test/cert.pem')
};
server.listen(port, function () {
console.log('Server listening at port %d', port);
});
When starting my server I encounter
https.js:32
if (process.features.tls_npn && !opts.NPNProtocols) {
^
TypeError: Cannot read property 'NPNProtocols' of undefined
at new Server (https.js:32:40)
at Object.exports.createServer (https.js:56:10)
So, I tried to define NPNProtocols within options, but that did not work. Anyone have any pointers here?
Thank you.
try this once, i think you should have certificate in .crt format. and you will require tls module.
var sslOptions = {
key: fs.readFileSync('public/server.key'),
cert: fs.readFileSync('public/server.crt')
};
tls.createServer(sslOptions, function (cleartextStream) {
var cleartextRequest = net.connect({
port: port,
host: serverStr
}, function () {
cleartextStream.pipe(cleartextRequest);
cleartextRequest.pipe(cleartextStream);
});
}).listen(443);
port is you http port . and sercerStr is you server address.
IMO, the issue is not with the extension of the keys, rather the ssl configuration used. Use https node module with correct ssl options for ca, cert, and key to enable https with express.
// server/index.js
const express = require('express');
const fse = require('fs-extra');
const helmet = require('helmet');
const https = require('https');
const path = require('path');
// path to cert files
const paths = {
certFile: '/path/to/cert.pem',
chainFile: '/path/to/fullchain.pem',
privateFile: '/path/to/privkey.pem',
};
/* Express implementation (ignore) */
const app = express();
app.use(helmet());
app.use(express.static(path.join(__dirname, '..')));
app.get('/', (request, response) => {
response.sendFile(path.join('index.html'));
});
// setup https
const setupHttps = () => {
const promises = [
fse.readFile(paths.chainFile),
fse.readFile(paths.privateFile),
fse.readFile(paths.certFile),
];
return Promise
.all(promises)
.then(data => {
const [ chainData, privateData, certData ] = data;
const options = {
ca: chainData.toString('utf-8'),
cert: certData.toString('utf-8'),
key: privateData.toString('utf-8'),
};
return https.createServer(
options,
app
).listen(443);
})
.catch(err => console.log(err));
};
return setupHttps();
EDIT: I used helmetjs for better security with http headers.

Categories