NodeJS: Send HTTPS request but get HTTP - javascript

I am building a website using NodeJS, and I deploy it to Heroku. But when I open the website, something went wrong. Here is the problem:
Code:
In the main source file of my web:
app.get('/', (req, res) => {
var data = {
rootURL: `${req.protocol}://${req.get('Host')}`,
};
res.render('home.html', data);
});
Then, in home.html, I include the following script:
<script type="text/javascript">
$.getJSON('{{rootURL}}'+'/about', {}, function(data){
// Code here is deleted for now.
}).fail(function(evt) {
// Code here is deleted for now.
});
</script>
Here I use hbs template, so {{rootURL}} is equal to the 'rootURL' property within the 'data' object rendered along with the 'home.html' page.
The '/about' is one of the APIs I designed for my web. It basically sends back something about the website itself and this information is wrapped in JSON.
Then, here comes the problem. The code works fine locally, and works well when I send HTTP request instead of HTTPS to Heroku. But if I send HTTPS request to Heroku, I'll get 'Mixed Content' Errors:
Errors I get in Chrome Console.
I then switched to 'Elements' tab in the developers tool, and I saw this:
The schema is HTTP, not HTTPS!
I'm very confused here. I just grab the 'protocol' property within the 'req' object, and fill in the template with it. So, I'm assuming if I enter '[my-website-name].herokuapp.com' with 'https' schema in my Chrome Browser, my nodeJS app deployed on Heroku should get 'https' for req.protocol. But Apparently it's not the case. What is wrong here?

I assume you don't actually have an SSL certificate? Heroku will be providing the HTTPS, but it will then translate it to normal HTTP internally when it hits your express endpoint, which is why it sees req.protocol as HTTP.
Is there any point in even providing the URL to getJSON? Why not just send it $.getJSON('/about', callback) and let the browser handle that?
Also, you haven't hidden your URL in that first image you uploaded, if that's what you were intending.

Heroku router is doing SSL termination, so no matter if you connect via http or https, you get http on your side. Original protocol is however set in X-Forward-Proto header. You need use this value.

Related

I can't show the results of search in my movies library app doing by reactjs

I try to build a movies library with react js
I take the data from an API, and add Search component
when I type a text in the search bar I have an error,
no results appeared! and there is an error in the console!
isAxiosError.js:10 Mixed Content: The page at 'https://react-
japox3.stackblitz.io/' was loaded over
HTTPS, but requested an insecure XMLHttpRequest endpoint
'http://www.omdbapi.com/?
i=tt3896198&apikey=b0cdc816&s=g'. This request has been blocked; the content
must be served over
HTTPS.
isAxiosError.js:10 Uncaught (in promise) Error: Network Error
at e.exports (isAxiosError.js:10)
at XMLHttpRequest.l.onerror (isAxiosError.js:10)
can you help me to solve it?
this is the code and you can try it
https://stackblitz.com/edit/react-japox3?file=src%2FApp.js
Your problem is that your site is secure HTTPS whereas you are requesting from the omdbapi which is insecure HTTP
I would suggest you to use some secure API for the purpose over HTTPS.
Or you could do it without a API too.
Here is a module called moovies that might help.
With this you can setup a local api server just with one line of code.
const moovies = require('moovies')
const express = require('express')
const app = express()
app.use('/apipath', moovies.mooviesBackend)
app.listen(8000, () => {
console.log("Server is listening on port 8000");
})
You can also use the methods moovies.getPlot('tt3896198', callback) or moovies.getCast('tt3896198', callback) to get the same json responses directly from the code without any api.
The callback should be like:
function callback(response, error){
//do your stuff here
}
This library is being updated regularly and new features are getting added.
Disclosure: I am the developer of the Library.

Gatsby.js - proxy to express server

