How to run custom php script from doc root in magento2 - 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...

Related

Trying to return a static file in web.py but getting "not found" error message

I have a web.py server hosted on pythonanywhere.com doing some handy things with python.
Now I'd like to just serve a straightforward html file from the same server i.e. just return the contents of a static html file to the client
The comments/answers below state that it should be possible, out of the box, to serve static files in the static directory, located in the same directory as the main python file which contains the following :
import web
urls = (
'/', 'hello'
)
app = web.application(urls, globals())
class hello:
def GET(self):
return 'Hello, Joe'
if __name__ == "__main__":
app.run()
The server above works fine, when I go to http://myhost/ it displays "Hello , Joe".
The directory static exists and contains a file small.jpg but when I try the url http://myhost/static/small.jpg it gives me "not found"
Previous text of question up to Nov 9th 2022 is below :
original question title : Trying to return a html file in web.py but getting "No template named ....." error message
So I've looked at the web.py documentation on serving static files and templating and I think the following code should work :
import web
render = web.template.render('static/')
# have also tried render = web.template.render('/full/path/to/static/')
urls = (
'/getlatlongEIRCODE', 'getlatlongEIRCODE', #other stuff
'/getlatlongGOOGLE', 'getlatlongGOOGLE', #other stuff
'/getmonthlyPV', 'getmonthlyPV', #other stuff
'/Tomas', 'Tomas',
)
class Tomas:
def GET(self):
return render.Tomas()
I have created a folder static at the same level as my file above (which works fine for the other scripts) and i have created a file Tomas.html in the static folder containing
<h1>Help me</h1>
However I get an error message when I go to https://example.com/Tomas
<class 'AttributeError'> at /Tomas
No template named Tomas
P.S. From the static files page it seems to say I should just be able to put the Tomas.html file in a folder called "static" and then access is via https://example.com/static/Tomas.html but that is not working (it returns "not found")
You're using a relative path to your template directory without paying attention to the working directory. See https://help.pythonanywhere.com/pages/NoSuchFileOrDirectory/
You're working too hard. 'static' is built in.
As the documentation says, http://localhost/static/logo.png will return the file logo.png from the existing directory static, which is relative to your webserver root.
Do not use render() for this (not needed). Also, do not list your desired file ('/Tomas') in the urls list (not needed).
Anything under the static directory can be accessed with the url https://localhost/static/...
"static" is hardcoded in the web.py server, so you cannot (easily) change this to some other folder. The suggestion in the web.py documents is to have nginx or apache host your application and use an Alias there to go to web.py static. (I think you can also add StaticMiddleware to your web.py application, but you'd need to investigate that yourself -- look at web.application.run()
The case of the disappearing /static/ directory was related to the fact that I'm hosting on pythonanywhere.com
Even though the web.py documentation says that the /static/ folder is plugged in by default, that's not the case in pythonanywhere and you need to expressly make the link between the url http://yourhost/static/ and /path/to/static in the Web part of the dashboard.

How to resolve issue :: file_get_contents(http://localhost:8085/assets/data/test.txt): Failed to open stream: HTTP request failed

By using CodeIgniter 4 framework, I've developed RESTful api and there I need to access file (.json and .txt) to get content. But not able to access php inbuilt function file_get_contents().
For more details, pls check attached screenshot API_curl_file_get_content_error.PNG
And test.txt file is also accessible with same file path. For more details pls check screenshot Input-txt-file-content.png
NOTE : 1) test.txt file and respective directories have full permission.
2) Development environment :
<---->Apache/2.4.47 (Win64) OpenSSL/1.1.1k PHP/8.1.2
<---->Database client version: libmysql - mysqlnd 8.1.2
<---->PHP version: 8.1.2
<---->CodeIgniter 4
Product.php (index method)
<?php
namespace App\Controllers;
use CodeIgniter\RESTful\ResourceController;
class Product extends ResourceController
{
use \CodeIgniter\API\ResponseTrait;
public function index()
{
helper("filesystem");
ini_set('max_execution_time', 300);
$data['msg'] = "Product Index wizard";
$data['status'] = 200;
$file_path = base_url() . '/assets/data/test.txt'; // Read JSON
$json = file_get_contents($file_path, true);
$json_data = json_decode($json, true);
return $this->respond($data);
}
}
Explanation:
Remember that "http://localhost:8085/" most likely points to the document root of the project, which is usually the /public path. So, unless the "assets" folder resides in the /public path, file_get_contents("http://localhost:8085/assets/data/test.txt"); will fail to find the requested server resource.
Solution:
Since your file resource (test.txt) is on the local filesystem,
Instead of:
file_get_contents("http://localhost:8085/assets/data/test.txt");
Use this:
constant ROOTPATH
The path to the project root directory. Just above APPPATH.
file_get_contents(ROOTPATH . "assets/data/test.txt");
Addendum:
I believe you also forgot to add the $json_data output to the returned $data variable in the Product::index resource controller method.

