I have a Linux webserver using node which hosts a directory containing a static index.html file. I am wondering how I can make it so a user getting to the correct URL does not rely upon case sensitivity.
Currently, server.com/caa/ points to something different than server.com/CAA/ -- the directory holding index.html is lowercase "caa"
Have you tried adding some middleware that coverts all urls to lower case? Heres an example of one way of doing this
app.use(function(req, res, next) {
req.url = req.url.toLowerCase();
next()
});
Related
I have a nuxt-app, where I have a lot of posts. I recently refactored the project and I won't generate all posts anymore, as it is just taking too much time to do that.
Instead I have a page where I would fetch the matching post content via url query:
www.mypage.com/posts/?post=my-post-slug
Because the content is lying in static json files, for example in:
/static/data/posts/my-post-slug.json
/static/data/posts/my-post-slug_2.json
/static/data/posts/my-post-slug_3.json
/static/data/posts/my-post-slug_n.json
I read the post https://github.com/nuxt/nuxt.js/issues/123
about how to load json in the best way.
I decided to do something like this in the fetch() hook:
// ... simplified code
async fetch() {
let postSlug = this.$route.query.post
const post = this.$axios
.get(`/posts/posts.de.${postSlug}.json`)
.then((data) => {
return data?.data
})
.catch((error) => {
console.error('error: ', error)
const code = parseInt(error.response && error.response.status)
if (code === 404) {
this.$nuxt.error({ statusCode: 404, message: 'Post not found' })
}
})
this.activePost = post?.items?.[0] || false
}
As already said, I do not generate the actual posts, but I generate all post urls in my sitemap.xml.
When running the generate in analyze mode I have now a huuuuge bundle size (app.js), and I can't understand why...
-> Check out the attached image. (Note: app.js has a ridiculous size of 34MB!!!!😕)
I don't understand why all my post jsons appear in the static and the dist part of the bundle???
I don't understand at all why they appear in there. I want them to just lie in the static folder, but not be included in the app bundle.
(you can see that there are files like events.bundle.de.json included. I need those to fetch a list of all posts for example. I do that also within my fetch hook only.
I would be very happy if somebody could point out why those files are included (twice)!
Those files are not included "twice". You need them, so you do have them locally in your static folder.
Meanwhile, you should probably put them inside of your src directory if you don't want/need to have them exposed publicly and benefit from code-splitting thanks to Webpack as explained in the post you've linked (which is still valid even if it's a 2017 one!).
Here, since you're making an axios call and using target: 'static', it will bundle your whole thing to work even without JS and it does that ahead of time. So, in order to have all the possibilities, it includes all in the final bundle I think.
If you want to only load what is needed while not shipping a big static directory, you should import them dynamically. You can use a dynamic import: load only the needed JSON by passing the actual postSlug.
PS: style-wise, prefer using async/await (.then is deprecated) and maybe also $axios.$get.
Although I think #kissu s answer is answering my question in the title, it was not the solution for my problem. For the sake of completeness I will post what I found out after long and many hours of debugging. I still don't quite understand why this even happened, but maybe someone could comment on that as well:
In my nuxt-project I am using a utility file getData.js of which I import a function getDataServer into one of my vuex store modules.
// vuex store module: store/data.js
import { getPreviewData } from '~/api/getData'
The code looks like this:
// getData.js
// Get static JSON file (e.g. basic.de.json or posts.de.1.json)
export function getDataServer(fileProps) {
return require(`~/${fileProps.path}${fileProps.name}.${fileProps.lang}${
fileProps.page ? `.${fileProps.page}` : ''
}.json`)
}
Only by importing and not even by executing that function webpack would bundle EVERY .json file it can find in my root folder into my app.js.
That is why I had a dist folder appearing in my bundle, if not deleted. (The point I talk about in my original question, where I have things included twice).
I even created additional folders and .json files to see, and they were all bundled no matter what.
Only after removing the getData.js from my project my bundle became clean.
I understand that with the require command, webpack cannot tree-shake things, so I would have expected that some code-splitting features would not work, but what I did not expect was that this bit of code would automatically get every .json in my folder...
Does anyone know why importing that function would execute it in a way that acts as a wildcard for all .jsons?
To me it still does not make any sense.
Thanks and cheers.
See, I was training with Node (and TS btw), and tried to do a trivial server with multiple request/response options. But I have a problem I don't know how to solve without using Express (at least for now I don't want to use it).
I have a HTML file which requests an image file. While in the IDE, everything looks like it's going to work, but when the server is running, the image cannot be found. It's kind of obvious why: The HTML makes a request the server doesn't know how to handle. Thing is, I thought the document could refer to other files without the need of talking to the server.
What is an elegant and working solution for my problem?
Thanks in advance.
import * as http from 'http'
import * as fs from 'fs'
fs.readFile('doc/kmCNHkq.jpg', function (err, data) {
let binaryimg = new Buffer(data).toString('base64');
if (err) throw err;
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'image/jpeg'});
res.end(data);
console.log("Delivered the jpeg");
}).listen(8000);
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end(binaryimg);
console.log("Delivered base64 string");
}).listen(8124);
console.log("Unless bug, both servers are listening");
});
fs.readFile('doc/index.html', function(err, data) {
http.createServer(function(req,res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(data)
}).listen(80);
console.log("HTML server is running")
})
(main.ts; Targets ES6)
<html>
<head>
</head>
<body>
<img src="doc/kmCNHkq.jpg"/>
</body>
</html>
(index.html)
Observation: I used to leave the HTML file in '../doc/' and resources on '../img/' however it seems that the HTML uses relative paths, so I copied the image into HTML's folder. If the solution also made it so I could leave the resources on their's respective folders it would be much appreciated.
#Edit:
Now I'm using this switch/case request handler. Working as expected, the HTML's request for the image is interpreted as a normal request (which may not end up scaling well, idk, but screw it). Thanks a lot!
import * as http from 'http'
import * as fs from 'fs'
var stream: fs.ReadStream,
folder = __dirname.substr(0, __dirname.length - 3);
http.createServer(function(req,res) {
switch (req.url){
case('/jpeg'):
stream = fs.createReadStream(folder + 'img/kmCNHkq.jpg');
stream.pipe(res);
console.log("Delivering the jpeg");
break;
case('/base64'):
fs.readFile('img/kmCNHkq.jpg', function (err, data) {
let img64 = new Buffer(data).toString('base64');
if (err) throw err;
res.end(img64);
console.log("Delivered base64 string");
})
break;
case('/html'):
stream = fs.createReadStream(folder + 'doc/index.html');
stream.pipe(res);
console.log("Sending the docs");
break;
default:
console.log("Shit happens");
}
}).listen(80)
(main.ts)
<html>
<body>
<img src="jpeg"/>
</body>
</html>
(index.html)
Short answer:
You won't be able to refer to specific resources on the server (such as your image) unless your server knows how to respond to those requests for that content. It looks like you can probably make your example work easily immediately though by changing the image src to just http://localhost:8000 though.
Longer answer:
Using 'doc/kmCNHkq.jpg' as the src for your image tells your browser that when it loads the page, it should go to the server it got the page from, and ask it for the 'doc/kmCNHkq.jpg' resource. If you specify a full URL including the protocol (the http://) then it will be absolute, instead of relative, so you can request from a different server than the one that served the page.
The servers that you've written don't actually look at the path of the file that's requested though (req.url), and actually they just always return the same content. If you connect to http://localhost:80 (the third server you've created above), and do request that jpg you'll still just get given the same HTML data of the page, because it just runs the two lines in your createServer call at the end of your example. You have written a server that always returns the image however above (the first server), just running on a different port, which is why the above solution works.
Just using that existing server is the simplest solution. The far more conventional approach though is to have just a single HTTP server running on a single port (instead of the 3 you have) and to use req.url to decide what data to return.
Traditionally for static content that means mapping a requested path directly onto the layout of the files on disk, so that requesting doc/abc.jpg looks for a doc folder in the server's directory, and returns the data from abc.jpg therein. That's not required necessarily at all though, and your server can interpret those paths however you like, to return content from anywhere.
(Note than none of this is really anything to do with TypeScript, or even much to do with Node.js. This is really just the essentials of how HTTP servers and browsers interact, and it would be almost identical with any other backing technology. I'd take a look more into the general HTTP and browser details if you're looking to get more background on this.)
I am trying to configure my browserHistory. My route is
<Route path="/test" component = {App} />
It works fine if I create a link. But if I put localhost/test in the browser or url I get a 404 error. I assume it cant find it on the server.
Can someone please help me? I am new to react-router. Do I have to configure the server side?
Thank you so much in advance.
Yes, as mentioned in React Router documentation you must configure your server so that it always returns your index page, no matter which path the browser requests.
Using express, supposing you have a /public/index.html file, this would work:
/* Your express includes and init code would go here... */
// Serve static assets normally
app.use(express.static(__dirname + '/public'))
// Handle every other route with index.html, which will contain
// a script tag to your application's JavaScript file(s).
app.get('*', function (request, response){
response.sendFile(path.resolve(__dirname, 'public', 'index.html'))
})
The important thing is app.get('*', ..., which will return the same thing (in this case your index.html file), no matter which path is requested from your browser.
Hope that helps.
I'm making the front end of a webpage where some json is needed for now I'm not doing the back so I made a file called it map.json and placed it on my server.
I'm working with node.js as a server so in the public folder I created a new folder named it jason and saved the file there.
Now I'm making an ajax call to this file, but the program isn't finding it, and when I go to public from the google chrome I don't see the json folder.
What do I have to do to be able to see this file and upload it as it was an ajax call to the server?
here is my jquery code, its in a file in public/javascript:
$.ajax('/../json/map.json', {
cache: false,
dataType: "json",
success: function(json) { ... code ... }
});
I really don't know how or what file should I modify in noje.js
Thanks!
The URL path used is technically invalid. Following a leading / with .. attempts to reach the parent directory of the domain's root path, which doesn't exist.
Though the browser may simply ignore the .., you should still choose one or the other -- either specify the path from root:
$.ajax('/json/map.json', {
// etc.
});
Or relative to the URL path of the current page (e.g., /some/page):
$.ajax('../json/map.json', {
// etc.
});
You've also stated that that the folder is named "jason" while the request includes /json/.... One may simply be a typo, but make sure they match.
And, assuming you're using the static() middleware, the URL will need to match the prefix specified (or lack of one):
app.use(express.static(__dirname + '/public'));
// $.ajax('/json/map.json', ...);
app.use('/public', express.static(__dirname + '/public'));
// $.ajax('/public/json/map.json', ...);
I'm using Node.exe in the following file structure
Node/
node.exe
index.js
/view
index.html
When running the following code:
var html;
fs.readFileSync('/view/index.html', function(err, data) {
if(err){
throw err;
}
html = data;
});
I get the following error:
Error: ENOENT, The system cannot find the file specified. '/view/index.html'
Can you see what's causing the error? I'm quite new to node.js.
Additional information:
I'm running Windows 7 64 bit, up to date version of node.exe.
I've found the solution!
When node.exe is run through cmd the default directory for node.exe is user.... that's where I was going wrong, it wa using a different directory to where the node.exe is located.
Few things:
You should resolved the relative path first to real path and try reading the file.
Read the file asynchronously to get the callback
Relative path should be corrected. The "./view/index.html" in my code is the path relative to where you start your node.js engine.
Rough code will be:
// get real path from relative path
fs.realpath('./view/index.html', function(err, resolvedPath) {
// pass the resolved path to read asynchronously
fs.readFile(resolvedPath, function(err, data) {
// assign the variable per your use case
html = data;
})
});
Note that I am using version 4.11 (latest stable version)
You might wanna lose the Sync part. Only readFile when you have a callback.
Also: ./path, not /path.