Proxy error 504 after reading the request body - javascript

I was trying to read http request body, but I got 504 errors, it reminded me that proxy didn't config correctly. I think the issue is because of I read and access the request with process request.read().toString() How do I reset http request after done the request.body.toString()?
const proxyWithPromise = (
req: Request,
res: Response,
next: NextFunction
): Promise<void> => {
const events = req.body.toString();
console.log('events', events);
const goodData = filterJob(events);
if (goodData) {
return new Promise<void>(
(resolve) => {
res.on('close', resolve);
proxy(req, res, (err) => {
if (next != null) {
console.error(err);
next(err);
}
});
}
);
}
return new Promise<void>(() => {});
My goal is if its goodData after the filter work, I process the Promise; otherwise I would do nothing but complete a Promise.
Thanks a lot!!!
one approach I think is to do a deep copy with request, but its very expensive.

Related

Soap call with NestJS

I have to call SOAP webservice and serve it. I am using strong-soap library(https://github.com/loopbackio/strong-soap). I get my data in the service and I can see it in console.log() but I can't send this data to my controller to serve it. I have tried using pipe(map()) and I have looked into this following topics
(https://www.freecodecamp.org/news/an-express-service-for-parallel-soap-invocation-in-under-25-lines-of-code-b7eac725702e/)
but no luck. I either get 'can't subscribe to undefined' or my request is passing without my controller getting the data and serving it.
Here is my controller.ts
export class MyController {
constructor(private readonly service: Service){}
#Get('/example')
getAll(#Query() query: Query){
return this.service.getAll(query);
}
}
and here is my service
export class Service {
private URL = process.env.URL;
constructor() { }
async getAll(query: OrderRequest) {
const request = {
req: {
req: query,
}
};
return await soap.createClient(this.URL, (err, client) => {
if (err) {
console.error(err);
} else {
let method = client.myMethodName;
method(request, (err, result, envelope, soapHeader) => {
// here I am getting the data but 'return result. is not sending it to the controller
console.log(result[0])
return result
});
}
});
}
}
As I said I have tried with map and pipe like this:
return await soap.createClient(this.URL).pipe(map((err, client) => {
if (err) {
console.error(err);
} else {
let method = client.myMethodName; // here I have an error
method(request, (err, result, envelope, soapHeader) => {
console.log(result)
});
}
}))
but I can't pass my method in the client.
Thanks
OK I have found the solution. Thing is the function above was returning the promise so solution was to initialize new promise and handle reject and resolve. Like this we get the results in resolve and take them with .then() in our controller.
Here is the code:
service.ts
getAll(query: Query) {
const request = {query: {query: query}};
return new Promise ((resolve, reject) => { // here we add new Promise
soap.createClient(this.URL, (err, client) => {
if (err) {
return reject(err); // if error reject promise
} else {
return resolve(client); // else resolve and send client
});
}
});
}
)}
controller.ts
getAll(#Query() query: query){
console.log(this.service.getAll(query))
return this.service.getAll(query).then(result=>result)
}

Passing res wrapped in object into callback fails

I have a temporary server that looks like this:
import http from 'http'
export default function tempServer(
port: number
): Promise<{ req: http.IncomingMessage; res: http.ServerResponse }> {
return new Promise((resolve) => {
const server = http
.createServer(function (req, res) {
resolve({ req, res })
// This works
// res.write('Hey!')
// res.end()
server.close()
})
.listen(port)
})
}
And I am trying to manipulate res by calling res.write in another function:
function () {
const server = tempServer(parseInt(process.env.AUTH_PORT) || 5671)
return server.then(({req, res}) => {
const data = url.parse(req.url, true).query
...
res.write('Error: ' + data.error)
res.end()
...
})
}
The result is that res.write and res.write have no effect. I am sure the issue has something to do with contexts and bindings but I am having trouble going about it. Anyone willing to indulge me?

Value retrieved from MongoDB is undefined when fetched by Express.js server

Basically what I'm trying to accomplish is pulling the data from a MongoDB database and feed it into my Express.js server. Both of these are ran on the localhost with different addresses. I have tried numerous different methods to get it working and can't seem to get it to work.
Express portion
app.get('/products', function(request, response) {
var query = request.query.keywords;
var promise = new Promise(async (resolve, reject) => {
var productList = await db.getProducts(query);
resolve(productList);
});
promise.then(function(productList) {
console.log(productList); // <--- productList is undefined here
response.json({
productList
});
}).catch('Error retrieving data');
// var productList = Promise.resolve(db.getProducts(query));
// productList.then(products => response.json({products}));
});
MongoDB portion
StoreDB.prototype.getProducts = function(queryParams){
return this.connected.then(function(db){
// TODO: Implement functionality
const collection = db.collection('products');
var productList;
if (!queryParams){
console.log('no queryParams');
collection.find({}).toArray(function(err, docs) {
productList = convertToObject(docs);
// console.log(productList); // <--- productList is defined here
return productList;
});
////////////
Some extra information:
- StoreDB is a functional class with only one property , connected, which is a promise that gets resolved once the connection to the database has been established
- The Express.js server calls getProducts which then resolves the promise
- Within the getProducts call, productList is defined, but when it returns, the value is undefined
With this being said, I thought that by putting the getProducts within in a promise, it would wait for the function call to be complete, then resolve it. However, that is not the case. Some insights would be greatly appreciated. Thanks.
SOLVED
Thanks to #Renan Le Caro
app.get('/products', function(request, response, next) {
db
.getProducts(request.query.keywords)
.then(productList=>response.json({productList}))
.catch(err=>next(err));
});
StoreDB.prototype.getProducts = function(queryParams){
return this.connected.then(db =>
new Promise((resolve, reject) => {
db
.collection('products')
.find({})
.toArray((err, docs) => err ? reject(err) : resolve(docs))
})
}
getProducts is already a Promise; you shouldn't need to be wrapping a Promise in another Promise, and that just opens the code up to more places things can go wrong. But Promise.resolve does not wait for a Promise to resolve; instead, it IMMEDIATELY returns a new Promise that has already resolved with the value you pass it. That's not what you want. And .catch takes a function to run when the Promise fails, not a string.
Your code should be as simple as this:
app.get('/products', function(request, response) {
var query = request.query.keywords;
db.getProducts(query).then(function(productList) {
console.log(productList);
response.json({
productList
});
}).catch(function() {
response.send('Error retrieving data');
});
});
Or, if you prefer the async/await syntax:
app.get('/products', async function(request, response) {
var query = request.query.keywords;
try {
const productList = await db.getProducts(query);
console.log(productList);
response.json({
productList
});
} catch (err) {
response.send('Error retrieving data');
}
});
This is just a promises misuse problem. Here's a fix (not tested).
app.get('/products', function(request, response, next) {
db
.getProducts(request.query.keywords)
.then(productList=>response.json({productList}))
.catch(err=>next(err));
});
StoreDB.prototype.getProducts = function(queryParams){
return this.connected.then(db =>
new Promise((resolve, reject) => {
db
.collection('products')
.find({})
.toArray((err, docs) => err ? reject(err) : resolve(docs))
})
}

How to get JSON data from Firebase Cloud Function

Is there something wrong in my code? I always get the error Error: could not handle the request. Here's the code of my Cloud Function:
exports.helloWorld = functions.https.onRequest((request, response) => {
cors(request, response, () => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Methods", "GET");
response.set("Access-Control-Allow-Headers", "Content-Type");
response.set("Access-Control-Max-Age", "3600");
let dock = [];
const snapshot = db.collection("users").get()
snapshot.docs.forEach((val) => {
dock.push(val.id);
});
});
});
I don't know if you are trying to return dock as response, but if you do, try this out:
exports.helloWorld = functions.https.onRequest((request, response) => {
cors(request, response, () => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Methods", "GET");
response.set("Access-Control-Allow-Headers", "Content-Type");
response.set("Access-Control-Max-Age", "3600");
let dock = [];
db.collection("users").get().then(snapshot => {
snapshot.docs.forEach((val) => {
dock.push(val.id);
});
return dock;
})
.catch(errors => {
console.log(errors);
return false;
})
});
});
The get() returns a promise that you have to solve.
Also it is a good idea to put a catch() at the end to see errors appear, when executing your code.
A HTTPS triggered Cloud Functions (like the one in your question) runs until it sends a response to the client, or until it times out. Since your code never sends a response to the client, it times out. And that's why the client gives you and error.
I assume you want to send the document IDs back to the client, so that'd be something like:
exports.helloWorld = functions.https.onRequest((request, response) => {
cors(request, response, () => {
response.set("Access-Control-Allow-Origin", "*");
response.set("Access-Control-Allow-Methods", "GET");
response.set("Access-Control-Allow-Headers", "Content-Type");
response.set("Access-Control-Max-Age", "3600");
let documentIds = [];
db.collection("users").get().then((snapshot) => {
snapshot.docs.forEach((document) => {
documentIds.push(document.id);
});
res.send(JSON.stringify(documentIDs));
});
});
});

Promise Chaining error handling

I am learning how to use Promise without libraries. From what I have read, I could chain Promise together and then add .catch in the end for error handling.
What do I expect
So if I change the URL to some false url, shouldn't I be catching the error and stop the entire program to be continuing?
What Am I seeing now?
When I put a false url, the program just throws out an error, instead of handling it like an rejection.
const request = require("request");
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
}
resolve(JSON.parse(body).results[0].geometry.location);
}
);
})
.then(res => {
const {lat, lng} = res;
return new Promise((resolve, reject) => {
request(
`https://api.darksky.net/forecast/6fb416a8313aabd902a22558e07cc032/${lat},${lng}`,
(err, res, body) => {
if (err) {
reject("bad call on darksky");
}
resolve(JSON.parse(body));
}
);
});
})
.then(res => {
const currentTemp = res.currently.temperature;
const feelTemp = res.currently.apparentTemperature;
const temps = {currentTemp, feelTemp};
return new Promise((resolve, reject) => {
request(
"http://ron-swanson-quotes.herokuapp.com/v2/quotes",
(err, res, body) => {
if (err) {
reject("bad call on quotes");
}
resolve({temps, body});
}
);
});
})
.then(res => {
console.log(
`Today's weather is ${res.temps.currentTemp}, and it feels like ${res
.temps
.feelTemp}! \nAnd here is your stupid quote of the day: \n${JSON.parse(
res.body
)[0]}`
);
})
.catch(err => {
console.log(err);
});
Error Message:
This isn't really meaningful, basically the error did not stop the program, which just passed down to the next promise. That promise receive the error but could not parse it because it is not in expected JSON format.
SyntaxError: Unexpected token < in JSON at position 0
at JSON.parse (<anonymous>)
at Promise.then.then.then.res (/Users/leoqiu/reacto/playground/6_promiseMethod.js:48:74)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
When you call reject() inside your if statement, you don't return and you don't use an else so your resolve(JSON.parse(body).results[0].geometry.location); still gets executed and that throws an exception.
You can change to this:
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
return;
}
resolve(JSON.parse(body).results[0].geometry.location);
}
);
})
It is a common mistake that people think reject() works like break or some other control flow statement because reject() is a type of promise control flow. But, it doesn't stop execution in your block so you need to either return after it or use an else.
Or, I prefer to use if/else because I think it makes the logic even more obvious:
new Promise((resolve, reject) => {
request(
"http://maps.googleapis.com/maps/api/geocode/json?address=321%20i%20st%20davis",
(err, res, body) => {
if (err) {
reject("bad call on geo code!");
} else {
resolve(JSON.parse(body).results[0].geometry.location);
}
}
);
})
Based on Patrick Evans suggestion...
reject does not stops the program from running, so the error message gets pass down to the next Promise, which is why is throwing a json parsing error.
The solution is simply put a return in the rejection.
if (err) {
reject("bad call on geo code!");
return err;
}

Categories

Resources