How would I find the farthest matching file - javascript

The title makes no sense to a closest-to-the-box person, but it will make sense.
I'm trying to make a custom-code HTTP server. the code works completely, but I want to add a 404 page.
when you get the 404 page, I want to show more than text.
this is what I have without that addition:
http = require("http");
fs = require("fs");
server = {};
server.http = http.createServer((request, response)=>{
request.path = request.url.split("?")[0];
if(request.url.split("?").length>1){
request.query = request.url.split("?")[1];
request.query = request.query.split('&');
var result = {};
for (var i = 0; i < request.query.length; i++) {
var cur = request.query[i].split('=');
result[decodeURIComponent(cur[0])] = decodeURIComponent(cur[1]);
}
request.query = result;
}
console.clear();
console.log(request.headers, request.path, request.query);
fs.readFile(`Public/HTTP/Scripts${request.path}.js`, "utf-8", (directError, script)=>{
if(directError){
if(directError.message == `ENOENT: no such file or directory, open 'Public/HTTP/Sripts${request.path}.js'`){
//this is where I would like that code. i was thinking a for loop would work but then i got really confused, so, here i am.
}
} else {
fs.readFile(`Public/HTTP/Send${request.path}.file`, (A, sendFile)=>{
eval(script);
});
}
})
});
server.http.listen();
console.clear();
The question without the extras is:
How do I go through file folders backward until I find a folder with the file I need?
I don't even know what I mean, but even more broken down in an example:
/a/path/to/a/file_that/doesn't_exist is request.url.
a, to, and file_that all have the file with the 404 response code.
I want it to get file_thats 404 script because it is the last.
I am so sorry if you still don't understand me. I'm new here and Idk how else to explain it.

Using the Express NodeJS Library is the industry standard framework for defining routes.
Express automatically finds the farthest file and sends an error.
If you use express, you can write
app.use(function (req, res, next) {
res.status(404);
res.send("public/error-404.html") //Where error-404.html is your custom HTML Page
return;
});
You can follow the official guide to implement Express in your app

Related

Inject rendered Node Express route into response of another route

Brief Project Overview
I am working on a full page caching system using Node and Express. I have this working, however I am trying to add cache "hole-punching", where portions of a document can have different caching policies.
Attempted Approach
I am attempting to achieve this by injecting the rendered output of one Express route into the rendered output of another Express route. Unfortunately, the most popular methods of firing an http request within Node involve asynchronous promises. I have not been able to get promises working in a synchronous request because... well, they don't work that way.
From what I can tell, I am left with 2 options:
Make the entire route/request/response asynchronous (is this possible?)
Find a synchronous way of rendering an Express route
I don't know how to achieve either of these. I know many folks will say not to do #2 because performance - I'm open to other suggestions.
Code
In the code below, I override the res.render() method to analyze the output of the current response and determine if there is a secondary request that should be made, rendered, and injected.
async function getRemoteInclude(req, content) {
// remote include format: {{ includeRemote('path') }}
const handlebarRegex = '(?<={{)(.*?)(?=}})';
const includeRegex = '(?<=includeRemote[(])(.*?)(?=[)])';
const replaceHandlebarRegex = /\{\{[^\}]+\}\}/g;
let parsedContent = content;
let foundHandlebars = content.match(handlebarRegex); // does string with {{ * }} exist?
if (foundHandlebars) {
let foundInclude = foundHandlebars[0].match(includeRegex); // does string with includeRemote('*') exist?
if (foundInclude) {
const axios = require('axios');
let path = 'http://expresscache.com:3000/test'; // sample hardcoded route
let response = await axios.get(path); // fire async request to express route
return parsedContent.replace(replaceHandlebarRegex, response.body); // replace remote include string with route response
}
}
return content;
}
function interceptRender() {
return function (req, res, next) {
res.render = function (view, options, callback) {
var self = this;
options = options || res.locals;
self.app.render(view, options, function (err, content) {
if (!callback) {
content = getRemoteInclude(req, content); // check if content should be modified with rendered remote include
self.locals.body = content;
self.send(content);
} else {
callback();
}
});
}
next();
}
}
module.exports = {
interceptRender: interceptRender
};
Obviously this code performs an async request through use of the axios node library. I am expecting that this will not be part of the final solution, unless option 1 from above is possible.
Ask
Does anyone have an idea how to either get this async request working in a synchronous context or to modify this request so that it is synchronous itself? Or maybe a completely different approach?

