How to redirect assets to public, make public invisible and make lessMiddleware work - redirect

Yesterday I had a public folder with generated css, and a source folder with less
root
/public
/css
/source
/less
and a less middleware like this
module.exports = function (app, dir) {
return lessMiddleware(path.join(dir, 'source', 'less'), {
dest: path.join(dir),
preprocess: {
path: function(pathname, req) {
return pathname.replace('public' + path.sep + 'css' + path.sep, '');
}
}
});
};
It works fine, except that root dir is open, and I can get access to public folder. So, I put a NGINX as proxy, and had no problems, it denies access to root folder and redirects 'assets' to 'public'.
So I had url's like http://localhost/assets/css/main.css
Today I want to get rid of nginx for debug purposes. So I give static access to assets folder like this
if (settings.debug) {
app.use('/assets', express.static(path.join(__dirname, "public")));
}
The problem is that less middleware stopped working, because this code changes path for middleware to
c:\node\myproject\source\less\assets\css\main.less
Is there a way to redirect 'assets' to 'public' using express js standard static middleware? Or a standard way to substitute '/assets' with '/public' and pass this request forth?
I can do that with app.get(... and parse request and so on. I also can change middleware 'preprocess' directive. But I want to spend as less code as possible.
P.S.
Ok, now I can make assets work
if (settings.debug) {
app.use(function(req, res, next) {
if (req.url.indexOf('/assets/') === 0) {
req.url = req.url.replace('/assets/', '/public/');
}
next();
});
}
app.use(require('./config/lessMiddlewareConfig.js')(__dirname));
app.use('/public', express.static(path.join(__dirname, 'public')));
but I want to deny access to public now.

On your server is it actually necessary to use less middleware?
I got around this, buy adding this to my deployment shell script:
curl http://localhost:3000/stylesheets/style.css > /dev/null
which forces a recompile by requesting the css file directly to the node process.

Related

Requiring config.js file in VSCode extension with absolute path (e.g. "C:\...") does not work

I am developing the Argdown VSCode extension. The Argdown parser can be configured using either argdown.config.json files or argdown.config.js files exporting a config object. Using Javascript files is the easiest way to allow users to add custom plugins to the Argdown parser.
If the user tells the parser to use a Javascript file, the file is loaded using import-fresh, (which uses node's require, but deletes the cached version.
Using the Argdown commandline tool (#argdown/cli) this works fine, but in the VSCode extension the module of the config file can not be found. The extension is using absolute file paths to require the config module (e.g. "C:\Users\my-username\projects\my-argdown-project\argdown.config.js"). These paths work with import-fresh outside of the VScode extension.
Is there a security restriction for VSCode extensions that does not allow to require modules with absolute file paths? Or is there some other reason why this does not work?
This was not related to VSCode. The problem was caused by bundling up import-fresh with webpack. I thought that webpack would ignore dynamic imports, but it did not.
I was lucky: Since last month, webpack supports "magic comments" for require (not only for import). So I can use:
require(/* webpackIgnore: true */ file);
You have to activate magic comments support in your webpack config:
module.exports = {
parser: {
javascript: {
commonjsMagicComments: true,
},
},
}
Now the next question is how to add the magic comments to the import-fresh package. For that I used the string-replace-loader:
module.exports = {
module: {
rules: {
{
enforce: "pre",
test: /import-fresh[\/\\]index\.js/,
loader: "string-replace-loader",
options: {
search:
"return parent === undefined ? require(filePath) : parent.require(filePath);",
replace:
"return parent === undefined ? require(/* webpackIgnore: true */ filePath) : parent.require(/* webpackIgnore: true */ filePath);",
},
},
}
}
}
After that, I could load the argdown.config.js files again, even after bundling everything with webpack.

Include node module as a file to inject

I want to include /node_modules/es6-shim/es6-shim.min.js into the client side in Sails v0.11.
I've tried including it into the pipeline as such:
var jsFilesToInject = [
// Load sails.io before everything else
'js/dependencies/sails.io.js',
/* INCLUDE NODE MODULE */
'/node_modules/es6-shim/es6-shim.min.js',
// Dependencies like jQuery, or Angular are brought in here
'js/dependencies/**/*.js',
// All of the rest of your client-side js files
// will be injected here in no particular order.
'js/**/*.js',
// Use the "exclude" operator to ignore files
// '!js/ignore/these/files/*.js'
];
Is this possible? I don't really want to use bower or a CDN, I would like to install/update the dependency via npm.
The simplest way to accomplish this would be to leave the pipeline.js file alone and just make a symlink inside of assets/js pointing to the file you want, e.g.:
ln -s ../../node_modules/es6-shim/es6-shim.min.js assets/js/es6-shim.min.js
Next time you run sails lift, Grunt will see the new Javascript file in your assets/js folder and process it with the rest.
If this is for some reason not an option, you'll need to add a new subtask to the tasks/copy.js Grunt task:
dev_es6: {
files: [{
expand: true,
src: ['./node_modules/es6-shim/es6-shim.min.js'],
dest: '.tmp/public/js'
}]
}
and then add that to the compileAssets task in tasks/register/compileAssets:
module.exports = function (grunt) {
grunt.registerTask('compileAssets', [
'clean:dev',
'jst:dev',
'less:dev',
'copy:dev',
'copy:dev_es6', // <-- adding our new subtask
'coffee:dev'
]);
};

How to run custom php script from doc root in magento2

I wanted to add custom php script to magento2 root folder and run from the browser.I tried to add it in magento2 root folder but it redirects to 404 page.
I also tried to add it in pub folder but no success.
Also cleared cache and empty generation folder.
I am using nginx server
If you are using nginx configuration that comes with magento you need to put a file inside pub folder to allow access to it from the browser as pub is the document root of the vhost. Magento root dir is one level up. Second of all default config for nginx allows only to access index.php, get.php, static.php, report.php, 404.php and 503.php files. Any other are not processed by the php. You can see this in line with location ~ (index|get|static|report|404|503)\.php$ { in nginx.conf.sample. If you are not using it check your config for similar rule. To allow another file to be accessible from browser simple add another name after 503 or change entire brackets with location ~* \.php$ {
Source: https://magento.stackexchange.com/a/97290/1883
For example you can get product name in custom script by this step
step 1: create index.php at root of magento 2
magento2/test/index.php
<?php
require __DIR__ . '../../app/bootstrap.php';
$bootstrap = \Magento\Framework\App\Bootstrap::create(BP, $_SERVER);
$app = $bootstrap->createApplication('customScript');
$bootstrap->run($app);
step 2: create customScript.php
magento2/test/customScript.php
<?php
class customScript
extends \Magento\Framework\App\Http
implements \Magento\Framework\AppInterface {
public function launch()
{
$this->_state->setAreaCode('frontend'); //Set area code 'frontend' or 'adminhtml
$id = 12;
$_product = $this->_objectManager->create('\Magento\Catalog\Model\Product')->load($id);
echo $_product->getName();
return $this->_response;
}
public function catchException(\Magento\Framework\App\Bootstrap $bootstrap, \Exception $exception)
{
return false;
}
}
Now you can run this custom script by
http://10.16.16.196/magento2/test/
As stated by #Ranjit, the /pub folder must be your Magento root folder.
The correct way to run a standalone php script on Magento would be:
On nginx:
Locate location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check)\.php$ { and add your file there.
I.e:
location ~ ^/(index|get|static|errors/report|errors/404|errors/503|health_check|myphp)\.php$ {
Then you can access yourstore.com/myphp.php.
On Apache:
Simply add the file under /pub folder. I.e.: /pub/myphp.php.
Apache rewrites rule will redirect to index.php if the file or folder doesn't exist.
In my case on Apache (cPanel) the problem was that file permissions of .php files should not be writable by group or others to be served directly, else Magento's 404 would open.
So in my case to serve file directly I had to set file permission to -rw-r--r-- (on Linux).
This is the mostly issue with servers using suPHP.
Putting this here in case someone runs into same situation...

prefix assets for production with static path

for assets such as /assets/image.png, that I call in stylesheets, javascript etc...
I need to prefix or prepend a path to server.
so that /assets/image.png becomes /static/ember/memory/dist/assets/image.png for production.
where it will be served as ie: http://domain.com/static/ember/memory/dist/assets/image.png
i need to pass and use a STATIC_PATH variable when compiled/built for production that will be prefixed, or compile it so that it does it automatically.
I have checked ember-cli docs for assets compilation:
var app = new EmberApp({
fingerprint: {
prepend: '/static/ember/memory/dist/'
}
});
however, this doesn't work as where the assets are being called the path doesn't change in production, unless it actually modified the path where it's called.
for example in styles.css if I call /assets/image.png somewhere, I need to prefix this with STATIC_PATH + /assets/image.png when in production.
the STATIC_PATH will look something like:
/static/ember/memory/dist/
I can add this manually for production in development, but then cannot test in development.
thanks for any response.
You can pass a prepend option in the ember-cli-build file, you will have to exclude the assets that don't need the path:
var app = new EmberApp({
fingerprint: {
exclude: ['excludedAssets/'],
prepend: '/static/ember/memory/dist/'
}
});
For more information check out asset compilation

Sharing a public tree in an ember-cli addon

I am completely puzzled when I read all the information I can gather about sharing a public assets directory from an ember-cli addon.
Is there anybody having it working around here? Any ref to an example addon doing it would also be appreciated...
So... I finally found a way to share the static assets:
- I placed the files in vendor/assets directory
- Declared the files to shared (each file...) into the addon's index.js file # addon's root
app.import('vendor/assets/my_image.png');
An interesting option of app.import statement I found in my searches is destDir, which allows to customize the target publication path of the asset:
app.import('vendor/assets/a/b/c/my_image.png', { destDir: 'x/y' });
will publish my_image.png # URL /assets/x/y/my_image.png
Hoping this will help others to save time...
Assets of addons are available under a namespace. For example if there is a file in public/assets/image.png in your addon, this file is available under /my-addon/assets/image.png.
If you don't want to use a namespace, you can overwrite the treeForPublic hook in the addon definition as demonstrated in this gist:
const Funnel = require('broccoli-funnel');
const mergeTrees = require('broccoli-merge-trees');
module.exports = {
name: require('./package').name,
treeForPublic: function(tree) {
const assetsTree = new Funnel('public');
return mergeTrees([tree, assetsTree], {
overwrite: true,
});
},
};