Apache rewrite requests to build/public folder with .htaccess - apache

I often have projects that produce some sort of output folder, usually named build or public or something like that. But if I deploy my entire project to an Apache web server, in order to route to the actual project you would have to do it like this: https://example.com/user/project/build/file.
To simplify and shorten the url, how can I rewrite requests in a .htaccess file so that if google for user/project/file it automatically routes it to user/project/build/file?

The best usually is to place only those files under the DOCUMENT_ROOT that are actually meant to be directly published by the http server. That also typically simplifies the URL to access them. The rest of the files, scripts and ressources should be kept outside the DOCUMENT_ROOT. You can still access them inside your application logic.
Sometimes this is not possible though. For example if you are using a cheap hosting service instead of operating your own http server. In such case request rewriting comes in as an alternative. In this situation you also typically have to rely on distributed configuration files (".htaccess") instead of being able to use the usual http server's host configuration. That comes with a few disadvantages, but sometimes it is your only option.
Have a try using such an implementation:
RewriteEngine on
RewriteRule ^/?user/project/build/(.*)$ /user/project/$1 [R=301,L]
RewriteRule ^/?user/project/(.*)$ /user/project/build/$1 [END]
This relies on the rewriting module being loaded and activated in the http server, obviously. And also the usage of distribute configuration files needs to be enabled for the http host and the requested location.
Always test using a fresh anonymous browser instance (to prevent caching issues in your tests). It also makes sense to start out using a R=302 temporary redirection first and only to change that to a R=301 permanent redirection once everything works as expected.

Related

Apache: .htaccess vs vhost conf file for blocking URLs

I need to block some uld URLs that are generating a lot of traffic in my web server (Apache). For example to block all the requests like https://example.com/xxxxxx/
I Can't do that with IPtables so I am using mod_rewrite with a rule in my .htaccess
That is still consuming a lot of resources and I am wondering if there is a better way to block the request before reaching Apache. Or another most efficient way to do it within Apache. For example, I heard that parsing .htaccess files consumes resources so not sure if using the vhost .conf file can help or it is really the same...
Any advice on how can I block requests using the URL?
Thank you experts!
Certainly distributed configuration files consume more load than a single, central and static configuration. But the differences are not like day and night. The issue with a distributed configuration is more the effort to keep the overview, to maintain it.
If you can keep those requests away from the http server at all you certainly will see more difference. You could consider using a frontend server. Something like nginx or HAProxy that acts as a gate keeper and only forwards those requests you actually want to respond to. This makes little sense on a single system though, you'd need two separate cloud services or even systems for that.
The best approach would be to add something like this to your httpd / vhost.conf file:
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/xxxx$
RewriteRule ^ - [F]
Every call to /xxxx would result in mod_rewrite to return a 403 response.
Make sure to place those rules into the according vhost tag.

How to make a pretty URL using .htaccess

I am creating my whole application with .html extension, to play with the database I am using jQuery Ajax. I have created the project structure like WordPress, for each file I am having a folder and inside that folder I am having an index.html file.
In the above picture, I have created user/equipment/index.html, in this file all the equipment are being shown, now I want that if user clicks on an equipment then the URL should be like 'domain.com/user/equipment/equipment-title' and the file should be called user/equipment/details/index.html
I believe that this can be done with a .htaccess file.
Any solution for the problem would be much appreciated.
Well, you need to store the references in that index file the way you want them to be, request rewriting (wo which you refer as ".htaccess") cannot do that for you. Why you can do with request rewriting, so inside a distributed configuration file (".htaccess") is to the internally rewrite the incoming requests. For that you need a mapping from request URLs to your detail pages. If the mapping the simply the name as to be found in the "equipment" folder (this is unclear from your question), then you indeed can simply implement a rewriting rule.
This would be such an example:
RewriteEngine on
RewriteRule ^/?user/equipment/(.*)/?$ /equipment/$1 [END]
This will deliver the content of the file /equipment/equipment-title when the URL https://example.com/user/equipment/equipment-title gets requested and that file exists.
For this to work the rewriting module has to be enabled inside your http server and, if you want to use a distributed configuration file for this, the interpretation of such files also needs to be enabled for that location inside your http server. Usually the better alternative is to place such rules in the real http server's host configuration, though.

apache .htacces configuration