Cheerio not working. What am I doing wrong?

I am trying to scrape a classified ad search result page.
I have tried console logging everything I can to make sure I am getting a response, which I am, but when I actually use cheerio to query something I don't get anything back. For instance if I just query for how many children using $('.listing-group').children('section').length I get back 0 instead of 24 when I console log it.
Here is what I'm doing. Pardon the long URL.
const request = require("request");
const cheerio = require("cheerio");
const app = express();
app.get("/scrape", function(req, res) {
url =
"http://classifieds.ksl.com/search/?keyword=code&category%5B%5D=Books+and+Media&zip=&miles=25&priceFrom=&priceTo=&city=&state=&sort=";
request(url, function(error, response, html) {
if (!error) {
let $ = cheerio.load(html);
let test = $("#search-results").find("section").length
console.log(test);
} else {
console.log("there has been an error");
}
res.send("Check the console.");
});
});
app.listen("8081");
console.log("check localhost:8081/scrape");
exports = module.exports = app;
I'm new to cheerio so I'm assuming I'm probably making a simple error, but with all the tutorials I've checked, I can't seem to find an answer.
Ultimately I want to grab each result on the page (found in the 'section' tags) to display the data for a personal project I'm working on.
It looks like:
JSON.parse(html.match(/listings: (\[.*\])/)[1])

How to get number of directory items in Node.js

I need to get number of items of specific directory in Node.js
If I get the items like
var dirItems = fs.readdirSync(__dirname+'/my_dir');
and then get specific item like
dirItems[1]
everything is ok
But if I try to get their number like
dirItems.length
or
Object.keys(dirItems).length
the page doesn't work in the browser
How to get the number of directory items?
UPDATED
My full code:
var http = require('http'),
fs = require('fs');
http.createServer(function(req, res) {
var dirItems = fs.readdirSync(__dirname+'/my_dir');
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(dirItems.length);
}).listen(80, 'localhost');
I was able to reproduce the error nyou get.
res.end() for the basic http server class is very picky about what you send it. You must give it a string (the error you got should have been a big clue here).
So, change this:
res.end(dirItems.length);
to this:
res.end(dirItems.length.toString());
And, it works for me. I was able to reproduce your original error and then make it work by making this simple change.
Logically, you can only send string data as an http response so apparently res.end() isn't smart enough to attempt a string conversion on its own. You have to do it yourself.
FYI, if you use a higher level framework like Express, it is more tolerant of what you send it (it will attempt a string conversion in a situation like this).
Here is how I would do it:
const fs = require('fs');
const dir = './somedir';
fs.readdir(dir, (err, files) => {
console.log(files.length);
});

Split video file to stream from browser

