Express + React + Heroku can't find a file - node.js

i want to get my app working on Heroku, But there is on problem. Heroku server can't find the images. On developmnt everything is working correctly. Images are loaded propertly. On heroku everything works correctly. Asking for json /api/articles gives in result json. Router also working. But images gives not found. In tag and fetch() .
code => https://github.com/bartek-fecko/cinema-app
The image file exists on heroku(i looked to the bash on heroku.com)
var express = require('express');
var indexRouter = require('./routes/index');
var usersRouter = require('./routes/users');
var app = express();
app.use(logger('dev'));
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, '../client/build')));
app.use('/api', indexRouter);
app.use('/api/users', usersRouter);
app.use(express.static(path.join(__dirname, '/assets/images')));//i'm sending a file
app.get('/images/:fileName', (req, res) => {
res.sendFile(path.join(__dirname, `/assets/images/${req.params.fileName}`)); //here also i'm sending a file
});
app.get('/*', (req, res) => {
res.sendFile(path.join(__dirname, '../client/build/index.html'));
});
module.exports = app;
<P.Wrapper>
<img src="spider-man-far-from-home.jpg" alt="no img"/>
<img src="/images/spider-man-far-from-home.jpg" alt="no img"/>
</P.Wrapper>
I'm getting a 404 error. And I tried everything and it doesn't work. The same for fetching fetch('/images/ ...') and so on.

From your code, you are having 2 servers:
Backend server (inside src)
Frontend server (inside client)
Since when you are starting them, they are of different servers, meaning that they either would be running on different IPs or the same IP but different Ports.
This means that your fetch of the image in the client's App.tsx would most likely be referencing the wrong host.
fetch('/images/spider-man-far-from-home.jpg')
Try using a full URL with both Host and Port in the fetch method and see if it works for you.

Yeah. woow. It's working now. The problem was exactly like Yee Hui Poh said. So in production i have to fetch to locallhost:8080/images/spider-man-far-from-home.jpg
where 8080 is backend server.

Related

how to redirect large file requests through node.js to a different server using request

