Why does the "request module" in Node.js accept only the URLs written with protocol? - node.js

I want to send a GET request using request module. Here's the code:
var requestModule = require('request');
var url = require('url');
var myUrl = 'www.google.com';
var myUrlObj = url.parse(myUrl);
requestModule(myUrl, myUrlObj , callback);
but it doesn't work because myUrlObj has a null value for its "protocol" attribute.
The same code works when:
var myUrl = 'http://www.google.com'
Why is it so rigid?
Also I tried doing the following to get around this problem:
if ( myUrlObj.protocol == null ) {
myUrl = "http://" + myUrl;
myUrlObj = url.parse(myUrl);
}
But some websites use https, while others use http. So, the above code fails for websites that use https, and the require module throws an exception.

If the URL comes from user input, default to http:// and let them enter a protocol for HTTPS. Encourage them to enter a protocol. Most HTTPS websites will redirect you from the HTTP url to the HTTPS URL. You can make the request module follow redirects using the example here.

Related

Redirect to url by nodejs

i tried to receive get request and redirect the user to another url
but the url not changing
const success_url = 'https://site.online/success'
const query = '?order_id=123123&data=abc'
res.status(301).redirect(`${success_url}${query}`);
// the output must be https://site.online/success?order_id=123123&data=abc
// but i get http://localhost:3000/success?order_id=123123&data=abc
also tried res.redirect(301, `${success_url}${query}`);
How i can change localhost:3000 to the domain of the target url
You want to use .redirect(code, url).
res.redirect(301, `${success_url}${query}`);

How to determine http vs https in nodejs / nextjs api handler

In order to properly build my urls in my xml sitemaps and rss feeds I want to determine if the webpage is currently served over http or https, so it also works locally in development.
export default function handler(req, res) {
const host = req.headers.host;
const proto = req.connection.encrypted ? "https" : "http";
//construct url for xml sitemaps
}
With above code however also on Vercel it still shows as being served over http. I would expect it to run as https. Is there a better way to figure out http vs https?
As Next.js api routes run behind a proxy which is offloading to http the protocol is http.
By changing the code to the following I was able to first check at what protocol the proxy runs.
const proto = req.headers["x-forwarded-proto"];
However this will break the thing in development where you are not running behind a proxy, or a different way of deploying the solution that might also not involve a proxy. To support both use cases I eventually ended up with the following code.
const proto =
req.headers["x-forwarded-proto"] || req.connection.encrypted
? "https"
: "http";
Whenever the x-forwarded-proto header is not present (undefined) we fall back to req.connection.encrypted to determine if we should serve on http vs https.
Now it works on localhost as well a Vercel deployment.
my solution:
export const getServerSideProps: GetServerSideProps = async (context: any) => {
// Fetch data from external API
const reqUrl = context.req.headers["referer"];
const url = new URL(reqUrl);
console.log('====================================');
console.log(url.protocol); // http
console.log('====================================');
// const res = await fetch(`${origin}/api/projets`)
// const data = await res.json()
// Pass data to the page via props
return { props: { data } }
}

How to pass a variable in an endpoint call in nodejs

I have a variable e.g. var merchanttoken = requestConfig.merchant_connect_token, how do I pass it when making an call to an endpoint e.g
request.get('http://pi.call/v2/{merchanttoken}/info, function)
I need to pass the variable in the url.
I recommend pass it as a POST request instead of GET. Because auth token is sensitive content.
Still if you prefer GET change URL format to this.
http://pi.call/v2/info?merchanttoken={merchanttoken}
You can access it at server side nodejs by
var url = require('url');
var url_parts = url.parse(request.url, true);
var merchanttoken = url_parts.merchanttoken;

How do you get RequireSSL in NodeJS on an Azure Website?

So a little background first: A NodeJS server running in an Azure Website will automatically have all HTTPS requests directed to the http endpoint. This allows the following code to work for both HTTP and HTTPS
var http = require('http');
var express = require('express');
var app = express();
// *snip*
http.createServer(app).listen(process.env.PORT);
// can go to http://*.azurewebsites.net or https://*.azurewebsites.net without issue
From here I decided to create a "RequireSSL" middleware
/* snip */
if (req.protocol === 'http') {
var origFullUrl: string = 'http://' + req.get('host') + req.originalUrl;
var u: url.Url = url.parse(origFullUrl, true);
u.host = null; // nead to clear so 'port' is used
u.protocol = 'https';
u.port = '443';
res.redirect(url.format(u));
}
/* snip */
Here's where the background comes into play. Because Azure redirects all HTTPS to the HTTP protocol the req.protocol always equals 'http' creating a redirect loop.
Anyone know of a way to get this to work in an Azure Website?
You can detect this using x-arr-ssl header.. Please go through this : https://coderead.wordpress.com/2014/09/05/redirecting-to-https-in-node-js-on-azure-websites/

Node.js request directly to URL with options (http or https)

I think I'm missing something about http and https requests
I have a variable that contains a URL, for example:
http(s)://website.com/a/b/file.html
I would like to know if there's a easy way to make a request to that URI to get the data
To make a http(s)Request, here's what I have to do now:
Test if the URL is http or https to make the appropriate request
Remove the http(s):// part and put the result in a variable (If I specify http or https in the hostname, I get an error)
Separate the hostname from the path: website.com and `/a/b/file.html
Put this variables in the options objects
Is this a must or are they easier solutions that don't involve getting out the hostname and path, and testing if the site is in http or https ?
Edit: I can't use http.get as I need to put some specific options
In order to get all components out of URL you need to parse it. Node v0.10.13 has stable module for it: url.parse
This is simple example how to do so:
var q = url.parse(urlStr, true);
var protocol = (q.protocol == "http") ? require('http') : require('https');
let options = {
path: q.pathname,
host: q.hostname,
port: q.port,
};
protocol.get(options, (res) => {...
For those ending up here, protocol includes :, and pathname does not include search so it must be added manually. Parameters shouldn't be parsed as they are not needed (so you can save computing time :)
Also it's not really a best practice to require inside a function and probably this code will end up inside a function so having all this improvements, so I would rewrite the answer to something like this:
import * as url from 'url';
import * as https from 'https';
import * as http from 'http';
const uri = url.parse(urlStr);
const { request } = uri.protocol === 'https:' ? https : http;
const opts = {
headers, // Should be defined somewhere...
method: 'GET',
hostname: uri.hostname,
port: uri.port,
path: `${uri.pathname}${uri.search}`,
protocol: uri.protocol,
};
const req = request(opts, (resp) => { ...

Resources