I split a video file into two using the split-file module.
There are no file part extensions. They seem like: gan-1, gan-2
I am hosting these two files on my own server.
http://bilketay.com/download/gan-1
http://bilketay.com/download/gan-2
I try to stream these two files through the browser like a single video file. Like;
// Dependencies
var express = require('express');
var app = express();
var CombinedStream = require('combined-stream2');
var request = require('request');
// Some routes
app.get('/', function(req, res) {
// Set header
res.set({
"Content-Type": 'video/mp4'
});
res.writeHead(200);
var combinedStream = CombinedStream.create();
// This function is to call gan-1 first, then gan-2
var recursive = function(param) {
var req = request('http://bilketay.com/download/' + param);
// First add gan-1, then gan-2
combinedStream.append(req);
req.on('end', function() {
if (param != 'gan-2') {
recursive('gan-2')
}
});
}
// Start recursive
recursive('gan-1');
// Start stream browser
// But, It does not start until it is completely loaded :(
combinedStream.pipe(res);
});
// Listen port
app.listen(3000);
I created this code with restricted node.js information. No problem for me, but I think Google Chrome is different. :)
The problem is, the two parts do not stream without being loaded. The stream starts after two parts have been uploaded. What I want to do is start the stream right away. A short note; gan-1 and gan-2 files are working locally. But it does not work on the remote server. What am I doing wrong?
I used the combined-stream2 module to merge the parts.
This module simplifies streaming by adding two different files. But because I can not get the result I want, I might have used it wrong.
In short, I want to stream two different files through the browser, respectively.
I need the help of ninjas. Thank you.
Screen shot describing the problem;
stream.gif

JSONP call with server-side language as Javascript

I've been trying to use JSONP to get a JSON object from a server via a client-side call (on a different port). However, because my server is implemented in javascript using Node.js and Express, I haven't been able to find much on JSONP with Javascript on the server as most sites I found used php for server-side code.
I believe the issue is with how I set up the url with respect to the callback, which I'm a bit fuzzy on cause it's new to me.
On the server:
//Setting up server stuff
var express = require('express'),
app = express.createServer();
app.use(express.logger());
//Making a connection to the mongoDB to get the data that I want to display in the JSON object
new Db('prism',
new Server("127.0.0.1", 27017, {auto_reconnect: false}), {}).open(function(err, db) {
app.get('/getData', function(req, res) {
console.log('JSONPCALLBACK CALLED WITH RETURNDATA PASSED IN; SERVER SIDE');
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
}
});
And on the client:
$.ajaxSetup({ cache : false });
$.getJSON('http://127.0.0.1:1337/getData&callback=?', function(rtndata) {
console.log('SUCCESS');
console.log(rtndata);
});
embedded by the standard tags.
But I get the error:
GET http://127.0.0.1:1337/getData&callback=jQuery16108897686484269798_1311007334273?_=1311007334342 404 (Not Found)
The server is on port 1337 while the client is run through MAMP on localhost:8888. I'm not sure if its even a localhost related issue as I've been trying to get this setup running for a few days now.
I believe the issue has something to do with not writing this line, which is in php, into my server-side Javascript. Most of the JSONP examples I found had something like this. But I'm not sure.
if ($GET['callback'] != '')
$json = $GET['callback']."( $json )";
return $json;
Any help would be greatly appreciated. I apologize ahead of times for being super verbose.
Bests,
Cong
I think you have two problems. First is the 404. Completely separate from getting the client-side jQuery code to work, you need to make sure that you can issue a regular browser request (i.e. paste in that URL) and get back what you expect. I haven't used express, so it's hard for me to comment on why you'd be getting that, except to say that I don't see 1337 anywhere in your server-side code, just what appears to be the port number 27017.
The second problem is that you don't actually want to execute the callback on the server, just build the JSON response including the callback (string) prefixed to it.
So instead of this ...
if (typeof callback == 'function') {
console.log('callback is defined');
callback(returnData);
}
else {
console.log('callback is not defined');
}
try this:
if (callback) {
console.log('callback is defined');
res.write(callback + '(' + JSON.stringify(returnData) + ')');
}
else {
console.log('callback is not defined');
}
Hope this helps!
From http://api.jquery.com/jQuery.getJSON/ there is an example that includes 2 '?' in the URL.
you only have one, so try
$.getJSON('http://127.0.0.1:1337/getData?callback=?', function(rtndata) {
and see if that gets rid of your 404
then look #jimbojw suggestion for returning a proper jsonp formated responce.
Use this:
var express = require("express");
var server = express.createServer();
server.enable("jsonp callback");
server.get("/foo", function(req, res) {
// this is important - you must use Response.json()
res.json("hello");
});
jsonp with node.js express

Categories

Resources