I'm following the symfony create your own mvc tutorial and I'm at a loss as to how to configure my apache server to point to the web directory.
Following the tutorial. My file structure has pages in the src folder, composer in the vendor folder and my front.php in the web folder with the associated routes. If I go to web/front.php all works fine.
How do I configure the .htaccess file?
Generally it is recommended not to use dynamic configuration files (".htaccess"), but to place rewriting rules inside the host configuration itself (performance and maintainability reasons). You will find tons of examples for such internal rewritings here on SO, your best starting point to read into that however certainly is the official documentation. It comes with great examples: http://httpd.apache.org/docs/current/mod/mod_rewrite.html
This is a simple example that should point you into the right direction:
RewriteEngine on
RewriteRule ^/?projectname/(.*)/?$ /web/front.php?variable=$1 [L]
That will take care to internally rewrite the request so that you can access the variable value as $_GET['variable'].
The example uses a pattern that will work likewise in dynamic configuration files (".htaccess") and in the real http servers host configuration. If you really want to use dynamic files, then you also need to enable their interpretation by means of the AllowOverride directive. Again take a look at the official documentation for that: https://httpd.apache.org/docs/2.4/mod/core.html#allowoverride

Aliases on Dreamhost, general management of http request / server errors

I had a hard time deciding how I should manage these errors (404, 500, ...) and when I finally decided, I am encountering problems. This is a reeeeeally long question, I appreciate anyone's attempt to help!
Let me first describe how I decided to set it up. I have several sites hosted on a shared Dreamhost account. In the folder structure that I see, everything of mine on the server is under /home/username, and for example, site1.com's web root is at /home/username/site1.com
I am creating a generic error handler (php script) for errors like 404 not found, 500, etc. that I want to store above the web roots of my sites at /home/username/error_handler/index.php so that I can use an .htaccess file at /home/username/.htaccess which includes something like the following:
ErrorDocument 404 /error_handler/index.php
ErrorDocument 500 /error_handler/index.php
...and many more
When these errors occur on any of my sites, I want it to be directed to /home/username/error_handler/index.phpThis is the problem I'm having a hard time figuring out. The ErrorDocument directives above will actually cause Apache to look for /home/username/site1.com/error_handler/index.php
Anyway, the errors should be redirected to my error handling php script. The script will use $_SERVER['REDIRECT_STATUS'] to get the error code, then use $_SERVER['REDIRECT_URL'] and $_SERVER['HTTP_HOST'] to decide what to do. It will check if an error handler specific to that site exists (for example: site1.com/errors/404.php). If this custom page doesn't exist, it will output a generic message that is slightly more user-friendly and styled, and perhaps will include some contact info for me depending on the error.
Doing it this way lets me funnel all these errors through this 1 php script. I can log the errors however I like or send email notifications if I want. It also lets me set up the ErrorDocument Apache directives once for all my sites instead of having to do it for every site. It will also continue to work without modification when I move the site around, since I already have a system that scans the folder structure to figure out where my site roots are when they really aren't at the web root technically speaking. This may not be possible with other solutions like using mod_rewrite for all 404 problems, which I know is common. Or if it is possible, it may be very difficult to do. Plus, I have already done that work, so it will be easy for me to adapt.
When I am working on sites for which I don't have a domain name yet (or sites where the domain name is already in use at the moment), I store them temporarily in site1.com/dev/site3.com for example. Moving the site to site3.com eventually would cause me to have to update the htaccess files if I had one for each site. Changing the domain name would do the same.
Ex: a site stored at site1.com/dev/site3.com would have this in its htaccess file:
ErrorDocument 404 /site1.com/dev/site3.com/error/404.php
And it would have to be changed to this:
ErrorDocument 404 /site3.com/error/404.php
Obviously, this isn't a huge amount of work, but I already manage a lot of sites and I will probably be making more every year, 95% of which will be hosted on my shared DreamHost account. And most of them get moved at least once. So setting up something automatic will save me a some effort in the long run.
I already have a system set up for managing site-relative links on all my sites. These links will work whether the site exists in a subdirectory of an existing site, or in their own domain. They also work without change in a local development server despite a difference in the web root location. For example, on the live server, the site-relative http link /img/1.jpg would resolve to the file /home/username/site1.com/img/1.jpg while on my local development server it would resolve to C:\xampp\htdocs\img\1.jpg, despite what I consider the logical site root being at C:\xampp\htdocs\site1.com. I love this system, and it is what gave me the idea to set up something that would work automatically like I expected it to, based on the file structure I used.
So, if I could get it to work, I think this seems like a pretty good system. But I am still very new to apache configuration, mod_rewrite, etc. It's possible there is a much easier and better way to do this. If you know of one, please let me know.
Anyway, all that aside, I can't get it working. The easiest thing would be if I could have the ErrorDocument directive send the requests to folders above the web root. But the path is a URL path relative to the document root. Using the following in /home/username/.htaccess,
ErrorDocument 404 /error_handler/index.php
a request for a non-existent resource causes Apache to look for the file at
site1.com/error_handler/index.php
So I thought I should set up a redirection (on all my sites) that would redirect those URLS to /home/username/error_handler. I tried a few things and couldn't get any of them to work.
Alias seemed like the simplest solution, but it is something that has to be set at server runtime (not sure if that is the right terminology - when the server is started). On my local server, it worked fine using:
Alias /error_handler C:\xampp\htdocs\error_handler2
I changed the local folder to test that the Alias was functioning properly. (On the local server, the URL path specified by the ErrorDocument directive is actually pointing to the right folder, since in my local server the web root is technically C:\xampp\htdocs and I store the error handler I want to use is stored locally at C:\xampp\htdocs\error_handler\index.php)
Dreamhost has a web client that can create what I am guessing is an Alias. When I tried to redirect the folder error_handler on site1.com to /home/username/error_handler, it would seem to work right if I typed site1.com/error_handler in the browser. But if I typed site1.com/test1234 (non-existant), it would say there was a 404 error trying to use the error handler. Also, I would have to login through the web client and point and click (and wait several minutes for the server to restart) every time I wanted to set this up for a new site, even if I could get it to work.
So I tried getting it to work with mod_rewrite, which seems like the most flexible solution. My first attempt looked something like this (stored in /home/username/site1.com/.htaccess for now, though it would eventually be at /home/username/.htaccess:
RewriteEngine On
RewriteRule ^error_handler/index.php$ /home/username/error_handler/index.php
The plain english version of what I was trying to do above is to send requests on any of my sites for error_handler/index.php to /home/username/error_handler/index.php. The mis-understanding I had is that the subsitution will be treated as a file path if it exists. But I missed that the documentation says "(or, in the case of using rewrites in a .htaccess file, relative to your document root)". So instead of rewriting to /home/username/error_handler/index.php, it's actually trying to rewrite to /home/username/site1.com/home/username/error_handler/index.php.
I tried including Options +FollowSymLinks because in the Apache documentation it says this:
To enable the rewrite engine in this context [per-directory re-writes in htaccess], you need to set "RewriteEngine On" and "Options FollowSymLinks" must be enabled. If your administrator has disabled override of FollowSymLinks for a user's directory, then you cannot use the rewrite engine. This restriction is required for security reasons.
I searched around for a while and I couldn't find anything about how Dreamhost handles this (probably because I don't know where to look).
I experimented with RewriteBase because in the Apache documentation it says this:
"This directive is required when you use a relative path in a substitution in per-directory (htaccess) context unless either of the following conditions are true:
The original request, and the substitution, are underneath the DocumentRoot (as opposed to reachable by other means, such as Alias)."
Since this is supposed to be a URL path, in my case it should be RewriteBase /, since all my redirects will be from site1.com/error_handler. I also tried Rewrite Base /home/username and RewriteRule ^error_handler/index.php$ error_handler/index.php. However, the Rewrite Base is a URL path relative to the document root. So I need to use something like an alias still. The implication in the quote from the documentation above is that it is possible to use mod_rewrite to send content above the web root. One of the many things I don't know is what the 'other means' besides Alias might be. I believe Alias might not be an option on Dreamhost. At least I couldn't make sense of it.
Why not use error pages in the site root, then include the actual file from the shared section?

