Symfony does not detect relative url root - apache2

In symfony 1.4 in settings.yml we are using the option:
env:
request:
param:
relative_url_root: /name-of-app
to specify which relative_url_root an app uses. So every app runs under a different relative_url_root.
The problem is that symfony 1.4 routing does not detect this relative url root. So for example if we have the following route:
route_name:
url: /some-module/some-action
param: { module: somemodule, action: someaction }
And we try to access http://myproject.local/name-of-app/some-module/some-action symfony tries to search for a route name which matches name-of-app/some-module/some-action instead of /some-module/some-action.
Also symfony now tries link to images using this relative_url_root, therefore images are not found anymore. Because images are only reachable via http://project.local/img/.. instead of http://project.local/name-of-app/img
What is the best way to solve this?
Should I remove a '/' somewhere?
Should I use RewriteBase somehow in htaccess?
Should I strip 'name-of-app' in the REQUEST_URI using htaccess?
Prefix every routing url with name-of-app/?
Should I in someway tell apache that /name-of-app is some kind of path or prefix? Note that in our production environment we are not able to create virtual hosts so we have to solve this using .htaccess or symfony itself.
A very different solution.

I'm not sure if the relative_url_root is what you're really after. As the documentation states:
relative_url_root
The relative_url_root option defines the part of the URL before the front controller. Most of the time, this is automatically detected by the framework and does not need to be changed.
So it is part of the URL before index.php or frontend_dev.php, etc.
What you could do, in my opinion, is to write your own Routing class which will extend the sfPatternRouting and have it remove the prefix part of your URLs before trying to match any route. Then use this class for routing in factories.yml.
EDIT: I somehow missed the fact that you operate between different applications.
In general the relative_url_root is definitely not a good idea to separate calls to different apps. The best way, in my opinion, would be to use separate front controllers and Virtual Hosts to have different subdomains. Unfortunately you say you cannot go for this option.
You could then go for either of the solutions:
Fiddle with .htaccess and have it redirect your calls to a proper front controller: myurl.com/path-to-app1/something will call app1.php/something and myurl.com/path-to-app2/something will call app2.php/something.
Change the index.php file. Have it catch the first part of URL (path-to-app/) and based on it's value load the configuration for the proper app (e.g. $configuration = ProjectConfiguration::getApplicationConfiguration('app2', 'prod', false);)
You would then have to change your routes to take into consideration that there is this first part of URL (e.g. have all your routes start with a :path-to-action variable which will be passed to functions generating URLs), or use a parameter defined in config:
.
In apps/app1/config/app.yml
path_to_app: app1
In apps/app1/config/routing.yml
route1:
url: <?php echo sfConfig::get('app_path_to_app') ?>/something
...

Fix for the routing:
I changed my .htaccess as follows.
RewriteCond %{HTTP_HOST} myproject.local
RewriteCond %{THE_REQUEST} /name-of-app* [NC]
RewriteRule ^(.*)$ dispatcher.php/$1 [QSA,L]
By using this rewrite rule symfony seems to recognize that /name-of-app is a prefix in the routing and somehow matches this on the relative_url_root. Now when I var_dump the sfRoute object in the controller I get the following.
object(sfRoute)[33]
protected 'isBound' => boolean true
protected 'context' =>
array (size=7)
'path_info' => string 'some-module/some-action' (length=10)
'prefix' => string '/name-of-appp' (length=8)
'method' => string 'GET' (length=3)
'format' => null
'host' => string 'myproject.local' (length=20)
'is_secure' => boolean true
'request_uri' => string 'https://myproject.local/name-of-app/some-module/some-action' (length=47)
Note that I did not change the routing rules as Michal suggested. Also I believe my approach with the relative_url_root is not really that strange as Symfony understands it.
Fix for direct file access:
In order to redirect a request like https://myproject.local/name-of-app/some/path/to/a/file.ext to https://myproject.local/some/path/to/a/file.ext I used the following directives.
RewriteCond %{REQUEST_URI} \..+$
RewriteCond %{REQUEST_URI} !\.html$
RewriteCond %{REQUEST_URI} ^/name-of-app
RewriteRule ^name-of-app/(.*)$ https://myproject.local/$1 [L]

Related

Is there a way to configure Apache to auto-recognize URLs for Django vs React without hard-coding each endpoint?