I want to setup proxy for my simple express server. I have added cors policy and everything works perfect when I call api like this:
fetch('http://localhost:3000/tasks')
But when i setup proxy in gatsby.config.js like this:
proxy: {
prefix: '/',
url: 'http://localhost:3000'
},
and call:
fetch('/tasks)
I'm getting this error:
Unhandled Rejection (SyntaxError): Unexpected token < in JSON at position 0
How to setup properly proxy in gatsby.js ??
I don't think you can use root as proxy. In gatsby develop, proxy is handled like this:
app.use(`${prefix}/*`, (req, res) => { ... }
So if prefix is set to /, it'll become //* which will not work. Even if it did work like /*, all routes from gatsby server will be redirect to proxy server because proxy has higher precedent than the rest of the routes, gatsby wouldn't have any chances to serve any pages at all.
prefix has to be a word started with a slash, i.e /api:
proxy: {
prefix: '/api',
url: 'http://localhost:3000'
},
Then you can use it:
fetch(`/api/tasks`)
This should go into a comment, but format is not good so i post as answer. I'm not sure what's the precise cause, but some idea to help you debug.
Chance are you received a HTML response with content-type header saying it's a JSON. Verify if this is the case by inspecting the network panel in browser devtools.
Make sure that request actually hit your express server. If 1. is true, then it's highly likely it didn't reach express server, the HTML comes from Gatsby's dev server.
If both points above are true, then perhaps debug the Gatsby source code to find out why it decide to handle the request instead of forward it. Derek Nguyen pointed out the location. It's also a express server so should be fine to you.

Mixed content jQuery ajax HTTPS request has been blocked on Laravel

I think this question will be easy for someone and will be a face-palm situation for me.
I have a Laravel 5.3 site, and various pages have ajax requests. Because I use the csrf_field() feature, they work fine.
But there is one page where the ajax produces this error:
Mixed Content: The page at 'https://example.com/fb/reports' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com/fb/json?levelType=&id=&aggLevel=ad&start=&end='. This request has been blocked; the content must be served over HTTPS.
My javascript looks like this:
var relUrl = '/fb/json/';
var payload = {
levelType: levelType,
id: id,
aggLevel: aggLevel,
start: start,
end: end
};
console.log(relUrl);
return $.ajax({
type: 'GET',
dataType: 'json',
data: payload,
url: relUrl,
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
I've read tons of articles about this error. I've tried tons of suggested solutions, including changing the relative URL to the full https URL, or starting it with 2 slashes.
I've even tried changing the way my Laravel routes work and am now using just querystring parameters.
I've studied all of the articles below (and more).
Also, since this one ajax query is in a password-protect part of the site (and the ajax queries that work are in a public/open part of the site), I figured maybe that was related to the problem. But then I used SSH to log into the production server and vim to temporarily remove the line that required any authentication, and the https error still happens.
What steps can I take to debug further from here? What logs can I 'tail' on my Cloudways server?
Is there anything that Cloudflare might be interfering with (which I doubt, since other ajax queries work, all on https)?
Thanks!
jQuery AJAX Request to HTTPS getting served to HTTP with Laravel and Select2
This request has been blocked; the content must be served over HTTPS
Mixed content issue - insecure XMLHttpRequest endpoint
XHR response blocked by Chrome, because of mixed content issue (http/https)
Forcing AJAX call to be HTTPS from HTTPS Page
MixedContent when I'm loading https page through ajax, but browser still thinks it's http
jQuery ajax won't make HTTPS requests
Laravel 5.1 ajax url parameter is url
Summary:
I needed to replace var relUrl = '/fb/json/'; with var relUrl = '/fb/json'; (remove the trailing slash) because that's what my Laravel web.php routes file expected.
In Chrome console, I noticed that the https XHR request was being "canceled" and replaced with an http request.
So then I used ssh to log into the remote production server and vim to temporarily disable the requirement of authentication.
Then in the Chrome console, I defined and ran a new ajax command using an absolute https URL with querystring params on the end. That worked (no mixed content error). Then I tried a relative URL like that, and it worked too.
Even a relative URL with no payload or querystring params or trailing slash worked.
Then I added the trailing slash again, and it didn't work.
I still wish there had been an easier way to trace or debug the redirect paths or whatever was happening. I still feel like I stumbled onto the answer clumsily (after many hours) instead of knowing how to dissect this problem reliably.
When changing from HTTP to HTTPS, it's possible to get the problem Mixed content issue - Content must be served as HTTPS.
So, first, modify APP_URL in the .env file, if we use the assets helper, this shouldn't give any problem with the URL.
APP_URL=https://url.net
Finally, add the following to the beginning of **api.php** or **web.php**:
if (App::environment('production')) {
URL::forceScheme('https');
}

No 'Access-Control-Allow-Origin' header present AngularJS

I am trying to build a quick demo site that I do not have control over the server I am trying to connect to. Here is the code that I am using to build it with AngularJS. I am running the file through a simple Python HTTP Server and viewing it at localhost:8000.
var retrieveAppliances = function () {
console.log('Attempting to retrieve appliance list.');
var requestUrl = '****';
$http({
method: 'GET',
url: requestUrl,
})
.then(function (response) {
console.log(response);
});
};
retrieveAppliances();
I have read multiple places to try switching the method to JSONP but doing so resulted in a parsing error.
While I have considered trying to build a server.js file and running NodeJS with it, I am unsuccessful in learning the basics of making an AJAX request and proxying that to my app.js.
I will greatly appreciate any help that someone may be able to give me, with clear and easy to follow steps.
If you're running an Ajax call to a different origin (e.g. different host, port or protocol) and the server at that origin does not have support for cross origin requests, then you cannot fix that from your client. There is nothing you can do from the client.
If the server supported JSONP, you could use that, but that also requires specific server support.
The only solutions from a browser web page are:
CORS support on the target server.
JSONP (also requires support on the target server).
Set up your own server that you do have access to (either on your existing page domain or with CORS) and then have that server get the file/data for you and proxy it back to you. You can either write your own proxy or deploy a pre-built proxy.
Find some existing third party proxy service that you can use.
If you're interested in making your own node.js proxy, you can see a simple example here: How to create a simple http proxy in node.js?.

Whitelist PDF Embed

Is there a way or a service that allows for read-only (no saving or downloading) PDF embeds on one domain only? I know that there are services like Scribd and Slideshare but the problem is that while they do have private options, no service as far as I can tell allows to whitelist embeds (eg, only allow embeds on certain domains.) Vimeo can do this with videos and I don't mind paying for this service either. Any ideas?
I've also looked into PDFJS and it seems they have a NodeJS implementation so I was thinking maybe PDFJS could grab the PDF from the server on the server side and just stream it to the client without exposing the original PDF url. However I couldn't find good documentation for PDFJS.
Any help would be greatly appreciated.
This can be achieved with any HTTP server, but since you mentioned Node in your question, we will solve the problem with that technology. I am assuming Express Framework as well.
First you simply host the PDF as a static file on your server. Then you would register some Middleware that detects a request for the PDF. If the hostname that is requesting does not match a list of "approved" domains, then you serve an error back to the client. If the domain is approved, you serve the PDF. This is no different then a .htaccess file in Apache that limits access by domain/IP or an "allow" block in a Nginx config. Here is a quick look at the Middleware function...
var approved = []; // Add your approved domains here.
// Make sure this middleware comes before app.use(express.static)
app.use(function(req, res, next){
if(req.url == '/path/to/PDF') {
if(approved.indexOf(req.headers.host) {
next();
} else {
next(new Error('Nu uh uh!'));
}
} else {
next();
}
});
This way even if they copy the embed code, they will get an error from the server (probably should be a 403, but those are semantics you can decide on yourself)

Categories

Resources