pass variable to nodesjs to localhost - node.js

I want to pass the variable "valor_dollar" into the server localhost or an file html. Actually I can not to look the variable the browser.
const express = require ('express');
const cheerio = require ('cheerio')
const request = require ('request-promise')
const axios = require('axios')
const app = express();
app.get('/',(req,res) => {
res.end(prova());
});
app.listen(3000);
function prova(){
axios.get('https://www.morningstar.es/es/funds/snapshot/snapshot.aspx?id=F0GBR04ASX').then((response) => {
// Load the web page source code into a cheerio instance
const $ = cheerio.load(response.data)
// The pre.highlight.shell CSS selector matches all `pre` elements
// that have both the `highlight` and `shell` class
const urlElems = $('td.line.text')[0]
const urlText = $(urlElems).text()
let valor_dollar = Number(urlText.substring(4,7))
console.log(valor_dollar)
})
}

You are calling res.end method directly without setting the body, the prova function returns undefined.
Instead you can modify your method like this to have a callback that runs after the HTTP call.
function prova(callback){
axios.get('https://www.morningstar.es/es/funds/snapshot/snapshot.aspx?id=F0GBR04ASX').then((response) => {
// Load the web page source code into a cheerio instance
const $ = cheerio.load(response.data)
// The pre.highlight.shell CSS selector matches all `pre` elements
// that have both the `highlight` and `shell` class
const urlElems = $('td.line.text')[0]
const urlText = $(urlElems).text()
let valor_dollar = Number(urlText.substring(4,7))
callback(valor_dollar);
});
}
and the route should be like this:
app.get('/',(req,res) => {
prova(function(value) {
res.body = { dollar_value: value };
res.end();
});
});

Related

How can i get a client side cookie with next.js 13 before rendering from middleware

I am trying to get a cookie from the middleware of Nextjs 13 and I can't find up to date information on this.
My question: is there a way to see the cookie before rendering the html.
window is fined or something?
page.tsx
async function getData() {
const nextCookies = cookies(); // Get cookies object
try {
let cityToken = nextCookies.get('regionCode'); // Find cookie city
return cityToken;
} catch (e) {
console.log(e);
}
}
export default async function Page() {
const nextCookies = cookies(); // Get cookies object
const token = nextCookies.get('new'); // Find cookie for is new user
// const cityToken = await getData();
const cityToken = cookies().get('regionCode')?.value;
console.log(cityToken);
}
middleware.tsx
const myFunction = async () => {
// https://geolocation.onetrust.com/cookieconsentpub/v1/geo/location
// run asynchronous tasks here - ip location
const response = await fetch('https://www.cloudflare.com/cdn-cgi/trace');
const text = await response.text();
const arr = text.split('\n');
const ip = arr.filter((v) => v.includes('ip='))[0].split('=')[1];
// https://stackoverflow.com/questions/65752416/how-can-i-most-easily-parse-this-http-response-into-json-to-then-access-response
// https://stackoverflow.com/questions/64591296/access-to-fetch-at-https-www-cloudflare-com-cdn-cgi-trace-from-origin-http
const ipCity = await fetch(`https://ipapi.co/${ip}/json/`);
const textJson = await ipCity.json();
};
const data = await myFunction();
res.cookies.set('regionCode', 'textJson.region');

Cannot GET /[object%20Object] when calling axios.get()

