In my client side javascript, I request private content if the user is authorised (using firebase auth) as per below:
firebase.auth().onAuthStateChanged(user => {
if (!user) {
ui.start("#firebaseui-auth-container", uiConfig);
}
if (user) {
import("/private.js").then(module => {
console.log(module.default);
});
}
});
All users are served index.html from the public firebase hosting URL, but only when a user has been authorised do they request the private content. My firebase.json redirects to handle this:
"rewrites": [
{
"source": "**",
"function": "app"
}
]
I am struggling to set up a firebase functions based express backend to serve the javascript. (I haven't added auth checking yet because I want to get it working simply serving the js first).
My firebase function looks like this:
const fs = require("fs");
const functions = require("firebase-functions");
const express = require("express");
const app = express();
app.get("/private.js", (req, res) => {
fs.readFile("private.js", "utf8", function (err, data) {
if (err) throw err;
res.send(data)
});
});
exports.app = functions.https.onRequest(app);
However, when a user gets authorised and the client tries to dynamically import private.js I get the following error: Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec. How do I properly set the MIME type to serve js files?
You need to tell the browser that an error occurred, so that it does not try to parse the response as JavaScript. You can do that by sending a status code starting with 4 (client error) or 5 (server error). Here is an example:
app.get("/private.js", (req, res) => {
fs.readFile("private.js", "utf8", function (err, data) {
if (err) {
res.status(403).send('Could not load the data.');
} else {
res.send(data);
}
});
});
I worked it out. I need to use:
res.setHeader("Content-Type", "text/javascript"); //Solution!
res.writeHead(200);
res.end(data);
And it works fine.
Try this
res.type('.js');
res.send(data);
Related
I'm trying to use axios to receive data from my backend to my front end so that my webpage can display the data but my axios does not even seem to even run the axios.get code.
const baseUrl = "http://localhost:8081"
axios.get(`${baseUrl}/travels`)
.then((response) => {
const listing = response.data;
console.log(response.data)
})
That's my front end. There was no console.log or anything
app.get('/travels', function (req, res) {
listings.getListings(function (err, result) {
if (err) {
res.status = 500;
res.send(null);
} else {
res.status(200);
res.send(result);
}
});
});
Here's my backend
Possibly it is a cors problem within your webserver since you are accessing a URL from a completely different project.
Install the following:
> npm install cors -S
Then in your express code put this:
...
const cors = require('cors');
app.use(cors())
...
With this you are allowing your webserver to serve the resources to any project outside of itself.
Note: put this code in your backend.
I've got a nodejs web project running with express-js and ejs. After making it, it appered to me that it can be host throught static html files on Netlify instead of an nodejs app on Heroku. Indeed, the data only change each month so I only have to build it once a month. Like that, it will be the best hosting option regarding the price.
Is there a way (npm package, GitHub action, ...) to compile an entire express server + ejs application into a folder of static html/css files in order to be hosted on Netlify ?
I've been looking for a while and I couldn't find anything solving my problem.
Thanks for your help.
You can loop through all of the routes, and execute app.render for each of them, then store results in a file.
Sample code:
//express server should be started before this
const fs = require('fs')
['/', '/about', '/contact'].forEach( path => {
app.render(path, {
// optional metadata here
}, (err, res) =>{
if (err)
console.log('Error rendering ' + path, err)
else {
fs.writeFile(__dirname + '/public/' + path + '.html', res, function(err, res) {
if (err)
console.log('error saving html file', path, err)
})
}
})
})
I am trying to create a web app with some drop down menus that contain data from a sql server database. After some searching I figured out how to use node.js to output the table data into the command prompt.
var sql = require('mssql/msnodesqlv8');
var config = {
connectionString: 'Driver=SQL Server;Server=NAME\\SQLEXPRESS;Database=master;Trusted_Connection=true;'
};
sql.connect(config, err => {
new sql.Request().query('SELECT * FROM TABLE', (err, result) => {
console.log("Works");
if(err) { // SQL error, but connection OK.
console.log(" Error: "+ err);
} else { // All good.
console.dir(result);
};
});
});
sql.on('error', err => { // Connection bad.
console.log("Bad");
console.log(" Error: "+ err);
});
Now the problem is I don't know how to get that result into JSON data that can be used in my web app. Any help would be appreciated as I am quite new to node.js. Thanks!
EDIT:
Thanks for the help so far! I added the following code for when there is no error:
var express = require('express')
var app = express()
JSON.stringify(result);
console.log(JSON.stringify(result));
app.get('/', function (req, res) {
res.send(result)
})
I also have all of the code for the http server but I don't think it's necessary to show it all. Is this all that is needed on the server side?
First of all, to send data from the server to the client you'll have to run an HTTP server as part of your Node backend. Then, once the web app loads, it should make a request to your server, which as a response will return the data from the database. For more information on how to do this check out Express (for the server side) and Fetch API (for the client side).
I am attempting to create a basic webserver with Node.JS, but running into an issue with properly serving images.
var server = http.createServer(function (request, response){
if(request.url === '/') {
fs.readFile('public/index.html', 'utf8', function(errors, contents){
response.write(contents);
response.end();
});
} else {
fs.readFile("public" + request.url, 'utf8', function(errors, contents){
if (!errors) {
response.end(contents);
} else {
console.log('Failed to read file: /public' + request.url);
response.writeHead(404);
response.end();
}
});
}
});
Everything works fine, apart from if you go to view the image it attempts to download it (which I believe is corrupted - cant open it), which is not what I want, I wish for the images to be served properly in the browser (not via a tag)
Bonus points: I need to be able to correctly give the proper headers (Do I need just a switch statement and set them via that?), as chrome is giving off warnings
Resource interpreted as Stylesheet but transferred with MIME type text/plain: "http://localhost/css.css".
You can use expressjs : http://expressjs.com/
const express = require('express')
const app = express()
app.get('/', (req, res) => res.sendFile('public/index.html'))
app.use(express.static('public'))
app.listen(8080, () => console.log('Example app listening on port 8080!'))
NB :
Your code is unsafe : "public" + request.url. Your users can get all files of your server : fs.readFileSync("public/../../../README.txt");
You will get error on parent folder.
Error: ENOENT: no such file or directory, open 'C:\README.txt'.
Trying to get auth0 working with my electron app. When I follow the default tutorial and try to authenticate with Username-Password-Authentication, the lock fails with a 403 error and responds with "Origin file:// is not allowed".
I've also added "file://*" to the Allowed Origins (CORS) section of my client settings in the auth0 dashboard.
Auth0 Lock with console errors
Origin file:// is not allowed
EDIT:
Lock setup in electron
var lock = new Auth0Lock(
'McQ0ls5GmkJRC1slHwNQ0585MJknnK0L',
'lpsd.auth0.com', {
auth: {
redirect: false,
sso: false
}
});
document.getElementById('pill_login').addEventListener('click', function (e) {
e.preventDefault();
lock.show();
})
I was able to get Auth0 to work by using an internal express server in my electron app to handle serving pages.
First I created a basic express app in a separate folder in my project called http, here will be the express server code and html files to serve.
const path = require('path');
const express = require('express');
const app = express();
app.use(express.static(process.env.P_DIR)); // Serve static files from the Parent Directory (Passed when child proccess is spawned).
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:<PORT>'); // Set this header to allow redirection from localhost to auth0
next();
})
// Default page to serve electron app
app.get('/index', (req, res) => {
res.sendFile(__dirname + '/index.html');
})
// Callback for Auth0
app.get('/auth/callback', (req, res) => {
res.redirect('/index');
})
// Listen on some port
app.listen(<SOME_PORT>, (err) => {
if (err) console.log(err);
console.log('HTTP Server running on ...');
});
Then in the Electron main process, I spawn the express server as a child process
const {spawn} = require('child_process');
const http = spawn('node', ['./dist/http/page-server.js'], {
env: {
P_DIR: __dirname // Pass the current dir to the child process as an env variable, this is for serving static files in the project
}
});
// Log standard output
http.stdout.on('data', (data) => {
console.log(data.toString());
})
// Log errors
http.stderr.on('data', (data) => {
console.log(data.toString());
})
Now the auth0 lock authenticates as expected.