How do I rewrite URLs with Nginx admin / Apache / Wordpress

I have the following URL format:
www.example.com/members/admin/projects/?projectid=41
And I would like to rewrite them to the following format:
www.example.com/avits/projectname/
Project names do not have to be unique when a user creates them therefore I will be checking for an existing name and appending an integer to the end of the project name if a project of the same name already exists. e.g. example.project, example.project1, example.project2 etc.
I am happy setting up the GET request to query the database by project name however I am having huge problems setting up these pretty url's.
I am using Apache with Nginx Admin installed which mens that all static content is served via Nginx without the overhead of apache.
I am totally confused as to whether I should be employing an nginx rewrite rule in my nginx.conf file or standard rewrites in my .htaccess file.
To confuse matters further although this is a rather large custom appliction it is build on top of a wordpress backbone for easy blogging functionality meaning that I also have the built in wordpress rewrite module at my disposal.
I have tried all three methods with absolutely no success. I have read a lot on the matter but simply cannot seem to get anything to work. I am certain this is purely down to a complete lack of understanding on with regards to URL rewriting. Combined with the fact that I don't know which type of rewriting should be applicable in my case means that I am doing nothing more than going round in circles.
Can anyone clear up this matter for me and explain how to rewrite my URLs in the manner described above?
Many thanks.
If you are proxying all the non static file requests to Apache, do the rewrites there - you don't need to do anything on nginx as it will just pass the requests to the back end.
The problem with what you are proposing is that it's not actually a rewrite, a rewrite is taking the first URL and just changing it around or moving the user to another location.
What you need actually takes logic to extrapolate the project name from the project ID.
For example you can rewrite:
www.example.com/members/admin/projects/?projectid=41
To:
www.example.com/avits/41/
Fairly easily, but can you map that /41/ in your app code to change it to /projectname/ - because a URL rewrite can't do that.