How to load JSON/API data using https.request and Node.JS - javascript

I'm trying to load weather data. I have front end code that was doing this perfectly but I need to move this to back end. I moved a library of my functions over to Node.JS. I was using $.getJSON but was told I should use https.request for the new version. Here's my code:
getTextWeatherUsingStationUsingRequest: function(theStation){
const http = require("http");
const https = require("https");
thePath = 'stations/' + theStation + '/observations/current';
// theURL = 'https://api.weather.gov/stations/' + theStation + '/observations/current';
function requestTheData(){
var options = {
protocol: "https:",
hostname: "https://api.weather.gov/",
path: thePath,
port: 80,
method: "GET"
};
var instaRequest = https.request(options);
instaRequest.on("response", function(res){
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
console.log("response");
console.log(res.statusCode);
console.log(res.statusMessage);
});
instaRequest.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
instaRequest.end();
}
requestTheData();
I'm getting this error and can't figure out what's going on:
problem with request: getaddrinfo ENOTFOUND https://api.weather.gov/stations/ https://api.weather.gov/stations/:80

HTTPS generally uses port 443, so lets change that. Also, the API shows the hostname should be the raw URL and the path should be the remainder of the route (with a leading slash) similar to this:
thePath = '/stations/' + theStation + '/observations/current';
...
var options = {
hostname: "api.weather.gov",
path: thePath,
port: 443,
method: "GET"
};

Before even seeing any answers I got it working by:
protocol: "https:",
hostname: "api.weather.gov",
but then I was getting a STATUS:
403 Forbidden You don't have permission to access
"http://api.weather.gov/" on this server.
I seemed to remember that you are required to pass something in through headers so I added this under "method: "GET","
method: "GET",
headers: {
'Accept' : 'application/json',
'Content-Type': 'application/json',
'User-Agent' : 'MY-UA-STRING'
}
And, voila, now I'm getting JSON weather data. It didn't work until I added the 'User-Agent'. Do you guys know what this needs to be (and/or point me to a place that describes this)?

Related

POST request from Node to another server with windows credentials

I am trying to send a post request to a service from my node server.
Node is running on http://localhost:3000. The method I am trying to reach is reachable through http://localhost:80/some/adress/business/layer/myMethod.
var options = {
host: 'localhost',
path: '/some/adress/business/layer/myMethod',
port: '80',
method: 'POST',
headers: {
'Content-type': 'application/json',
'Content-Length': data.length
}
};
var req = http.request(options, function (resu) {
console.log('statusCode: ' + res.statusCode)
resu.on('data', function (d) {
console.log(d);
});
resu.on('error', function (err) {
console.log(err);
});
resu.on('end', function () {
res.jsonp({ result: true });
res.end();
});
});
req.write("data");
req.end();
The request works fine, well more or less. I am getting a 401 status back. The question is: How can I send windows credentials from node to the named server running on localhost:80... ?
Without knowing the exact details of your setup, I can't be sure, but you probably need to use NTLM authentication. There are several libraries that do this for node. Take a look at this question. Hope this helps!

Curl mechanism, inside the expressjs code

I am new to most of these concepts, so I apologize if this question is trivial.
I have a script that makes an HTTP POST request in Curl, for sending json file data .
curl https://XXXX.zendesk.com/api/v2/channels/voice/tickets.json ^
-d #C:\Users\Agent\Desktop\json.json ^ -H "Content-Type: application/json" -v -u AAAAA#BBBBB.com/token:99dd6ghxsdrf85fgYdHWb33VYCZXI35fg8w13pfL -X POST
i need to use the mechanism for making HTTP requests of Curl in my code expressjs,
var express = require('express');
var app = express();
app.use(express.static('public'))
app.get('/index.html',function(req,res) {
res.sendFile(__dirname+"/"+'index.html');
})
app.get('/express_get',function(req,res) {
response ={
firstname : req.query.firstname,
lastname: req.query.lastname,
Email: req.query.email
};
console.log(response);
res.end(JSON.stringify(response));
})
var server = app.listen(8000,function() {
var host = server.address().address;
var port = server.address().port;
console.log('App running on http://127.0.0.1:8000')
})
but unfortunately i don't know how to make it !!
so the questions are:
1:
-d #C:\Users\Agent\Desktop\json.json
in the Curl code, is the file that i want use it , it contain data, what do you think about replace it by (JSON.stringify(response)) in the expressjs code !!
2:
and how can i do the same work of curl inside my expressjs code !!!!
Any help, any suggestion is appreciated!
you want to request https://XXXX.zendesk.com/api/v2/channels/voice/tickets.json from one of your express route ?
For that there is Node.js HTTP built-in module (https://nodejs.org/api/http.html#http_http_request_options_callback), which offers the possibility to do a POST request to an host.
There is an example just below on how to use it
// From https://nodejs.org/api/http.html
const postData = querystring.stringify({
'msg': 'Hello World!'
});
const options = {
hostname: 'www.google.com',
port: 80,
path: '/upload',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(postData)
}
};
const req = http.request(options, (res) => {
console.log(`STATUS: ${res.statusCode}`);
console.log(`HEADERS: ${JSON.stringify(res.headers)}`);
res.setEncoding('utf8');
res.on('data', (chunk) => {
console.log(`BODY: ${chunk}`);
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});
// write data to request body
req.write(postData);
req.end();
You will need to read your JSON file (with Node's FileSystem module) and write it to req after stringifying it :)

HTTP POST in Espruino for Microcontrollers

I recently got myself an esp8266-12e module and loaded the ESPRUINO.js firmware on it. I am trying execute a post request from the device, but the device always returns a 'no connection' error when trying to POST.
To troubleshoot I have ran a GET request to the same URL, and the request was successful, this means that internet is working on the device and communication with the intended server is possible.
I then moved on to see if there were errors in my HTTP POST code, I ran the same code in a node.js app and it successfully posted to the server.
Here is the code below, I removed the exact address of my server and my wifi/pass info.
var http = require("http");
var wifi = require("Wifi");
var sdata = {
deviceID: 'esp-12',
};
var options = {
hostname: 'immense-XXXXXX-XXXXX.herokuapp.com',
method: 'POST',
path:'/MXXXXXX',
headers: {
'Content-Type': 'application/json'
}
};
var req = http.request(options, function(res) {
console.log('Status: ' + res.statusCode);
console.log('Headers: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function(body) {
console.log('Body: ' + body);
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
payload = JSON.stringify(sdata);
req.write(payload);
req.end();
terminal response from device after execution
problem with request: no connection
Here is the documentation for Espruino.js HTTP module.
https://www.espruino.com/Reference#http
Can any of the JS gurus see an issue with the request?
Turns out the http post request requires the 'content-length' header to function correctly.
Here is the working post request model for anyone who may need it. Note: Payload has already been formatted as a JSON object.
function postX(payload) {
var options = {
host: 'url',
port: '80',
path:'/ext',
method:'POST',
headers: { "Content-Type":"application/json", "Content-Length":payload.length }
};
var req = require("http").request(options, function(res) {
res.on('data', function(data) {
console.log("-->"+data);
});
res.on('close', function(data) {
console.log("==> Closed.");
ticksSinceConnect = 0;
});
});
req.end(payload);}

node socket hang up error with http

I followed the node http document to write a delete request to the local server, but receive the socket hang up error, similar question I checked are:
NodeJS - What does “socket hang up” actually mean?
Error: socket hang up using node v0.12.0
but no one actually work for my scenario.
I believe it is the code error because I use postman it works for me, following is my code
var options = {
hostname: 'localhost',
port: 3000,
path: '/accounts/abc'
method: 'DELETE',
headers: {
'Content-Type': 'application/json; charset=utf-8'
}
};
var order = {
"secret": "abc_secret"
};
var content = JSON.stringify(order);
var req = http.request(options, function(res) {
console.log('STATUS: ' + res.statusCode);
res.on('data', function(chunk) {
console.log('resp: ' + chunk);
});
});
req.on('error', function(err) {
console.error('error: ' , err.stack.split("\n"));
});
req.write(content);
req.end();
and the errors are:
error: [ 'Error: socket hang up',
' at createHangUpError (_http_client.js:215:15)',
' at TLSSocket.socketOnEnd (_http_client.js:300:23)',
' at TLSSocket.emit (events.js:129:20)',
' at _stream_readable.js:908:16',
' at process._tickCallback (node.js:355:11)' ]
Apparently, the request header does not have content length. Therefore, whatever you wrote in the write function will be ignored. Hope this is the root cause.
for me - solved by add Content-Length header.
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Content-Length': Buffer.byteLength(JSON.stringify(order))
}

Verifiy iOS Receipt with Node.js

After struggling a few days trying to get something to work and getting no where, I was wondering if someone has gotten iOS Receipt Validation working on Node.js. I have tried the node module iap_verifier found here but I could not get it to work properly for me. the only response I received back form Apples servers is 21002, data was malformed.
One thing that has worked for me was a client side validation request to apples servers that I got directly from the tutorials provided by Apple here, with the code shown below.
// The transaction looks ok, so start the verify process.
// Encode the receiptData for the itms receipt verification POST request.
NSString *jsonObjectString = [self encodeBase64:(uint8_t *)transaction.transactionReceipt.bytes
length:transaction.transactionReceipt.length];
// Create the POST request payload.
NSString *payload = [NSString stringWithFormat:#"{\"receipt-data\" : \"%#\", \"password\" : \"%#\"}",
jsonObjectString, ITC_CONTENT_PROVIDER_SHARED_SECRET];
NSData *payloadData = [payload dataUsingEncoding:NSUTF8StringEncoding];
// Use ITMS_SANDBOX_VERIFY_RECEIPT_URL while testing against the sandbox.
NSString *serverURL = ITMS_SANDBOX_VERIFY_RECEIPT_URL;
// Create the POST request to the server.
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:serverURL]];
[request setHTTPMethod:#"POST"];
[request setHTTPBody:payloadData];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
[conn start];
I have a bunch of different code I have been using to send a wide array of things to my node server. and all of my different attempts have failed. I have even tried just funneling the "payloadData" I constructed in the client side validation example above to my server and sending that to Apples servers with the following code:
function verifyReceipt(receiptData, responder)
{
var options = {
host: 'sandbox.itunes.apple.com',
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptData)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
});
});
req.write(receiptData);
req.end();
}
Where the function is passed the payloadData. The response received from Apple is always 21002. I'm still basically a node novice,so I can't figure out what exactly is going wrong. I think there might be some data corruption happening when I am sending the data from ObjC to my Node server, so perhaps I am not transmitting right.
If anyone can point me in the right direction, or provide some example of how they got receipt validation to work in node for them, it would be a great help. It would be great if anyone has had any experience with the iap_verifier module, and exactly what data it requires. I'll provide any code example I need to, as I have been fighting this process for a few days now.
Thanks!
For anyone using the npm library "request", here's how to avoid that bothersome 21002 error.
formFields = {
'receipt-data': receiptData_64
'password': yourAppleSecret
}
verifyURL = 'https://buy.itunes.apple.com/verifyReceipt' // or 'https://sandbox.itunes.apple.com/verifyReceipt'
req = request.post({url: verifyURL, json: formFields}, function(err, res, body) {
console.log('Response:', body);
})
This is my working solution for auto-renewable subscriptions, using the npm request-promise library.
Without JSON stringify-ing the body form, I was receiving 21002 error (The data in the receipt-data property was malformed or missing)
const rp = require('request-promise');
var verifyURL = 'https://sandbox.itunes.apple.com/verifyReceipt';
// use 'https://buy.itunes.apple.com/verifyReceipt' for production
var options = {
uri: verifyURL,
method: 'POST',
headers: {
'User-Agent': 'Request-Promise',
'Content-Type': 'application/x-www-form-urlencoded',
},
json: true
};
options.form = JSON.stringify({
'receipt-data': receiptData,
'password': password
});
rp(options).then(function (resData) {
devLog.log(resData); // 0
}).catch(function (err) {
devLog.log(err);
});
Do you have composed correctly receiptData? Accordlying with Apple specification it should have the format
{"receipt-data": "your base64 receipt"}
Modifying your code wrapping the base64 receipt string with receipt-data object the validation should works
function (receiptData_base64, production, cb)
{
var url = production ? 'buy.itunes.apple.com' : 'sandbox.itunes.apple.com'
var receiptEnvelope = {
"receipt-data": receiptData_base64
};
var receiptEnvelopeStr = JSON.stringify(receiptEnvelope);
var options = {
host: url,
port: 443,
path: '/verifyReceipt',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': Buffer.byteLength(receiptEnvelopeStr)
}
};
var req = https.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (chunk) {
console.log("body: " + chunk);
cb(true, chunk);
});
res.on('error', function (error) {
console.log("error: " + error);
cb(false, error);
});
});
req.write(receiptEnvelopeStr);
req.end();
}

Categories

Resources