How to change the Public directory path in Lumen?

By default Lumen "same as Laravel" has myApp/public directory to put all the public files (assets).
I want to change that directory path from myApp/public to myApp/src/custom/public. How can I do achieve this?
I also struggled with this and found a soltuion elsewhere.
I wanted the following directory structure:
.hosting root dir
├── lumen_app_dir <---
├── other_app_dir
├── etc...
└── public_html
└──lumen_app_public_dir <---
So I did the following:
Copied the index.php and .htaccess from lumen_app_dir/public to the lumen_app_public_dir.
Changed the index.php there like this:
$app = require __DIR__.'/../../lumen_app_dir/bootstrap/app.php';
$app->run($app['request']);
The important part here is, that I had to include $app['reqest'] as the parameter for run function.
And it just works without any change in the default .htaccess file. I can access the Lumen installation at server.dev/lumen_app_public_dir
Got the same problem, and solved it. Look here, maybe it will help you.
I have done this solution for my Lumen application, which works for me.
UPDATE
Ok, let's go proceeding some changes to make the system to work with your tree.
Add a .htaccess file in the root of your application so in the directory myApp\. Write it in :
RewriteEngine On
RewriteCond %{THE_REQUEST} /public/([^\s?]*) [NC]
RewriteRule ^ %1 [L,NE,R=302]
RewriteRule ^((?!public/).*)$ src/custom/public/$1 [L,NC]
Assuming that you have configured your vhost pointing to \Path\myApp, we now accede to the index file of myApp\src\custom\public\. If we didn't make any mistakes, then we should get to a page that indicates an error, telling us that the bootstrap/app.php file is not found. Logic.
We must therefore change the index.php file in the directory myApp\src\custom\public :
Change from this :
$app = require __DIR__.'/../bootstrap/app.php';
To this :
$app = require __DIR__.'/../../../bootstrap/app.php';
You can now get your home page directly from the path wanted.
You can override your public directory using the IoC container like this:
App::bind('path.public', function()
{
return base_path().'/public_html';
});
But I prefer to use a symlink to the public folder like this:
ln -s public public_html
I believe you should "point" your vhost to the new location (assuming you moved/renamed the public dir to your desired path). This is only needed is your server is not yet configured this way.
Then open the index.php from your new location and "fix" the path to bootsrap/app.php
Then open server.php from the Lumen base dir and edit your paths in both locations you find "public" mentioned.
Didn't really test this but looks like it should work. Give it a try.
One solution is to bind the path fro public in the appServiceProvider.php register method:
$app->bind('path.public', function() {
return __DIR__; });
A reliable way is to go into your public_html/index.php!
I'm using Lumen 6.x and it's work properly.

Nginx - How to redirect a directory to a file that its path contains the directory?