We're using Apache 2.4 with React 17 and a Django 3.2 (Python 3.9) application. Curious about a better way to set up our Apache configs to route requests to the React and Django apps. Right now, our Apache virtual hosts file hard-codes which routes need to be handled by the React app vs which need to be handled by Django ...
AliasMatch ^/(?!people)(?!states/)(?!countries/)(?!predefined_types/)(?!coop_types/)(?!coops/)(?!data)(?!save_to_sheet_from_form).* /var/www/html/client/build/$0
<Directory "/var/www/html/client/build/">
Options Indexes FollowSymLinks
AllowOverride all
</Directory>
WSGIDaemonProcess ssl_directory home=/var/www/html/web python-home=/var/www/html/web/venv
WSGIProcessGroup ssl_directory
WSGIScriptAlias /coops /var/www/html/web/directory/wsgi.py/coops process-group=ssl_directory
WSGIScriptAlias /data /var/www/html/web/directory/wsgi.py/data process-group=ssl_directory
WSGIScriptAlias /countries /var/www/html/web/directory/wsgi.py/countries process-group=ssl_directory
WSGIScriptAlias /states /var/www/html/web/directory/wsgi.py/states process-group=ssl_directory
WSGIScriptAlias /predefined_types /var/www/html/web/directory/wsgi.py/predefined_types process-group=ssl_directory
WSGIScriptAlias /coop_types /var/www/html/web/directory/wsgi.py/coop_types process-group=ssl_directory
WSGIScriptAlias /people /var/www/html/web/directory/wsgi.py/people process-group=ssl_directory
WSGIScriptAlias /save_to_sheet_from_form /var/www/html/web/directory/wsgi.py/save_to_sheet_from_form process-group=ssl_directory
The Django app, for its part, defines urls in the standard way (in our urls.py file) ...
...
urlpatterns = [
path('data', views.data, name='data'),
path('coops/no_coords', views.coops_wo_coordinates, name='coops_wo_coordinates'),
path('coops/unapproved', views.unapproved_coops, name='unapproved_coops'),
path('coops/', views.CoopList.as_view()),
path('coops/<int:pk>/', views.CoopDetail.as_view()),
path('people/', views.PersonList.as_view()),
path('people/<int:pk>/', views.PersonDetail.as_view()),
path('users/', views.CreateUserView.as_view()),
path('predefined_types/', views.CoopTypeList.as_view()),
path('coop_types/', views.CoopTypeList.as_view()),
path('countries/', views.CountryList.as_view()),
path('states/<country_code>', views.StateList.as_view()),
path('login', views.signin),
path(settings.LOGOUT_PATH, views.signout),
path('user_info', views.user_info),
]
urlpatterns = format_suffix_patterns(urlpatterns)
Is there a more automated way we can get Apache to know what routes shoudl go to Django vs React? Whenever we add a new Django endpoint, we have to add a hard-coded exception in our Apache configs.
Edit: Here is an example how I make a React call to the API ...
const { REACT_APP_PROXY } = process.env;
class PersonService {
getById(id, callback) {
fetch(REACT_APP_PROXY + "/people/" + id)
.then((response) => {
return response.json();
})
.then((data) => {
const person = data;
person.contact_methods.map((contact_method) => {
if (contact_method.type == "PHONE") {
person.phone = contact_method.phone.substring(2);
} else if (contact_method.type == "EMAIL") {
person.email = contact_method.email;
}
});
if (callback) callback(person);
});
}
}
Concerning python there are two wsgi-options that could help you to reduce the required lines and steps.
Using the WSGIScriptAlias directive to map to a directory containing
any number of WSGI applications:
WSGIScriptAlias /wsgi/ /usr/local/wsgi/scripts/
When this is used, the next part of the URL after the URL prefix is
used to identify which WSGI application script file within the target
directory should be used. Both the mount point and the directory path
must have a trailing slash.
Another option is intended primarily to suppress the extension in the
Frontend but could be used too to redirect based on different aspects:
WSGIScriptAliasMatch ^/wsgi/([^/]+) /usr/local/wsgi/scripts/$1.wsgi
In this case, any path information appearing after the URL prefix, will be mapped to a corresponding WSGI script file in the directory, but with a ‘.wsgi’ extension. The extension would though not need to be included in the URL.
The options can be configured with common Apache directives too, and there are additional features like directory index can be configured like that, it's useful to read this page about all the options: https://modwsgi.readthedocs.io/en/master/user-guides/configuration-guidelines.html
Furthermore you've the option to use the powerful mod_rewrite. Certainly there are many more options, most important is that to distinguish between script-types you've to have some aspect in the url or path to decide where to redirect. It can be a suffix and / or usage of WSGIScriptAlias which both would be most simple but could be based on mod_mime perhaps too.
So actually the question in return is how far you're willing to use suffixes or URLs that make a distinction possible and easy enough to be handled by the offered options.
One aspect to consider is that a python app can reference js-files too, so simply a suffix might not be enough but if full paths are provided that's perhaps not too difficult to handle.
With mod_rewrite you have full control over redirection and remapping in Apache
Redirecting and Remapping with mod_rewrite
You should implement something like this:
RedirectMatch "^/docs/(.*)" "http://new.example.com/docs/$1"
or
RewriteRule ^images/([^/]+)$ /assets/images/public/$1 [L]
That redirects each part of application documents to its corresponding handler.
RedirectMatch "^/react-docs/(.*)" "http://react-handler.example.com/react-docs/$1"
As you see you need something in your URL that RedirectMatch or RewriteRule uses Regex on it for separating and sending each document to corresponding handler.
Q&As on mod_rewrite

