I have two separate node.js express servers running on different ports.
on port 5000 is running an Authentication API that handles the register, login, and session verification.
on port 6000 is running a Product API that handles the CRUD operations for the products.
When I create a new product I would like to verify the token found in the request header, so instead of copying over the session verification method from the Authorization API, I imported it, but for some reason, I get this error in the console when starting the app: Error: listen EADDRINUSE: address already in use :::5000
Authorization API exports the method:
export const verifySessionToken = async (sToken: string) => { ... }
Products API imports the Method:
import { verifySessionToken } from '../../../auth/common/verify-session';
If I comment out the import from above, the app runs again.
Is it even possible to import methods from node apps running on different ports?
If it is, what would be the correct way of doing it?
Million thanks!
First off, you import functions from modules. You don't import methods from servers. And, it's perfectly feasible to import the same function for use in two separate servers either in the same nodejs process or in different nodejs processes. The process of importing something from a module has absolutely nothing to do with a server or a port that server is running on. You're just importing a function reference from a file that you can call later.
You do need to make sure that your code is properly modularized so that the process of importing the function doesn't have any unintended side effects such as trying to start another server that you don't want to start. So, perhaps your function isn't properly modularized (put in its own sharable module)?
Is it even possible to import methods from node apps running on different ports? If it is, what would be the correct way of doing it?
Yes. It's very easy if you create your module properly and make sure that it doesn't have any unintended side effects. If you show us the entire module that you're importing from, we can probably help you identify what you are not doing correctly.
FYI, just put this:
export const verifySessionToken = async (sToken: string) => { ... }
in its own file where both places that want to use it can then import it.
I don't think you can run two servers sharing the same files. Why don't you just replicate your function in the other app ?
Related
My question could be flagged as "opinion based" but I am wondering which approach is the best for my application as I am able to do it in both ways.
I am building chat application in which users and conversations are saved in MongoDB. I will have my react application consuming API/APIs. The question is - is it better to have REST API and Socket.io applications running separate? For example:
Have REST API running on port 3005
Have Socket.io running on port 3006
React Application consuming these 2 separately and basically they will not know about each other. My endpoints in REST API endpoints and socket.io will be invoked only in front-end.
On the other hand, I can have my socket.io application and REST API working together in 1 big application. I think it is possible to make it working without problems.
To sum up, at first glance I would take the first approach - more cleaner and easy to maintain. But I would like to hear other opinions or if somebody had a similar project. Usually how the things are made in this kind of projects when you have socket.io and REST API?
I would check the pros and cons for both scenario. For example code and resource reusability is better if you have a single application and you don't have to care about which versions are compatible with each other. On the other hand one error can kill both applications, so from security perspective it is better to have separate applications. I think the decision depends on what pros and cons are important to you.
you can make a separate file for socket.io logic like this:
// socket.mjs file
import { Server } from "socket.io"
let io = new Server()
const socketApi = {
io: io
}
io.on('connection',(socket)=>{
console.log('client connected:', socket.id)
socket.join('modbus-room')
socket.on('app-server', data=>{
console.log('**************')
console.log(data)
io.to('modbus-room').emit('modbus-client', data)
})
socket.on('disconnect',(reason)=>{
console.log(reason)
})
})
export default socketApi
and add it to your project like this:
// index.js or main file
//...
import socketApi from "../socket.mjs";
//...
//
/**
* Create HTTP server.
*/
const server = http.createServer(app);
socketApi.io.attach(server);
//
I'm trying to use npm pg with pg-pool in my Next.js application.
I'm new to pooling connections but I gathered that I need to establish a pool connection whenever my Next.js server is initialized and I need to pass that connection as a module around my application.
From pg-pool docs:
a note on instances
The pool should be a long-lived object in your application. Generally you'll want to instantiate one pool when your app starts up and use the same instance of the pool throughout the lifetime of your application. If you are frequently creating a new pool within your code you likely don't have your pool initialization code in the correct place.
So, I created file my-app/lib/db.js to initialize my connection and hopefully pass that around my application whenever I need to run a query.
However, when I attempt to import { Pool } from 'pg'; I get an error:
Module not found: Can't resolve 'fs'
I found this question with the understanding now that..
You can't use Node.js libraries that use fs in Next.js Middleware. Try using a client-side library instead.
So, my question is, how can I initiate a postgres-pool connection on a Next.js server node and route all queries through it? Do I need use a different package? Really not sure where to place this in the Next.js architecture.
If you only import it with "import { Pool } from 'pg';" in a component (not an API route) without calling the "Pool" object inside "getServerSideProps" or "getStaticProps" it will fail because Nextjs will include the "Pool" object in the client bundle and this way you will try to import a server-side module "fs" in the browser.
If you call the "Pool" in "getServerSideProps" or "getStaticProps" Nextjs will know NOT to include the "Pool" object in the client bundle and the problem will be solved.
There is a very good explanation here: https://maikelveen.com/blog/how-to-solve-module-not-found-cant-resolve-fs-in-nextjs
In my web application (I'm using expressJS), there are many services (such as mongoDB connection, MQTT connection, etc.) that need to be executed once the whole application is executed (using npm start command). Therefore, I can make use of these services in my entire application. For example, I want to use my MQTT connection in different files.
My idea is to export the MQTT connection, MongoDB connection, etc. in addition to the app this way:
//app.js
module.exports = {
app: app,
mqttConnection: myMQTTConnection,
db: myMongoDB
};
However, we know that this approach doesn't work (I tested it and got an error saying: TypeError: app.set is not a function).
How can I export other things in addition to app from app.js file?
If my approach is not possible, what other approaches can I use? (considering the fact that many services (such as connecting to a server, etc.) are asynchronous)
I've recently started to work with node.js and I have to build an architecture that should use multiple express.js services. Some of these services will have to be located on one server, anothers - on other server machines. I want to build a base service (like API Gateway), but I don't know what the proper way to communicate between this Gateway and microservices, or between two microservices.
Currently I'm working with a solution based on this:
# inside Gateway server I call another service:
http.get('http://127.0.0.1:5001/users', (service_res) ->
data = ''
service_res.on 'data', (chunk) ->
data += chunk
service_res.on 'end', ->
# some logic on data
).end()
I have a strong feeling that this approach is not right. What the proper way to build communication logic between API Gateway and microservices?
The logic you have is not incorrect but what would probably be better is to build a layer of abstraction on top of making requests to an another service eg. the API gateway to another microservice. Lets just call that microservice B for this instance (API gateway to make a request to B).
B in this case should provide its own client on how another service should interact with it, whether its through HTTP or WebSockets, the protocol is up to B because B understands how one should communicate with it. The argument for the client and the service being implemented together is that these two components should have a higher level of cohesion since technically they are bound by a contract eg. if a requests needs to be made to a service, it needs to adhere to the contract that the service requires.
In simple pseudocode with Express:
// implemented elsewhere, ideally next to the service that it communicates with
function BServiceClient() {
// ...
}
// the API gateway's calling code
app.get('...', function(request, response, next) {
// create an instance of the service client
var bServiceClient = new BServiceClient();
// retrieving the users from an abstracted endpoint
bServiceClient.GetUsers();
// do some processing and then render a response or call next
});
In order for it to be more testable, you might have to write your own wrapper around the app to do the proper dependency injection for injecting the client to make the routes more testable. Otherwise, you might be able to create another function that can inject the client and create the client at the handler level that calls the newly created function. The newly created function could then be tested. However, I prefer the former approach of using the wrapper. Hope this helps!
What i would do is,
Create separate modules for each microservice. Depending on what microservice you want to run, just have a route for that in express.
Inject the modules you want into an instance of express().
Example + shameless plug - https://github.com/swarajgiri/express-bootstrap/blob/master/core/index.js
Disclaimer - The above solution is a highly opinionated way of solving your problem.
I'm new to using Derby.js, and have scaffolded out a project using the yeoman generator-derby package. I thought everything was going fine, but I can't figure out what I'm doing wrong here.
A breakdown:
I have an 'app/dbWp.js' controller that exports several functions, and requires the modules 'mysql', 'async', and 'needle'
In my app/index.js, I import this file and use it like so:
app.proto.submitWp = function() {
dbWp.createUser(this.model);
};
I call this function from the view/index.jade like so:
button.btn.btn-primary(type="button", on-click="submitWp()")
In the browser, I get numerous console.error message complaining about the 'fs' module not being defined. After much googling, I discover that it's due to Browserify ignoring the 'fs' module, which subsequently causes problems with modules 'mysql' and 'needle'. But that implies this code is being executed in the browser?
So my question is: why is this trying to call the function on the client side? Obviously if it executes on the server side, as I thought it was going to, there wouldn't be a problem requiring these modules.
How can I execute this function on the server? Had this working fine with express + socket.io before, but wanted to change frameworks and give Derby.js a shot.
I'm clearly misunderstanding something about how Derby.js is supposed to work; any help would be appreciated. Thanks!
I know this is like 4 months later, but being new to DerbyJs too, I thought I could try and help.
I personally with standard html code have the equivalent working.
<button on-click="editContact(#contact.id)">Edit Contact</button>
This indeed runs code on the server. Can you try writing your code in standard HTML, or perhaps better yet, see if you can do a console.log on the server method to see if it even is getting there?
Perhaps the best would be to call an empty function on the server with a console log and check both the browser console and the server console.