I'm new to Nginx and I'm trying to redirect a directory to a file, here is basically what I'm trying to do:
When entering this link:
http://localhost:8889/dir
go to this link instead:
http://localhost:8889/dir/path/to/the/file/index.html
As you can see the directory is part of the file path which I'm trying to redirect to. Plus there is already a location block in the config file to redirect that directory to the proper location:
location /dir {
root /opt/dir;
}
My first attempt was to use the rewrite directive as I saw from this blog(https://jeffsebring.com/2012/nginx-301-redirects/):
if ( $request_filename ~ dir ) {
rewrite ^ http://localhost:8889/dir/path/to/the/file/index.html permanent;
}
But the page says it has a redirect loop, which I believe is the conflict with the old location block.
Then I tried to add another location block as I saw from here(nginx rewrite virtual directory to file):
location /dir {
rewrite ^/dir$ /dir/path/to/the/file/index.html;
}
But after reloading config file, Nginx told me there is already a location block with the same directory exists.
So my question is is there any way I can do this? or it is not even possible?
Thanks!!
Found the solution.
I used "return" to return the full hard-coded url instead rewrite the current one:
location ~* /dir$ {
return http://localhost:8889/dir/path/to/the/file/index.html;
}
And also this rewrite solution works as well:
location ~* /dir$ {
rewrite ^/dir$ /dir/path/to/the/file/index.html;
}
The problem I had was actually caused by cache. I was actually reloading the page from cache so I could not see the result after changing nginx config file, and I resolved this by checking the "Disable cache" option in developer tools in Chrome.

PHP Built-in Webserver and Relative Paths

TL;DR
Does PHP 5.4 built-in webserver have any bug or restriction about relative paths? Or does it need to be properly (and additionally) configured?
When I used to programming actively I had a system working under URI routing using these lines in a .htaccess file:
RewriteEngine On
RewriteRule !\.(js|ico|gif|jpg|png|css)$ index.php [L]
The FrontController received the Request, find the proper route from given URI in a SQLITE database and the Dispatcher call the the Action Controller.
It worked very nicely with Apache. Today, several months later I decided to run my Test Application with PHP 5.4 built-in webserver.
First thing I noticed, obviously, .htaccess don't work so I used code file instead:
<?php
if( preg_match( '/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"] ) ) {
return false;
}
include __DIR__ . '/index.php';
And started the webserver like this:
php.exe -c "php.ini" -S "localhost:8080" "path\to\testfolder\routing.php"
So far, so good. Everything my application need to bootstrap could be accomplished by modifying the include_path like this:
set_include_path(
'.' . PATH_SEPARATOR . realpath( '../common/next' )
);
Being next the core folder of all modules inside a folder for with everything common to all applications I have. And it doesn't need any further explanation for this purpose.
None of the AutoLoader techniques I've ever saw was able to autoload themselves, so the only class manually required is my Autoloader. But after running the Test Application I received an error because my AutoLoader could not be found. o.O
I always was very suspicious about realpath() so I decided to change it with the full and absolute path of this next directory and it worked. It shouldn't be needed to do as I did, but it worked.
My autoloader was loaded and successfully registered by spl_autoload_register(). For the reference, this is the autoloading function (only the Closure, of course):
function( $classname ) {
$classname = stream_resolve_include_path(
str_replace( '\\', DIRECTORY_SEPARATOR, $classname ) . '.php'
);
if( $classname !== FALSE ) {
include $classname;
}
};
However, resources located whithin index.php path, like the MVC classes, could not be found. So I did something else I also should not be doing and added the working directory to the include_path. And again, manually, without rely on realpath():
set_include_path(
'.' . PATH_SEPARATOR . 'path/to/common/next'
. PATH_SEPARATOR . 'path/to/htdocs/testfolder/'
);
And it worked again... Almost! >.<
The most of Applications I can create with this system works quite well with my Standard Router, based on SQLITE databases. And to make things even easier this Router looks for a predefined SQLITE file within the working directory.
Of course, I also provide a way to change this default entry just in case and because of this I check if this file exist and trigger an error if it doesn't.
And this is the specific error I'm seeing. The checking routine is like this:
if( ! file_exists( $this -> options -> dbPath ) ) {
throw RouterException::connectionFailure(
'Routes Database File %s doesn\'t exist in Data Directory',
array( $this -> options -> dbPath )
);
}
The dbPath entry, if not changed, uses a constant value Data/Routes.sqlite, relatively to working directory.
If, again, again, I set the absolute path manually, everything (really) works, the the Request flow reached the Action Controllers successfully.
What's going on?
This a bug in PHP's built-in web server that is still not fixed, as of PHP version 5.6.30.
In short, the web server does not redirect to www.foo.com/bar/ if www.foo./bar was requested and happens to be a directory. The client being server www.foo.com/bar, assumes it is a file (because of the missing slash at the end), so all subsequent relative links will be fetched relative to www.foo.com/instead of www.foo.com/bar/.
A bug ticket was opened back in 2013 but was mistakenly set to a status of "Not a Bug".
I'm experiencing a similar issue in 2017, so I left a comment on the bug ticket.
Edit : Just noticed that #jens-a-koch opened the ticket I linked to. I was not awar of his comment on the original question.