Apache 2 /httpd vhost dynamic documentroot

I have an app in folder /var/www/test
Also there is an "sub-app" in folder /var/www/test/subapp (There is another index.php inside
If user will type test.com the index.php of test should trigger but when user type test.com/triggersubapp the index,php from /var/www/test/subapp shall run.
I failed to create correct statements and RewriteRules and I haven't got much time left. So have any one of You know how to do this easiest way or maybe have a correct definition?
I would greatly appreciate it !!!
EDIT
The main index.php and .htaccess are in /var/www/test/public/. :(
Put this in your .htaccess in root directory:
RewriteEngine On
RewriteRule ^triggersubapp/?$ subapp/index.php
This will rewrite triggersubapp to subapp/index.php which means if user enters test.com/triggersubapp he/she will see result for test.com/subapp/index.php

Joomla 3.x Multilanguages RewriteRule

I have an issue. I set up my joomla 3.3.x with multilanguages.
URL how it appears in the browser:
www.example.com/%LANG%/folder1/module1/images/img.png
%LANG% stands for de, en, ...
And now the actually path where my image is(this is just an example, images/files could be anywhere):
www.example.com/folder1/module1/images/img.png
I thought about a rewrite rule which should get this work.

Routes and Path in CakePHP

i am currently dvelpping a website for a friend and i have a strange issue.
Let me first say i am rather a non experienced developper and I cant seem to find a solution:
I've localized my websites in different languages you can watch it here:
http://parfum-poudre.fr/en (in English) it works fine
but if you go to http://parfum-poudre.fr/en/ the paths are messed up and some pics don't appear...
for example there is a professional sapce on this website but then if you go back on the public space i have the same issue...
anyone ha s anything to say about that ?
Thanks
Have added your images, scripts and styles using normal HTML tag in layout file?
This can be one issue.
You can add images,scripts and styles to your layout file using
<?php
echo $this -> Html -> css('style');
echo $this -> Html -> script('jquery');
echo $this -> fetch('css');
echo $this -> fetch('script');
?>
<?php echo $this->Html->image('logo2.png', array('url' => '/ProjectName/','alt'=>'Logo')); ?>
Add this to your app_helper.php
class AppHelper extends Helper {
function url($url = null, $full = false) {
$routerUrl = Router::url($url, $full);
if (!preg_match('/\\.(rss|html|js|css|jpeg|jpg|gif|png|xml?)$/', strtolower($routerUrl)) && substr($routerUrl, -1) != '/') {
$routerUrl .= '/';
}
return $routerUrl;
}
}
The AppHelper stuff goes in the app_helper.php file located in HTDOCS/PROJECT/APP folder (APP ROOT). If the file doesn't exits, create one.
And edit your .htaccess to
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ http://domain.com/$1/ [L,R=301]
The .htaccess code goes in the .htaccess file in HTDOCS/PROJECT/APP/WEBROOT folder (APP ROOT/WEBROOT). Just replace the original contents and make sure you change domain.com to whatever your domain is.

CakePHP 2.1 new install Missing Controller Error

I am completely new to CakePHP and installed 2.1. I am getting this error:
Missing Controller
Error: Index.phpController could not be found.
Error: Create the class Index.phpController below in file: app\Controller\Index.phpController.php
<?php
class Index.phpController extends AppController {
}
Notice: If you want to customize this error message, create app\View\Errors\missing_controller.ctp
Stack Trace
APP\webroot\index.php line 96 → Dispatcher->dispatch(CakeRequest, CakeResponse)
ROOT\index.php line 40 → require(string)
I followed their guide at http://book.cakephp.org/2.0/en/installation/advanced-installation.html and tried everything it stated:
I enabled mod_rewrites (they were already enabled from something else)
I have all the .htaccess files in the directories
I have cake installed under my document root so I access it at localhost/cakephp/index.php
I do not know where to proceed from here. Thanks for any help you can give me.
Update: I just re-read your question and realized you're loading http://localhost/cakephp/index.php. Don't do that. Since you appended "index.php", it is trying to load a controller called "index.php" and the action "index" for that controller. Resulting mapped path to the "index.php controller" is app\Controller\Index.phpController.php.
Since you have the rewrites enabled, browse to http://localhost/cakephp without appending any filename.
Original answer:
Assuming you're using Apache, double-check the .htaccess in your /app/webroot directory. It should include the following:
RewriteRule ^(.*)$ index.php?/$1 [QSA,L]
Based on your error, it doesn't look like it's properly appending the path after your index.php file.
If you are using cakephp 2.0 or greater than rename the controller file name as the class name.
ie TaskController.php
class TasksController extends AppController {
--Your code inside class
}
I hope this will help you
the easiest solution is to stick to the "live environment" as close as possible.
this means using vhosts to use a "domain" and correctly root down to your webroot dir:
http://www.dereuromark.de/2011/05/29/working-with-domains-locally/
this leaves almost no room for error and also helps with other potential problems like "absolutely linked asset files" etc

Resources