Unable to redirect `file:///` requests - firefox-addon-webextensions

I am trying to override file:/// URLs, whether pointing to files or directories, to let my extension show its own file browser for directory views and also potentially allow editing of individual files for files.
I made the following attempt, but the listener was never triggered for either files or folders:
browser.webRequest.onBeforeRequest.addListener((details) => {
const {documentUrl, originUrl, type, requestBody, url} = details;
if ((/^file:/).test(originUrl)) {
return {
redirectUrl: browser.extension.getURL('filebrowser/index.html') + '?abc=1'
};
}
}, {
urls: ['file:///*/*']
}, ['blocking']);
I did add the "file:///*/*" permission to the manifest ("<all_urls>" also didn't work) (and I added "web_accessible_resources" for the redirect, but that was never even reached).
I am guessing this may be because of https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/RequestFilter#Type , where it states that only requests made using HTTP/HTTPS will work for events despite file patterns supporting other protocols. However, onHeadersReceived does seem to receive at least the file:/// file requests (though not directory requests) even though onBeforeRequest which is needed for redirects, does not.
Can anyone confirm whether there are any workarounds?

Related

Is there a way to rename automatically generated routes JSON file in Next.js?

I have a problem, when I click to go to the /analytics page on my site, adblockers block the analytics.json file that's being requested by Next.js as they think it's an analytics tracker (it's not, it's a page listing analytics products).
Is there a way to rename the route files Next.js uses when navigating to server-side rendered pages on the client-side?
I want to either obfuscate the names so they're not machine readable, or have a way to rename them all.
Any help appreciated.
With thanks to #gaston-flores I've managed to get something working.
In my instance /analytics is a dynamic page for a category, so I moved my pages/[category]/index.tsx file to pages/[category]/category.tsx and added the following rewrite:
// next.config.js
module.exports = {
async rewrites() {
return [
{
source: "/:category",
destination: "/:category/category",
},
];
},
};
This now gets the category.json file rather than analytics.json, which passes the adblockers checks and renders as expected.
Note that due to having a dynamic file name in the pages/[category] directory (pages/[category]/[product].tsx), I had to move that to pages/[category]/product/[product].tsx as I was seeing the /analytics page redirected to /analytics/category for some reason without this tweak.

Authentication to serve static files on Next.js?

So, I looked for a few authentication options for Next.js that wouldn't require any work on the server side of things. My goal was to block users from entering the website without a password.
I've set up a few tests with NextAuth (after a few other tries) and apparently I can block pages with sessions and cookies, but after a few hours of research I still can't find how I would go about blocking assets (e.g. /image.png from the /public folder) from non-authenticated requests.
Is that even possible without a custom server? Am I missing some core understanding here?
Thanks in advance.
I did stumble upon this problem too. It took my dumbass a while but i figured it out in the end.
As you said - for auth you can just use whatever. Such as NextAuth.
And for file serving: I setup new api endpoint and used NodeJS magic of getting the file and serving it in pipe. It's pretty similar to what you would do in Express. Don't forget to setup proper head info in your response.
Here is little snippet to demonstrate (typescript version):
import { NextApiRequest, NextApiResponse } from 'next'
import {stat} from "fs/promises"
import {createReadStream, existsSync} from "fs"
import path from "path"
import mime from "mime"
//basic nextjs api
export default async function getFile (req: NextApiRequest, res: NextApiResponse) {
// Dont forget to auth first!1!!!
// for this i created folder in root folder (at same level as normal nextjs "public" folder) and the "somefile.png" is in it
const someFilePath = path.resolve('./private/somefile.png');
// if file is not located in specified folder then stop and end with 404
if (! existsSync(someFilePath)) return res.status(404);
// Create read stream from path and now its ready to serve to client
const file = createReadStream(path.resolve('./private/somefile.png'))
// set cache so its proper cached. not necessary
// 'private' part means that it should be cached by an invidual(= is intended for single user) and not by single cache. More about in https://stackoverflow.com/questions/12908766/what-is-cache-control-private#answer-49637255
res.setHeader('Cache-Control', `private, max-age=5000`);
// set size header so browser knows how large the file really is
// im using native fs/promise#stat here since theres nothing special about it. no need to be using external pckages
const stats = await stat(someFilePath);
res.setHeader('Content-Length', stats.size);
// set mime type. in case a browser cant really determine what file its gettin
// you can get mime type by lot if varieties of methods but this working so yay
const mimetype = mime.getType(someFilePath);
res.setHeader('Content-type', mimetype);
// Pipe it to the client - with "res" that has been given
file.pipe(res);
}
Cheers

Next.js: How can we have dynamic routing redirect to static pages?

Using Next.js , I currently have an app with a single entry point in the form of /pages/[...slug]/index.ts
It contains a getServerSideProps function which analyses the slug and decide upon a redirection
In some cases a redirection is needed, but it will always be towards a page that can be statically rendered. Example: redirect /fr/uid towards /fr/blog/uid which can be static.
In other cases the slug already is the url of a page that can be static.
How can I mix this dynamic element with a static generation of all pages?
Thanks a lot for your help!
If I understood you problem correctly, you cannot use getServerSideProps if you are going to export a static site.
You have two solutions:
Configure your redirection rules in your web hosting solution (i.e. Amazon S3/CloudFront).
Create client-side redirects (when _app.tsx mounts you can check if router.asPath matches any of the redirection you would like to have configured.
Please remember that the first solution is more correct (as 301 redirects from the browser) for SEO purposes.
EDIT: #juliomalves rightly pointed out OP is looking at two different things: redirection, and hybrid builds.
However, question should be clarified a bit more to really be able to solve his problem.
Because you will need to host a web-server for SSR, you can leverage Next.js 9.5 built-in redirection system to have permanent server-side redirects.
When it comes to SSR vs SSG, Next.js allows you to adopt a hybrid approach, by giving you the possibility of choosing with Data Fetching strategy to adopt.
In case you are using AWS CloudFront, then you can redirect with CloudFront Functions.
CloudFront Functions is ideal for lightweight, short-running functions for use cases like the following:
URL redirects or rewrites – You can redirect viewers to other pages based on information in the request, or rewrite all requests from one path to another.
Here is what we are using to redirect clients (e.g. Native App, Google search index, etc.) to new location when NextJS page was moved or removed.
// NOTE: Choose "viewer request" for event trigger when you associate this function with CloudFront distribution.
function makeRedirectResponse(location) {
var response = {
statusCode: 301,
statusDescription: 'Moved Permanently',
headers: {
'location': { value: location }
}
};
return response;
}
function handler(event) {
var mappings = [
{ from: "/products/decode/app.html", to: '/products/decode.html' },
{ from: "/products/decode/privacy/2021_01_25.html", to: '/products/decode/privacy.html' }
];
var request = event.request;
var uri = request.uri;
for (var i = 0; i < mappings.length; i++) {
var mapping = mappings[i]
if (mapping.from === uri) {
return makeRedirectResponse(mapping.to)
}
}
return request;
}

ng-flow - no destination directory option

I am using ng-flow in my application and it works pretty well. Currently, the destination directory for the files being uploaded is set in my web.config and used within my webapi controller method.
What I want to do is allow the user to specify the destination, rather than it come from config. However, looking at the docs, I don't see an option that I can add to the below appconfig for this:
function appConfig(flowFactoryProvider) {
flowFactoryProvider.defaults = {
target: 'api/upload',
permanentErrors: [404, 500, 501],
maxChunkRetries: 1,
chunkRetryInterval: 5000,
simultaneousUploads: 4
};
flowFactoryProvider.on('catchAll', function (event) {
console.log('catchAll', arguments);
});
}
Am i missing something or do I need to handle this myself?
You should see a clear separation between your front end and you back end. That is why you are not able to set in flow-js or any other framework.
What you can do, is let the user specify it in a form field and leave the handling to the server side. This way it is also possible to filter on allowed locations. You don't want your client to add files to your system directories.

Node.js/Express Routing to a static file URL

I don't have a problem as such as I have a work-around. However the process of understanding and developing the work-around has highlighted what seems to me a fundamental gap in my knowledge (as a self-taught programmer, this happens a lot ;-) !) and I can't seem to find the answer to plug it anywhere.
Standard node.js/express setup with for example:
app.get('/index.htm', function (request, response) {
console.log("/index.htm");
});
app.get('*', function (request, response) {
console.log("*");
});
Why when the user connects directly to index.htm (by typing in the URL although I've not tried clicking on a link) does nothing fire ? The page is served no problem. The obvious use-case for this is to check if the user is authenticated prior to serving the static page.
FYI the workaround is to pass the user to a route such as "/authenticated" (which matches fine), do the check and then redirect and basically block everything else.
Thanks for educating me in advance ;-)
N
UPDATE to Raynos' question - yes (ignore the server/app variable name discrepancy).
// CREATE SERVER
var server = express.createServer();
server.configure(function() {
server.use(express.static(__dirname + '/public'));
server.use(express.logger());
server.use(express.errorHandler({dumpExceptions: true, showStack: true}));
// start of session stuff
server.use(express.cookieParser());
server.use(express.session({store: sessionStore, secret: 'secret', key: 'express.sid'}));
});
I've now found that the routing matches fine once you delete the static file i.e. in the original example, deleting index.htm means that the console will now log "/index.htm".
N
Just to bring some closure to this question:
Express static handler if it finds the file it will serve it and it won't let the other handlers to be called. If you remove it, then app.get('/index.htm' handler will be called. If you want to have a callback on all URLs just add server.use(function(req, res, next) {...}) before everything and that function will be called on all routers, make sure you call next if you want other middlewares or route handlers to be called.

Resources