I'm just beginning to learn javascript and https requests. I'm working in Visual Studio 2017, I created a blank javascript console app from the template and added the following code.
const https = require('https');
const options = {
hostname: 'api.gdax.com',
path: '/products/BTC-USD/stats',
method: 'GET',
agent: false
};
const req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.end();
The response I get from the server is
{"message":"User-Agent header is required."}
When I navigate to https://api.gdax.com/products/BTC-USD/stats in my browser I get the correct response. How come I can't do the same in a javascript console?
That's because that specific API is blocking any request without the User-Agent header.
Just add the header, and it will work fine:
const https = require('https');
const options = {
hostname: 'api.gdax.com',
path: '/products/BTC-USD/stats',
method: 'GET',
agent: false,
headers: {
'User-Agent': 'something',
},
};
const req = https.request(options, res => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', d => {
process.stdout.write(d);
});
});
req.on('error', e => {
console.error(e);
});
req.end();
You need to set headers manually. See http documentation for all possible request options (this is the same for http and https).
try:
const options = {
hostname: 'api.gdax.com',
path: '/products/BTC-USD/stats',
method: 'GET',
agent: false,
headers: {
'User-Agent': 'Foo/1.0',
},
};
You need to explicitely set the User-Agent header in the headers property of your request options
const options = {
hostname: 'api.gdax.com',
path: '/products/BTC-USD/stats',
method: 'GET',
agent: false,
headers: { 'User-Agent': 'Mosaic/1.0' }
};
Related
I am trying to send a post request to a URL, I did this in python with the following code and it worked like a charm and I got a [Response <200>], but since I needed to use this in a website, I switched over to JS and tried to recreate the same functionality, but for some reason I'm getting a [Response <403>] even tho all my auth tokens and headers and everything is same as the python code.
Python Code -
url = "https://discord.com/api/v8/channels/801784356711956522/messages"
auth = ""
headers = {"Authorization": auth,
'Content-Type': 'application/json', 'referer': "https://discord.com/channels/801784356217421874/801784356711956522"}
payload = {'content': 'Test' , 'nounce': 802056256326991872, 'tts': False}
response = requests.post(url, data=json.dumps(payload), headers=headers)
print(response)
JavaScript Code -
onst url = "https://discord.com/api/v8/channels/801784356711956522/messages"
const auth = ""
const headers = {"Authorization": auth,
'Content-Type': 'application/json',
'referer': "https://discord.com/channels/801784356217421874/801784356711956522"}
const options = {
headers : headers,
}
const data = JSON.stringify({'content':"Test" , 'nounce': 802056256326991872, 'tts': false})
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = 0;
const req = https.request(options, (res) => {
console.log(`statusCode: ${res.statusCode}`)
res.on('data', (d) => {
process.stdout.write(d)
})
})
req.on('error', (error) => {
console.error(error)
})
req.write(data)
req.end()
In your python code, you made a POST request but in JavaScript code, you made a GET request because you did not provide the method option.
It is specified in https.request options documentation:
method A string specifying the HTTP request method. Default:
'GET'.
To make POST request modify like this
const options = {
headers : headers,
method: "POST"
}
Also, you need to add URL since you did not provide hostname and path in the options.
const req = https.request(url, options, (res) => {
// ...
})
const querystring = require('querystring');
const https = require('https');
var postData = querystring.stringify({
'msg' : 'Hello World!'
});
var options = {
hostname: 'domain.com',
port: 443,
path: '/yow-path',
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': postData.length
}
};
var req = https.request(options, (res) => {
console.log('statusCode:', res.statusCode);
console.log('headers:', res.headers);
res.on('data', (d) => {
process.stdout.write(d);
});
});
req.on('error', (e) => {
console.error(e);
});
req.write(postData);
req.end();
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)?
Below in this example, in the variable 'obj' i get body of response. How to get header values of response using this https node.js library?
var options = {
hostname: hostname,
port: port,
path: pathMethod,
method: method,
headers: {
'Content-Type': APPLICATION_JSON,
'Authorization': BEARER + localStorage.jwtToken
},
rejectUnauthorized: false,
agent: false,
requestCert: false
};
return new Promise(function(resolve, reject) {
var req = https.request(options, function(res) {
res.setEncoding(ENCODING_UTF8);
res.on('data', function(result) {
try {
const obj = JSON.parse(result);
resolve({ 'httpStatus': PAGE_STATUS_200, 'result': obj });
}
catch(error) {
console.error(error);
resolve(resolve({ 'httpStatus': PAGE_STATUS_500 }));
}
});
res.on('end', () => {
console.log('No more data in response.');
});
});
req.on('error', function(err) {
console.log(`problem with request: ${err.message}`);
reject(err);
});
if (postData) {
req.write(postData);
}
req.end();
});
In my browser i get all necessary headers. What could be the problem that i can not get headers with https node.js lib?
You can get the headers in https module.
This is how you get the headers for the response.
res.headers
I have updated your code in example below:
var req = https.request(options, function(res) {
res.setEncoding(ENCODING_UTF8);
res.on('data', function(result) {
console.log("Headers: ", res.headers);
// Your code here.
});
res.on('end', () => {
// Do something here.
});
});
Hope this helps.
The response headers should be available in the res.headers object, e.g.
// Log headers
console.log('Headers: ', res.headers);
See: https://nodejs.org/api/https.html
e.g.
const https = require ('https');
// This will return the IP address of the client
var request = https.request({ hostname: "httpbin.org", path: "/ip" }, (res) => {
console.log('Headers: ', res.headers);
res.on('data', (d) => {
console.log('/ip response: ', d.toString());
});
});
// Also try using Request library
var request = require('request');
var options = {
url: "https://httpbin.org/ip",
method: "get"
};
console.log('Requesting IP..');
request(options, function (error, response, body) {
if (error) {
console.error('error:', error);
} else {
console.log('Response: Headers:', response && response.headers);
}
});
I have this function and the below data which is passed into this function returns a ECONNRESET, socket hang up error. However, when the discountCode array is reduced to like only 10 objects, it can POST without any problem.
What could the cause for this problem? I tried to do multiple req.write() by segmenting the data in Buffer, however that doesn't work out well. Any NodeJs ninja could give some insights to this problem?
createObj: function(data, address, port, callback) {
//console.log('Create Reward: '+JSON.stringify(data));
var post_data = JSON.stringify(data);
var pathName = '/me/api/v1/yyy/'+data.idBusinessClient+'/newObj';
//
var options = {
hostname: address,
port: port,
path: pathName,
method: 'POST',
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Accept': 'application/json',
'Accept-Encoding': 'gzip,deflate,sdch',
'Accept-Language': 'en-US,en;q=0.8'
}
};
// http call to REST API server
var req = restHttp.request(options, function(res) {
console.log('HTTP API server PUT Reward response received.');
var resData = '';
res.on('data', function(replyData) {
// Check reply data for error.
console.log(replyData.toString('utf8'));
if(replyData !== 'undefined')
resData += replyData;
});
res.on('end', function() {
//<TODO>Process the data</TODO>
callback(JSON.parse(resData));
});
});
req.write(post_data);
req.end();
console.log('write end');
req.on('close', function() {
console.log('connection closed!');
});
req.on('error', function(err) {
console.log('http request error : '+err);
callback({'error':err});
throw err;
});
req.on('socket', function(socket) {
console.log('socket size:'+socket.bufferSize);
socket.on('data', function(data) {
console.log('socket data:'+data);
});
});
}
]}`
I had the same problem and was able to resolve it by adding a Content-Length header:
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Content-Length': Buffer.byteLength(post_data),
'Accept': 'application/json',
'Accept-Encoding': 'gzip,deflate,sdch',
'Accept-Language': 'en-US,en;q=0.8'
}
However, I still have no clear idea why a missing Content-Length header causes such a trouble. I assume it's some kind of weirdness in the internal Node.js code. Maybe you can even call it a bug, but I'm not sure about that ;)
PS: I'm absolutely interested more information about the cause of this problem. So please leave a comment if you have any idea...
When you change the content of response for sure you need also to update on header the content length:
headers: {
...
'Content-Length': Buffer.byteLength(post_data),
...
}
But i run on this problem also when i try to make multiple request and seems that this is not well managed on different library so a workaround that i have found if this problem persist is to add on headers:
headers: {
...
connection: 'Close'
...
}
So if you are making request on different servers.. this close the connection after finish the process. This worked for me in net, node-http-proxy.
If Express and http-proxy-middleware is used to make the POST call, and some body parser middleware is used like express.json(), the request interceptor fixRequestBody must be used (more info). Otherwise the POST call will hang with the ECONNRESET error.
const express = require('express');
const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware');
const app = express();
app.use(express.json());
app.post(
'/path',
createProxyMiddleware('/path', {
target: API_URL,
changeOrigin: true,
pathRewrite: (path, req) => `/something/${req?.body?.someParameter}`,
onProxyReq: fixRequestBody // <- Add this line
});
Had the same problem. The solution for me was to append it to the proxy for it to work. If you're not using a proxy, you can probably just append it to the post request itself.
With proxy:
import express from 'express';
import { createProxyMiddleware } from 'http-proxy-middleware';
import logger from './logger';
// setup routes
server.get('/isAlive', (req, res) => res.send('Alive'));
server.get('/isReady', (req, res) => res.send('Ready'));
server.use(express.static(path.join(__dirname, '../build')));
const restream = (proxyReq, req, res, options) => {
if (req.body) {
let bodyData = JSON.stringify(req.body);
proxyReq.setHeader('Content-Type', 'application/json');
proxyReq.setHeader('Content-Length', Buffer.byteLength(bodyData));
proxyReq.write(bodyData);
}
};
server.use(
'/api',
createProxyMiddleware({
target: 'http://your-backendUrl-api',
onProxyReq: restream,
changeOrigin: true,
proxyTimeout: 30000,
secure: true,
logLevel: 'info',
onError: (err, req, res) => {
logger.error('error in proxy', err, req, res);
},
})
);
E.g without proxy:
import axios, { AxiosResponse } from 'axios';
const api = axios.create({
baseURL: '/api/....',
timeout: 35000,
withCredentials: true,
headers: { Pragma: 'no-cache', 'Cache-Control': 'no-cache' },
validateStatus: (status) => status < 400,
});
const response = await api.post(
`/somepath/${exampleInjectedId}/somepathToRestAPI`,
{
...payload
},
{
baseURL: '/api/...',
timeout: 35000,
withCredentials: true,
headers: {
Pragma: 'no-cache',
'Cache-Control': 'no-cache',
'Content-Length': Buffer.byteLength(
JSON.stringify({
...payload
})
),
},
validateStatus: (status) => status < 400,
}
);
I am trying to write a basic REST Post client to work with node.js and because of the REST API I have to work with I have to get details from the responses including cookies to maintain the state of my REST session with the server. My Question is what is the best way to pull the json objects from the response when res.on triggers with all the data in the PRINTME variable and return it to the test.js console.log().
test.js file
var rest = require('./rest');
rest.request('http','google.com','/upload','data\n');
console.log('PRINTME='JSON.stringify(res.PRINTME));
rest.js module
exports.request = function (protocol, host, path, data, cookie){
var protocalTypes = {
http: {
module: require('http')
, port: '80'
}
, https: {
module: require('https')
, port: '443'
}
};
var protocolModule = protocalTypes[protocol].module;
var options = {
host: host,
port: protocalTypes[protocol].port,
path: path,
method: 'POST',
headers: {
'Content-Type': 'text/xml'
, 'Content-Length': Buffer.byteLength(data)
, 'Cookie': cookie||''
}
};
console.log('cookies sent= '+options.headers.Cookie)
var req = protocolModule.request(options, function(res) {
var PRINTME = res;
console.log('STATUS: ' + res.statusCode);
console.log('HEADERS: ' + JSON.stringify(res.headers));
res.setEncoding('utf8');
res.on('data', function (chunk) {
PRINTME.body = chunk;
console.log('BODY: ' + chunk);
});
res.on('close', function () {res.emit('end')});
});
req.on('error', function(e) {
console.error('Request Failure: ' + e.message);
});
req.write(data);
req.end();
};
Using a package like request will help you simplify your code.
The following would be rest.js
var request = require('request');
module.exports = function(protocol, host, path, data, cookie, done) {
var options = {
host: host,
port: protocalTypes[protocol].port,
path: path,
method: 'POST',
headers: {
'Content-Type': 'text/xml',
'Content-Length': Buffer.byteLength(data)
},
jar: true
};
request(options, function(err, resp, body) {
if (err) return done(err);
// call done, with first value being null to specify no errors occured
return done(null, resp, body);
});
}
Setting jar to true will remember cookies for future use.
See this link for more information on the available options
https://github.com/mikeal/request#requestoptions-callback
To use this function in another file
var rest = require('./rest');
rest(... , function(err, resp, body){
...
});