I'm using MicroMQ to communicate between different services, and for main service it is ok, I received requests and then delegating them through RabbitMQ. I can see this message in queue but my microservice don't receive any messages. This is for main service:
controller:
export const create = async (req, res) => {
await res.delegate('trade');
}
gatewayConfig:
const Gateway = require('micromq/gateway');
const config = require('../configServer');
export const gateway = new Gateway({
microservices: ['platform', 'trade'],
name: 'platform',
rabbit: {
url: "amqp://rihtavqi:AhKDUujmeC5hBUPb0zQb7qh7AgqnR5QG#lion.rmq.cloudamqp.com/rihtavqi"
}
});
export const services = {
trade: 'trade'
};
server.js
app.use(gateway.gateway.middleware());
this what I use in my main service. This is only place where I'm calling gateway...
And this is for microservice:
server.js
const express = require("express");
const gateway = require('./gateway/gatewayRoute');
const app = express();
const server = require("http").createServer(app);
gateway.start().then(() => {
server.listen(constant.config.port, constant.config.host, async () => {
loggingHelper.consoleLog("APP", `Server running on port ${constant.config.port} and on host ${constant.config.host}.....`);
process.on("unhandledRejection", (reason, promise) => {
loggingHelper.consoleLog("APP_ERROR", `Uncaught error in ${String(reason)}`, promise);
});
});
route
const MicroService = require('micromq/src/MicroService');
const loggingHelper = require('../app/helper/loggingHelper');
const orderService = require('../app/service/orderService');
const gateway = new MicroService({
name: 'trade',
rabbit: {
url: "amqp://rihtavqi:AhKDUujmeC5hBUPb0zQb7qh7AgqnR5QG#lion.rmq.cloudamqp.com/rihtavqi"
}
}
);
gateway.post('/create', async (req, res) => {
loggingHelper.consoleInfoLog("TRADE", "/create received.");
res.json(await service.create(req));
});
module.exports = gateway;
Last one don't work. BTW my idea told me that .post() function is
Unresolved function or method post()
I think problem is here. I trying different ways(creating Gateway(micromq/gateway) in microservice, tried to destructure MicroService but this all give me nothing)
all of this was creating by examples but it not works... And I cannot understand why? Somebody knows why?
Not sure about MicroMQ, but you could use the SMF framework to prototype microservices that are connected to RabbitMQ automatically:
https://medium.com/#krawa76/bootstrap-node-js-microservice-stack-4a348db38e51
Related
I’ve been having an issue with deploying my nodejs App on AWS ECS Fargate. Running the app locally on my device with nodemon or building the app and running the build file is successful and I can ping my routes using postman. The issue happens when I deploy this same exact code on AWS; using postman, to do a POST request, I get a 404 error. Please note, I'm running a Node:14 container.
For reference, my nodejs code is structured in a way where there’s a main route.js file containing all routes, then there are specific route files, for example listingRoute.js, contains all the sub-routes then there are controllers (.js files) containing all the logic where I export the function and tie it with the route in the listingRoute.js example.
Here's what my main Route.js file looks like:
const express = require('express');
const error = require('../Middleware/error');
const listingRoute = require('../Routes/listingRoute');
module.exports = function (app) {
//Middleware
app.use(express.json());
app.use(express.urlencoded({ extended: false , limit : '20mb' }));
app.use('/listing', listingRoute);
//The final middleware to be called in case of an unhandled error.
app.use(error);
process.on('uncaughtException', function(err) {
// Handle the error safely
console.log(err)
})
};
My listingRoute file
const express = require("express");
const route = express.Router();
const listingController = require("../Controllers/listingController");
require('dotenv').config();
route.post("/create", listingController.createListing)
route.post("/update", listingController.updateListing)
route.post("/read", listingController.getListing)
route.post("/delete", listingController.deleteListing)
...
...
...
...
...
route.post("/getMostPopular" , listingController.getMostPopular)
route.post("/getByCategory" , listingController.getByCategory)
route.post("/getAllTOS" , TOSController.getTOSByListing)
route.post("/getTOS" , TOSController.getTOSByID)
route.post("/updateTOS" , TOSController.updateTOS)
route.post("/deleteTOS" , TOSController.deleteTOS)
route.post("/createTOS" , TOSController.createTOS)
route.post("/getListingsByIDs" , listingController.getListingsByIDs)
route.post("/cacheImagesNewCDN" , listingController.cacheImagesNewCDN)
module.exports = route;
My listingController file
const listingModel = require('../Models/listingModel');
const moment = require('moment')
const axios = require('axios');
var fs = require('fs');
const createCsvWriter = require('csv-writer').createObjectCsvWriter;
var fs = require('fs');
//tested
const createListing =async (req, res) => {
try {
//some logic here
}
catch (err) {
console.log(err)
return res.status(500).json({ error: err.message });
}
}
const updateListing = async (req, res) => {
try {
//some logic here
}
catch (err) {
return res.status(500).json({ error: err.message });
}
}
module.exports = {
getListing,
updateListing,
deleteListing,
createListing,
listingwithViews,
advertisedListings,
filterListings,
pressedOnBookNow,
cacheImages,
recommendListings,
getCacheMetaData,
addIndoorAmenity,
missingFromFilter,
adjustCreativeStudios,
listingsToCSV,
getAllListing,
getDiscountedListings,
addRevenueToListings,
getMostPopular,
getByCategory,
getListingsByIDs,
cacheImagesNewCDN,
getOwnersPhones
}
All the routes starting from getMostPopular till the end of the list give an error 404 not found although I have done the same procedure to all of them. Any ideas why this is happening? If you feel this isn't enough information to help diagnose, let me know and i'd be happy to provide more details. You're help would be beyond appreciated, thanks!
Im trying to add a proxy in my react native expo app so I can make api requests to my backend without always specifying http://localhost:3001 during development.
Im not sure if its different with react native that in react apps and cannot find any info about it (everything is always about using react and roxy).
I added a proxy and when I make a request from my frontend I always get this type err:
[Unhandled promise rejection: TypeError: Network request failed]
there is nothing wrong with my code, if I type out http://localhost:3001 in my request, everything works fine. What is wrong with my proxy?
app/client/src/setupProxy.js:
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
["/api/*",],
/* '/api',*/
createProxyMiddleware({
target: 'http://localhost:3001',
changeOrigin: true,
})
);
};
app/client/components/search.js
...
const callApi = async () => {
console.log("calling the test")
const response = await fetch('http://localhost:3001/api/hello');
//that without proxy would work
const response = await fetch('/api/hello');
const body = await response.json();
if (response.status !== 200) throw Error(body.message);
console.log("body", body)
return body;
};
...
<Button title="test" onPress={callApi}>press test</Button>
...
my serverside code:
app/server/index.js
const express = require('express');
const router = express.Router();
module.exports = app => {
app.use(router.get('/api/hello', (req, res) => {
console.log("incoming req success")
res.send({ express: 'Hello From Express' });
}))
};
I have the following API /api/v1/download/:id
Usage: http://localhost:3000/api/v1/download/client_app.zip
Implementation:
const express = require("express");
const axios = require("axios");
const { InternalServerError } = require("common-lib");
const router = express.Router();
router.get("/api/v1/download/:id",
async (req, res, next) => {
const { id } = req.params;
try {
const response = await axios.get(
`${process.env.DOWNLOAD_URL}/artifacts/client_app/${id}`, {
auth: {
username: process.env.USERNAME,
password: process.env.PASSWORD
},
responseType: "stream"
});
response.data.pipe(res);
} catch (error) {
return next(new InternalServerError(error.message));
}
});
module.exports = {
downloadByIdRouter: router
}
A user will use the /api/v1/download/:id to download the .zip file from another remote server, the actual credentials and remote URL are hidden from the end-user.
The API is working as expected and I am able to download the file into my system.
The question is how to write the test for this particular streaming scenario in Jest.
describe("download by id test", () => {
test("downloads the app, if requested properly", () => {
// to do
}, )
});
I checked this reference https://dev.to/cdanielsen/testing-streams-a-primer-3n6e. However, I am not exactly getting the approach.
I need guidance in writing the test for this particular scenario, comparatively new to Jest.
Route import
const express = require("express");
// Import routes
const { downloadByIdRouter } = require("./routes/download-byid");
const app = express();
// Use routes
app.use(downloadByIdRouter);
module.exports = {
app
}
Then I import app in the test file and using the supertest library I make the API calls
download.test.js
const request = require("supertest");
const { app } = require("../../app");
describe("download by id test", () => {
test.todo("starts the app download, if requested properly")
});
Thanks
I have a node.js server application that uses express and apollo-server-express to server my application. I want to serve my react client using a catch-all routing method, however, I still want to expose the /graphql endpoint. How can I do this so that /graphql doesn't get caught in the rest of my routing? Thanks.
import express from 'express';
const app = express();
app.get('/graphql', (request, response) => {
// ? not sure what to do here.l
});
app.get('*', (request, response) => {
response.sendFile('index.html', { root: '.' });
});
You don't have to manually define the /graphql route if you are indeed using the apollo-server-express package which is recommended if you want to combine Apollo with the express middleware. The official documentation actually puts you on the right track. In your specific case, your server setup should look someting like this:
const express = require('express');
const { ApolloServer, gql } = require('apollo-server-express');
// Construct a schema, using GraphQL schema language
const typeDefs = gql`
type Query {
hello: String
}
`;
// Provide resolver functions for your schema fields
const resolvers = {
Query: {
hello: () => 'Hello world!',
},
};
const server = new ApolloServer({ typeDefs, resolvers });
const app = express();
server.applyMiddleware({ app });
app.get('*', (request, response) => {
console.log('catch-all hit.');
});
app.listen({ port: 3000 }, () =>
console.log(`🚀 Server ready at http://localhost:3000${server.graphqlPath}`)
);
Just make sure that you define your catch-all route AFTER executing server.applyMiddleware, which sets up the /graphql endpoint for you. That way the /graphql endpoint is hit first and will be used to handle those requests. All the other requests will be handled by the catch-all.
I keep getting the following error on my graphql queries and not sure why:
POST body missing. Did you forget use body-parser middleware?
Am I doing something weird here? I have tried different recommendations with body-parser online, but still can't seem to fix it.
Server:
require('babel-polyfill')
const express = require('express')
const router = require('./middleware')
const expressStaticGzip = require('express-static-gzip')
const app = express()
const port = process.env.EXPRESS_PORT || 4000
const bodyParser = require('body-parser')
app.use(/\/((?!graphql).)*/, bodyParser.urlencoded({ extended: true }))
app.use(/\/((?!graphql).)*/, bodyParser.json())
app.use('/search/data', expressStaticGzip('public'))
app.use('/', router)
app.listen(port, () => {
console.log(`Server is running on port ${port}`)
})
Router
const router = express.Router()
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => {
const { authorization = '' } = req.headers
const universalFetch = (url, opts = {}) => {
return fetch(url, {
...opts,
headers: {
...opts.headers,
authorization,
},
})
}
const request = createRpcClient(universalFetch)
const methods = {}
const catalog = Object.keys(methods).reduce((catalog, method) => {
catalog[method] = params => request(methods[method], params)
return catalog
}, {})
return { catalog, fetch: universalFetch }
},
})
router.use(bodyParser.json())
router.use(bodyParser.text({ type: 'application/graphql' }))
router.use('*', renderer)
server.applyMiddleware({ app: router })
In my particular case the client just missed "Content-type" header with 'application/json' value. After adding that the error message has dissapeared.
applyMiddleware already adds body-parser for the GraphQL endpoint -- there's no need to apply it again and doing so may be causing your issue.
Additionally, I would expect applyMiddleware to be called before router.use('*', renderer) -- otherwise, I would think the wildcard route would be used for /graphql as well?
I forgot the header content-type: application/json
This error also caused by incorrect json in the body or some other problems in the body, such as unnecessary wrong invisible chars. So check generated json for errors and what is actually presents in the request body.
This error can also be raised because the body is too large.
I got it with apollo-server-micro inside a custom api route of NextJs.
It can be fixed by calling the json function coming from micro before apollo gets the request :
import { json } from 'micro'
import { ApolloServer } from 'apollo-server-micro'
const server = new ApolloServer({/*config*/})
const raiseBodyLimit: (handler: NextApiHandler) => NextApiHandler = (
handler
) => async (req, res) => {
if (req.headers['content-type'] !== 'application/json') {
return handler(req, res)
}
await json(req, { limit: '1gb' }) // This is the trick to raise body limit
return handler(req, res)
}
export default raiseBodyLimit(
server.createHandler({
path: '/api/graphql',
})
)
I saw this in this apollo-server's github issue.
Here are some information to build an apollo server endpoint with next.js
if your api upload anything you need to add the
{
uploads:true
}
in middleware while using graphql