I have a node.js server that is forwarding API requests through to another server on a different port (so that auth cookies and the like make it across), and this has all worked great until the client has needed to upload a large file (> 100mb).
When I try to do that, if the file is over ~30mb the request never even reaches the far server (which will happily accept large files when connected to directly), so I'm pretty sure it's dying in node ... somewhere.
"use strict";
const http = require("http");
const port = process.env.FRONTEND_PORT || 13370;
const path = require("path");
const request = require("request");
const express = require("express");
const app = express();
const staticPath = path.join(__dirname, "/dist/");
app.set("port", port);
// Attempt to set some ridiculously high limits on things
app.use(express.urlencoded({parameterLimit: 1000000, limit: '10gb', extended: true}));
app.use(express.json({limit: '10gb'}));
// Serve files from this location
app.use(express.static(staticPath));
app.use(
'/api',
(req, res) =>
{
var url = "https://localhost:12121/api" + req.url;
req.pipe(request(url)).pipe(res);
console.log(res.statusCode);
console.log(res.statusMessage);
});
// If we hit any path that doesn't exist, instead serve up index.html and let react router handle it
app.get("*", (req, res) => { res.sendFile(path.join(__dirname, "/dist/index.html")); });
app.listen(app.get("port"), () => { console.log("listening"); });
As you can see, I've tried bumping up the limits (based on other SO answers I've seen) using:
app.use(express.urlencoded({parameterLimit: 1000000, limit: '10gb', extended: true}));
app.use(express.json({limit: '10gb'}));
...but this doesn't seem to be helping me in this case. I'm sure I'm missing something obvious, but I am extremely new to node.js (and, honestly, web development in general).
(It's also worth noting, the file is being sent through a basic XMLHttpRequest as POST, sending a File object through - nothing fancy going on there)

bodyParser middleware not working when adding static route

I'm a newbie on express, and when I was creating a simple server demo I detected that POST requests were not sent. After doing some experiments I discovered that it was the express.static middleware, that somehow was interfering. I supposed it was a common error, but didn't manage to find a clue. My code is the following:
//jshint esversion:6
import express from "express";
import path from "path";
import { fileURLToPath } from "url";
import bodyParser from "body-parser";
import https from "https";
/* jshint ignore:start */
const __filename = fileURLToPath(import.meta.url);
/* jshint ignore:end */
const __dirname = path.dirname(__filename);
const app = express();
const port = 8080;
app.use(express.static(__dirname + "/public"));
app.use("/", bodyParser.urlencoded({ extended: true }));
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.post("/", function (req, res) {
let name = req.body.name;
let email = req.body.email;
let message = req.body.message;
res.send("POST request to the homepage");
console.log(req.body);
});
app.listen(port, () => console.log(`Listening on port ${port}!`));
I'll gladly appreciate any answer or commet :)
EDIT: Apparently this error doesn't occur on Firefox, but does on Chrome and Edge
Based on your symptoms of the POST not even being sent from the client when you added the express.static(), I would guess that when you go to the / route in your browser, that express.static() was picking up an index.html from your public directory rather than the index.html that you wanted from here:
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
You can fix that two ways. Either move this app.get("/", ...) route before the express.static() route or tell the express.static route to NOT serve index.html like this:
// set up static file handling, but don't serve index.html for the / request
app.use(express.static(__dirname + "/public", {index: false}));
Ok figured out what was really blocking this.
When adding express.static() it loaded the JS for the front-end, which has the following line:
$(".sendMessageBtn").attr("disabled", "true");
which disables the submit button. Turns out disabling it also means it can't send anything BUT only on chromium browsers. This does not happen on Firefox.
To disable it without causing this mess, you can replace with:
$(".sendMessageBtn").css("pointer-events", "none");
Instead of disabling it through HTML, it uses CSS
So the way express static file serving works is that you put a /path which you want to serve on, and the term express.static(/path/to/static/folder) which will be published to the api.
Otherwise your entire application will be static, due to the fact that everything start with /.
See the docs for more info.
In your case:
app.use("/your-static-endpoint", express.static(__dirname + "/public"));
One more thing about your code. Stuff like static serving, error handling, body parsing are called middlewares, so if you want to apply them through the application, you shouldn't specify a path, because it might interfere with how express handles routing.

No content in <app-root> element in browser using the command "node app.js"

I created an Angular 7 application using the Angular CLI. I added my express server as one knows it. Afterwards I used the command "node server/app.js to start my app, but then in the browser in the "Elements" section there appears <app-root></app-root> without any content. As if the browser knew nothing about the actual Angular application. And when I run the ng serve command it seems to know about the actual Angular application, but there appears a 404 not found error in terms of post and get requests to the data server.
I already had a working Angular4 application with -I guess- the same setup and now same things seem to not work any longer.
I researched all day long to find the solution but for nothing.
I think it is not advantageous to post all my files in here. Comment if I was wrong and I am going to edit them.
Thanks in advance.
My app.js:
"use strict";
var bodyParser = require('body-parser');
const cors = require('cors');
// import { Observable } from 'rxjs';
var express = require("express");
var path = require("path");
var app = express();
app.use(cors());
const router = express.Router();
var nodeModulesPath = path.join(__dirname, "..", "node_modules");
app.use("/node_modules", express.static(nodeModulesPath));
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
var serverPath = path.join(__dirname);
app.use("/server", express.static(serverPath));
// app.use(bodyParser.json());
var models = require("./models");
models.sequelize.sync({force:true}).then(function() {
console.log("TABELLE ERSTELLT");
// app.use(cors());
app.use("/", router);
app.use(bodyParser
.urlencoded({extended:true})
);
app.use(bodyParser.json());
console.log("after bodyparser");
app.get("/", function(req,res){
res.sendFile(path.join(__dirname, "views", "index.html"));
});
// app.get('/*', function(req, res) {
// res.sendFile(path.join(__dirname, "views", "index.html"));
// });
app.post("/goals/create",function (req, res){
models.Goal.create({
id: req.body.id,
name: req.body.name,
content: req.body.content,
firstGivenValue: req.body.firstGivenValue,
fittingValue: req.body.fittingValue,
someone_would_like_to_implement: req.body.someone_would_like_to_implement,
i_know_how_to_implement_it: req.body.i_know_how_to_implement_it
}).then(function(obj){
console.log(obj.id);
// res.end("erfolgreich");
res.redirect("/");
})
console.log(req.body);
});
app.get("/test",(req, res) => {
res.end("test erfolgreich");
});
app.listen(3000);
});
You mention that you think it used to work for angular 4. Currently you're serving the index.html from the src folder. That's not going to work, your app is a typescript app and will need to be compiled one way or another; not to mention the Angular compiler. In the early days (I think pre 4, but not sure) angular serve also write the served files in a folder in your project, so you could just pick those JIT compiled files up and toss them on a web server, or express server. Those days are gone (with good reason for that matter, mostly performance).
You will now have to create an explicit build (ng build) and tell your express server (app.js) to target your dist folder.
TL;DR:
Run ng build
Replace
var srcPath = path.join(__dirname, "..", "src");
app.use("/src", express.static(srcPath));
With:
var distPath = path.join(__dirname, "..", "dist");
app.use("/dist", express.static(distPath));

React App giving 404 on main js and css

I built a react app using "react-scripts". The application runs perfectly on my local development server but when I deploy to my actual server the applications seems to not find the main JS and CSS files being compiled. I get 404 on both.
Following is the information that might help.
The files on the server are located at
ads/build/static/js and ads/build/static/css || respectively
The 404s I am getting are on the following files:
https://www.example.com/ads/build/static/css/main.41938fe2.css
https://www.example.com/ads/build/static/js/main.74995495.js
Here is how my server is configured:
const express = require('express');
const path = require('path');
const app = express();
const favicon = require('serve-favicon');
//favicon
app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.get('/ads', function (req, res) {
app.use(express.static(path.join(__dirname, 'build/static')));
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
app.listen(9000);
In my package.json I have also included the homepage parameter as:
"homepage" : "https://www.example.com/ads
UPDATE
When I run the app on the server itself with the following path:
dedicated-server-host:9000/static/js/main.74995495.js that renders the JS file correctly
Is there some configuration that I am missing, the routing doesn't seem to be working. Please advise.
Use some indentation so you will see error like this:
app.get('/ads', function (req, res) {
app.use(express.static(path.join(__dirname, 'build/static')));
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
You are setting the static route inside of the /ads handler, will add a new express.static route handler on every GET /ads request.
This will set the static route on server startup:
app.use(express.static(path.join(__dirname, 'build/static')));
app.get('/ads', function (req, res) {
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
or:
app.get('/ads', function (req, res) {
console.log(path.join(__dirname, 'build'));
res.sendFile(path.join(__dirname, '/build/index.html'));
});
app.use(express.static(path.join(__dirname, 'build/static')));
But make sure that you get the path right - for example you may need:
app.use('/ads/build/static', express.static(path.join(__dirname, 'build/static')));
if you want the URL in your question to work.
To make it much simpler, you could use just this single handler to make express.static handle both the css/js and index.html at the same time:
app.use('/ads', express.static(path.join(__dirname, 'build')));
and change your index.html to use:
https://www.example.com/ads/static/css/main.41938fe2.css
https://www.example.com/ads/static/js/main.74995495.js
instead of:
https://www.example.com/ads/build/static/css/main.41938fe2.css
https://www.example.com/ads/build/static/js/main.74995495.js
Sometimes getting your paths structure right in the first place can make your route handlers much easier.

Angular2 application with NodeJS not loading everything

I'm experimenting with Angular2 and, with the quick start guide on their official documentation, I'm definitely up and running. However, if I want to do any APIs on the server or host it on the cloud it seems I'll need to use Node. I think I have everything set correctly in the server.js file, yet when I run it it seems like it's not loading everything from SystemJS and I get the following errors:
Here is the Node code:
var express = require("express");
var bodyParser = require("body-parser");
var app = express();
var System = require('systemjs');
// loads './app.js' from the current directory
System.import('app').then(function(m) {
console.log(m);
});
// Config
app.set('port', (process.env.PORT || 3000));
app.use('/app', express.static(__dirname + '/app'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.listen(app.get('port'), function() {
console.log('MEAN app listening on port ' + app.get('port'));
});
app.get('*', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
I'm not sure what I'm missing to include in the Node side that gets included when running lite-server from npm start that is included from the Angular2 quick start guide.
When you are telling express where to look for the static files, you have to include where your js files will be as well.
For example, in one of my projects I have it like so
app.use('/css', express.static(path.resolve(appPath, 'css')));
app.use('/lib/css', express.static(path.resolve(appPath + '/lib', 'css')));
app.use('/lib/js', express.static(path.resolve(appPath + '/lib', 'js')));
app.use('/assets', express.static(path.resolve(appPath, 'assets')));
app.use('/node_modules', express.static(path.resolve(appPath, 'node_modules')));
app.use('/app', express.static(path.resolve(appPath, 'app')));
I believe that might be your issue or hopefully set you in the right path.

Resources