I need to pull the weather API data from
https://api.weatherapi.com/v1/current.json?key=f5f45b956fc64a2482370828211902&q=London
It gives a response when pasted in the web browser as well as in postman. But, once incorporated in javascript https.get it fails by continuously loading the browsers and hanging the terminal with unwanted informations.
app.js :
//jshint esversion:6
const express = require("express");
const https = require("https");
const app = express();
app.get("/",function(req, res){
const url = "https://api.weatherapi.com/v1/current.json?key=f5f45b956fc64a2482370828211902&q=London";
https.get(url,function(response){
//console.log(response);
response.on("data",function(data){
const weatherData = JSON.parse(data);
const temp = weatherData.current.temp_c;
const weatherDescription = weatherData.current.condition.text;
});
});
res.send("Server is up and running");
});
app.listen(3000, function(){
console.log("Started on port 3000");
});
I tried the specific request that you posted using https.get() and it worked for me. So it will be difficult to figure out what is the exact problem without more information, for example about how exactly it is failing for you. What messages are you seeing on the console? How are you accessing the result of the request, so what makes you think that the request didn't work?
But apart from that, that is not how you usually make requests in Node. The "data" event may be emitted multiple times if the response arrives in multiple chunks, so the way you do it will only work if you are lucky and the response arrives in a single chunk. The proper way to do this by hand would be to listen to all "data" events, concatenate the result, and then when the "end" event is emitted, parse the concatenated data. However, it is rather uncommon to do this by hand.
A more common way to do this would be to use a library such as node-fetch to make the request for you. For example like this: fetch(url).then((res) => res.json()).then((weatherData) => { const weatherDescription = weatherData.current.condition.text; }).
Related
My main server.js File
const koa = require("koa");
const Router = require("koa-router");
const bodyParser = require("koa-bodyparser");
const app = new koa();
var router = new Router();
// app.use(bodyParser({ enableTypes: ["json", "text"] }));
// I have also tried passing enabletypes parameteres but it still is not working..
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());
router.post("/", async (ctx) => {
console.log(ctx);
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => console.log(`Server started on port no ${PORT}`));
When i hit this router.post("/") end point ... just for the purpose to see my context object i console logged the context object and it shows the following in the console when I hit this endpoint using postman (i am send JSON body in the request)
My postman request
How do I access my body (JSON object) ?
To access your body object, try the following:
const body = ctx.request.body;
Secondly: because in one of the comments there was a note, why you get a 404. I guess this is because in your route you are not returning anything. So your route could look like:
router.post("/", async (ctx) => {
const body = ctx.request.body;
console.log(body);
return (true) // or whatever you want to return to the client
});
I'd suggest using something to return i.e. if you return nothing you are going to get a 404 with Koa. Just set the body of the ctx i.e. ctx.body="something here".
Other than that depending on what you are using in the app to hit it Postman may work slightly different and pass additional headers etc. I've run into this a handful of times using Thunder Client on VS Code where it works when poking it but in the app something is slightly off. I've ONLY run into this with Koa and never express so might be worth checking and logging along the way WITHIN the app.
I've written a code here and I want to know what "response.on" is doing and why we are passing "data", what is this "data".
what exactly that ".on" is used for.
const express = require("express");
const https = require("https");
const app = express();
app.get("/",function(req,res){
const url="https://api.openweathermap.org/data/2.5/weather?q=London&appid=5c8618a9210a11846accc217f3b3084f";
https.get(url,function(respons){
response.on("data",function(data){
const wht = JSON.parse(data)
temp = wht.main.temp
res.send("temp "+ temp)
})
})
})
app.listen(3000, function(){
console.log("running");
});
.on("nameOfEvent", callback) it's a event emitter. So, basically whenever that event is called, that callback will be executed. data is just the name of the event.
In your code there is bug.
You using respons in the argument of function and response inside of function.
Waiting on data of response is documented in https
https://nodejs.org/api/https.html#https_https_get_options_callback
You can read that response is not a classical response from the server but an event listener that listens for stream of data.
It is a low-level interface and in your applications, you should not use them. Lets interest in node-fetch or axios instead if you want only get a response, but not process streams in real-time.
I am running a server using expressjs. Whenever a user accesses to one of my specific url (for this purpose, just imagine it will be https://server.com/test), I want to emit a data to another webserver using socketio, listen to the data and respond to the user with the data I have received.
Few things to note:
My server expects nothing but just an access to the https://server.com/test url.
Another server, which I want to connect using socket.io and obtain data expects me to send an argument of {"got" : "true"} to parameter called "test".
When another server receives the socket emit from my server on parameter "test" with arguments specified above, it simply replies back with an argument {"message" : "true"}
My code is quite simple and looks like this (router) :
const express = require("express");
const router = express.Router();
//const Goal = require("../models/battery_message");
const mongoose = require("mongoose");
const io = require("socket.io-client");
const host = "https://another_server.com"
const socket = io(host, {query:"email=edmund#gmail.com"});
console.log("connected");
router.get('/', function(req,res) {
socket.emit("test_me", {"got" : "true"}, function(data){
exists = data;
console.log(data);
});
});
module.exports = router;
The problem I have is whenever the user accesses my server on https://server.com/test nothing happens, as no response comes like in an infinite loop. My guess is that I need some kind of another socket.emit because another server probably emits its response to the socket too, but I might be wrong.
So to sum up, my question is, what do I need to add in order to successfully get the response from another server?
I cannot seem to get the body data shown on my server. I am actually trying to get this in post/put/fetch calls, but to try to fix the problem, i've boiled it down to a simple .get, and it still won't appear. Can anyone see why the body isn't showing on the server? I'm unable to get anything done in more complicated called due to this (like get the body of the req, but sticking to this simple example for now.)
This code is a fully working and sends data, just cant seem to access the body on the server.
server.js
const express = require('express');
const app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.json());
const port = process.env.PORT || 8000;
const Cat = require('./Cat');
const Dog = require('./Dog');
app.route('/animals')
.get(function (req, res) {
console.log(req.body, 'req.body log'); //this returns {}
res.send({ Cat, Dog });
})
app.listen(port, () => console.log(`Listening on port ${port}`));
In react, if I call the following callApi() function, console.log shows the body data just fine on the front end, and the data can be used on the page.
client call
callApi = async () => {
const response = await fetch('/animals');
const body = await response.json();
console.log(body) //shows all the data just fine!
if (response.status !== 200) throw Error(body.message);
return body;
};
Using node 9 and express 4.
I think you're confusing the request and response objects. But aside from that, I'll explain where/how to get data passed in from GET and POST/PUT requests.
When a GET request is made, you can pass data to the server via query params (i.e. /animals?type=cat). These parameters will be available already parsed in an object called req.query.
When a POST or PUT request is made, and you've applied the body parsing middleware (which you have done), the JSON will be available as a parsed object under req.body.
In your example, you have made a GET request, and have no provided any query string parameters. So req.body will return an empty object, as will req.query.
Your client call shows data because you've sent data back in the response via res.send(). This is totally unrelated to why req.body is an empty object in your case.
Try using fetch('/animals?type=cat') in your client call. Then, you will see that req.query returns { type: 'cat' }.
Have an application where I want to start a node express server and then start a browser on the same machine automatically as soon as the server is up. How can I query to see if the server is up and ready to go? I really wanted there to be some sort of callback on the .listen call, but doesn't seem to be. I could just wait a longer than I expect amount of time, but this is going on equipment that will be in the field so I either have to wait a ridiculous amount of time to make sure I'm up and running before kicking off the browser or have the user be smart enough to hit refresh if the page doesn't load right. Neither of those are good options for me. . .
I read the API online but don't see anything like this. Surely there's a trick I don't know that can accomplish this.
If the node HTTP api (which has a callback and tells me about the listening event) is the base for the express object, maybe there is a callback option for the express call listen that isn't documented. Or perhaps I'm supposed to just know that it's there.
Any help would be greatly appreciated.
The Express app.listen function does support a callback. It maps the arguments that you pass in to the http.listen call.
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
So you can just call: app.listen(port, callback);
Or you could use http.listen directly.
var app = require('express')(),
server = require('http').createServer(app);
server.listen(80, function() {
console.log('ready to go!');
});
You can fire a custom event after the server is started:
// server.js
const express = require('express');
const app = express();
modeule.export = app;
app.listen(3000, () => {
app.emit('listened', null)
});
In a separate module, the app can listen your custom event:
// custom.js
const server = require('server.js');
server.on('listened', function() {
console.log('The server is running!');
});
You can use the http.listen method which has a callback function that triggers once the server is ready:
http.createServer(app).listen(app.get('port'), function () {
console.log('Printed when ready!!!');
});
See the official reference at Node.js:
http://nodejs.org/api/all.html#all_server_listen_port_hostname_backlog_callback
http://nodejs.org/api/all.html#all_server_listen_path_callback_1
http://nodejs.org/api/all.html#all_server_listen_handle_callback_1
As many have mentioned, the listen function (on the express app or an http server, both support it), does support a callback and that will let your node process know when it is listening.
So if you plan to launch the browser from within your express app, do it there and you are good. However, if you are launching the express app from an external script and then want that external script to open the browser, the node callback doesn't really buy you anything.
Waiting for some magic string on stdout isn't really an improvement on just waiting for a good HTTP response. You may as well just use a try/backoff/timeout loop with curl until you get a successful response.
server.on('listening', function() {
resolve();//I added my own promise to help me await
});
The Listening event worked for me. Note I added my own Promise. I imagine you could obtain similar results without a promise by adding an entry point to this listener.
Note, I tried the more intuitive server.on('listen') and it didn't work. Running node 6.9.1
With async/await syntax, this can be done by wrapping the server startup in a promise, so you can wait for it to be started before running anything else:
import express from 'express';
import http from 'http';
const app = express();
let server: http.Server;
const startServer = async (): Promise<void> => {
return new Promise((resolve, _reject) => {
server = app.listen(3000, () => {
console.log('Express server started');
resolve();
});
});
};
await startServer();
// here the server is started and ready to accept requests