When I paste the endpoint URL with query directly inside the axios.get(), it responds correctly and I can see the json object returned. (i.e axios.get(http://localhost:3000/api/products/product_search?secretKey=${secret}&id=${blabla})). However, if I call the url with the summonerByNameUrl method, it crashes when I make a request. What is the problem in my code?
Crash report:
...
data: '<!DOCTYPE html>\n' +
'<html lang="en">\n' +
'<head>\n' +
'<meta charset="utf-8">\n' +
'<title>Error</title>\n' +
'</head>\n' +
'<body>\n' +
'<pre>Cannot GET /[object%20Object]</pre>\n' +
'</body>\n' +
'</html>\n'
},
isAxiosError: true,
toJSON: [Function: toJSON]
Code:
config.js
const summonerByNameUrl = (summonerName) => `${URL(hidden)}${summonerName}`;
module.exports = {
summonerByNameUrl
}
summoner.js
const config = require('../config');
const axios = require('axios');
const getSummonerByName = async (summonerName) => {
const res = await axios.get(config.summonerByNameUrl(summonerName));
return res.data;
}
const summonerParser = async (req, res) => {
if(!req.query.secretKey)
return res.status(403).json({error: 'missing secret key.'})
let data = await getSummonerByName(req.query)
return res.status(200).json(data);
}
module.exports = {
getSummonerByName,
summonerParser
}
products.js
var express = require('express');
var axios = require('axios')
var router = express.Router();
const summoner = require('../services/summoner');
router.get('/product_search', summoner.summonerParser)
module.exports = router;
app.js
...
app.use('/api/products', productsRouter);
...
You're calling your function with getSummonerByName(req.query) where it is clear from the lines just before that req.query is an object and not a string. When objects are used in a string-context (like your URL), they become "[object Object]", hence the error.
Taking some guesses here but it seems you want to forward some req.query information to the Axios call as query params. Try this instead...
const PRODUCT_SEARCH_URL = "http://localhost:3000/api/products/product_search"
const getSummonerByName = async ({ secretKey, id }) => {
const { data } = await axios.get(PRODUCT_SEARCH_URL, {
params: { secretKey, id }
})
return data
}
If you've got a helper function that returns the base URL (ie http://localhost:3000/api/products/product_search) then by all means, use that instead of a string literal in the Axios call.
The req.query is a Object, not a string.
You can try map the req.query object to make a string. Something like that:
Object.keys(req.query).map(key => {
return key + '=' + req.query[key]
}).join('&')
This code return a string like that: 'id=1&name=test', so you can pass to the endpoint.

Enabling Http2Stream in koa2 app

I7m trying to create a simple http2 server and want to make use of Http2Stream in the http2 module to push large assets. How can I incorporate it in my Koa2 app? currently my server is just a middleware that receives the ctx and next object and checks if the file exists and tries to send it out.
async server(ctx, next, ...arg){
//check if file exists
//if it exists, set the headers and mimetype and send file
}
Does the ctx object contain the functions needed to work with http2stream, or how can i extend it?
You can utilize the stream in ctx.res (which is the original node response) like so: ctx.res.stream
Working example: Koa2 with http/2 - this one gets a file in the public folder (filename ist hardcoded here) and sends it through the stream (which then should be the http2stream). Just type https://localhost:8080/file in your browser. You need to place a file thefile.html in to ./public:
'use strict';
const fs = require('fs');
const http2 = require('http2');
const koa = require('koa');
const app = new koa();
const options = {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem'),
passphrase: 'test'
};
function getFile(path) {
const filePath = `${__dirname}/public/${path}`;
try {
const content = fs.openSync(filePath, 'r');
const contentType = 'text/html';
return {
content,
headers: {
'content-type': contentType
}
};
} catch (e) {
return null;
}
}
// response
app.use(ctx => {
if (ctx.request.url === '/file') {
const file = getFile('thefile.html');
ctx.res.stream.respondWithFD(file.content, file.headers);
} else {
ctx.body = 'OK' ;
}
});
const server = http2.createSecureServer(options, app.callback());
console.log('Listening on port 8080');
server.listen(8080);
Hope that helps

Re Initialization express Application

I have node.js application, which was built on express.js framework.
const app = express();
require('./config')(app);
require('./services')(app);
./config/config.js we instantiate config:
module.exports = function (app) {
const conf = {APIKey: 1234567890, url: '<someurl>'};
app.set('config', conf);
};
./services/APIService.js we create service instance(singleton)
module.exports = (app) => {
app.set('apiService', new APIService(app));
};
function APIService(app) {
const config = app.get('config');
this.key = config.APIKey;
};
APIService.prototype.sendRequest = () => {
const config = app.get('config');
this._send(config.url, 'some text');
};
Or, service2
module.exports = function(app) {
const config = app.get('config');
const myMod = require('myMod')(config.APIKey);
}
Cool, all works correct. But sometime administrator will change some config data. So, we create new config, set him to
newConf = {APIKey: 1234000000, url: '<some_new_url>'};
app.set('config', newConf);
APIService.sendRequest, will send request to CHANGED url, but APIService.key still unchanged. And myMod already instantiated with old config data.
We need write some setter methods, like this
//for APIService
APIService.prototype.setConfig = () => {
const config = app.get('config');
this.key = config.APIKey;
};
//for service 2
/* change const myMod to let myMod and create method for overriding */
or bang! kill and restart node.js server process. Bad idea. Maybe exist some method for this goal, something like app.restart() for safely reinitializing application(or, maybe, his parts)?
Did you try to call app.set('apiService', new APIService(app)); again ? or just have getter and setter on the prototype for your params.
Better way should be to have a new APIService object at each new request with a middleware, somehting like :
app.use(function (req, res, next){
req.api = new APIService(app);
next();
});
And use req.api.

Routing in Express.js - dynamic number of parameters

I've a concept for create routing with multiple parameters when numbers of it are dynamic, for example:
/v2/ModuleName/Method/Method2/
In Express I want parse it as: Modules.v2.ModuleName.Method.Method2(). When will be just one method, this should be of course Modules.v2.ModuleName.Method(). It's possible to do that?
You can split pathname then lookup the method from your Modules object like this:
// fields = ['v2', 'ModuleName', 'Method', 'Method2']
var method = Modules;
fields.forEach(function (field) {
method = method[field];
})
// call method
console.log(method());
Full code:
var express = require('express'), url = require('url');
var app = express();
Modules = {
method: function () { return 'I am root'},
v2: {
method: function () { return 'I am v2';}
}
};
app.get('/callmethod/*', function (req, res) {
var path = url.parse(req.url).pathname;
// split and remove empty element;
path = path.split('/').filter(function (e) {
return e.length > 0;
});
// remove the first component 'callmethod'
path = path.slice(1);
// lookup method in Modules:
var method = Modules;
path.forEach(function (field) {
method = method[field];
})
console.log(method());
res.send(method());
});
app.listen(3000);
Test on browser:
http://example.com:3000/callmethod/method
"I am root"
http://example.com:3000/callmethod/v2/method
"I am v2"
PS: you can improve this app to support pass params to a method via url:
http://example.com:3000/callmethod/v2/method?param1=hello&param2=word

Resources