linux bash string replace - regex

The actual requirement here is to replace some tags in an nginx server block with values at runtime, fairly standard stuff:
server {
listen 80;# default_server;
root <sitepath />/<sitename />/sitefiles/public;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
index index.php index.html index.htm;
server_name <sitename />;#<- server_domain_or_$
error_log <sitepath />/<sitename />/platform_dir/logs/nginxerror.log;
access_log <sitepath />/<sitename />/platform_dir/logs/nginxaccess.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/run/php/php7.0-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_read_timeout 60;
include fastcgi_params;
}
}
I have loaded the file into $block and wish to substitute the tag <sitepath /> with the value of the variable $wwwrooot. While testing with
echo "$block" | sed -r "s/<sitepath \/>+/$wwwroot/g"
I get the error
sed: -e expression #1, char 19: unknown option to `s'

I'm gonna go out on a limb and assume $wwwrooot contains slashes.
That's gonna be a problem for your sed command, as you've chosen slashes as regex separators. Using a different character (one that's unlikely to be part of your $wwwrooot, e.g. #) should fix that:
echo "$block" | sed -r "s#<sitepath />#$wwwroot#g"

Related

How to serve images from a different root when a certain page of the website. Nginx

I don't have much experience with regex, and less in an Nginx context, so this one is a difficult one for me.
What I want is that when I'm on a especific page (not subfolder) the server takes images from a different root.
My current configuration to handle images in all the pages of my website right now is this one.
location ~* \.(png|jpg|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media;
}
And I'd like that when I'm in the page example.com/My-Profile the server handles the images from /usr/share/nginx/nginxTestPHP/media/uploads, my idea is something like this, if it makes any sense.
location ~* /My-Profile/*\.(png|jpg|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media/uploads;
}
Obviously this one doesn't work otherwise I wouldn't be here asking this, so for the regex pros out there, what would be the solution for this one ?
Also how would I apply this in 2 different pages in the same regex, something like (My-Profile|Configuration) is my idea.
My Nginx configuration
server {
listen 81;
listen [::]:81;
server_name IP;
client_max_body_size 4M;
charset UTF-8;
include /etc/nginx/mime.types;
error_log /var/log/nginx/error_log warn;
access_log /var/log/nginx/access_log main;
rewrite ^(/.*)\.html(\?.*)?$ $1$2 permanent;
rewrite ^/(.*)/$ /$1 permanent;
root /usr/share/nginx/nginxTestPHP/PHP;
index index.html index.htm Inicio.php Index.php;
location / {
try_files $uri/index.html $uri.html $uri/ #extensionless-php;
}
location #extensionless-php {
rewrite ^(.*)$ $1.php last;
}
# pass the PHP scripts to FastCGI
location ~ \.php$ {
try_files $uri =404;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Inicio.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /vendor/ {
deny all;
return 403;
}
# deny access to .htaccess files
location ~ /\.ht {
deny all;
}
location ^~ /en/ {
try_files $uri/.php $uri.php $uri/ #rewrite;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location ^~ /Blog/ {
try_files $uri/.php $uri.php $uri/ #rewrite;
fastcgi_intercept_errors on;
fastcgi_pass app:9000;
fastcgi_index Index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include fastcgi_params;
}
location #rewrite {
rewrite ^/(en|Blog)(/.*\.(png|jpg|svg|ico))$ $2 last;
return 404;
}
location ~ \.css {
root /usr/share/nginx/nginxTestPHP/CSS;
default_type text/css;
add_header Content-Type text/css;
}
location ~ \.js {
root /usr/share/nginx/nginxTestPHP/JavaScript;
default_type text/javascript;
add_header Content-Type application/x-javascript;
}
location ~ \.txt {
root /usr/share/nginx/nginxTestPHP/PHP;
}
location ~* ^/Mi-Perfil/([^/]+\.(png|jpg|jpeg|gif))$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads/$1;
}
location ~* \.(png|jpg|svg|ico|jpeg|gif) {
root /usr/share/nginx/nginxTestPHP/media;
}
error_page 405 =200 $uri;
# redirect server error pages to the static page /50x.html
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/nginxTestPHP/PHP;
try_files $uri /Inicio.php;
}
}
Your regex is broken, it is a dot (.) in PCRE patterns that acts as a wildcard, not an asterisk one. If you want to match any non-zero number of characters except a / one, you can use [^/]+ regex pattern:
location ~* /My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ { ... }
or to ensure that an URI started exactly with /My-Profile/ add a ^ anchor (matches start of the string):
location ~* ^/My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ { ... }
Check the difference between root and alias nginx directives. With your configuration nginx will search the files inside the /usr/share/nginx/nginxTestPHP/media/uploads/My-Profile folder. Use an alias directive instead:
location ~* ^/My-Profile/[^/]+\.(png|jpg|jpeg|gif)$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads;
}
Update
I think I made a serious mistake. Since this is a regex matching location an alias directive argument should contain full path to image file with filename:
location ~* ^/My-Profile/([^/]+\.(png|jpg|jpeg|gif))$ {
alias /usr/share/nginx/nginxTestPHP/media/uploads/$1;
}
Little experience with Nginx here but the regex part looks relatively simple to fix - try using:
location ~* /My-Profile/.+\.(png|jpg|jpeg|gif)$ {
root /usr/share/nginx/nginxTestPHP/media/uploads;
}
Note the .+ after My-Profile/ and the end-of-string anchor ($) - I'm assuming you want to only match images, not a URI like stackoverflow.com/test.png/somepage.
From the little research I did, you may also want to look into nginx maps, especially if you're looking to do this for multiple profile pages all following the same URI pattern.

In NGINX remove .html extension from URI without redirect

I'm trying to modify my NGINX config to strip the .html extension from URI's before they are passed to my PHP based CMS.
In other words when a visitor enters:
http://www.example.com/foo.html
I want the URI to be changed to/;
http://www.example.com/foo
Without doing an actual browser redirect. This is easy enough to accomplish in Apache, but I can't seem to crack the nut in NGINX. Here is what I have in my config file that doesn't seem to work.
location ~ \.html {
rewrite ^(/.*)\.html(\?.*)?$ $1$2 last;
}
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param SCRIPT_FILENAME $request_filename;
}
Using this code the REQUEST_URI that PHP picks up is still /foo.html.
Possible answer to my own question, or at least a workaround.
So apparently $request_uri is always going to contain the original URI, not the rewrite - that is contained in $uri. So to workaround this I'm using a variable to store and pass the modifed URI to PHP. I'm not really thrilled with this solution though.
location ~ \.html {
rewrite ^(/.*)\.html(\?.*)?$ $1$2 last;
}
location / {
set $new_uri $uri
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
include fastcgi_params;
fastcgi_param REQUEST_URI $new_uri;
fastcgi_param SCRIPT_FILENAME $request_filename;
}

Nginx remove '?' symbol before extension

I managed to make my index.php script to run properly when I get a url like:
http://myserver.com/?something.m3u8
Still, I need to remove the ? from it.
Any ideas?
My Nginx config looks like:
server {
listen 6868 default_server;
root /var/tmp/mfl;
index index.php;
# Make site accessible from http://localhost/
server_name localhost;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Apparently is was an one line solution
location / {
try_files $uri $uri/ /index.php?$args; #appended this line
}

Nginx regular expression fails

When I visit the http://example.com or http://example.com/index.html still goes to handleURL.html
This is what I have
server {
listen 80;
listen [::]:80;
root /var/www/vhosts/example.com/public;
index index.html;
server_name example.com www.example.com;
access_log /var/log/nginx/example.com/access.log;
error_log /var/log/nginx/example.com/error.log;
rewrite "^/([a-z0-9]{4,8})$" /forward.php?shortcode=$1;
rewrite "^/.{10,500}$" /handleURL.html;
location / {
try_files $uri $uri/ /index.html;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
I want to display different html file if the url has characters between 10,500.
Nginx might not care but it looks like the regular expression should not be in quotes. Unless your going to use the entered string in your replacement url you don't need to capture it, so the parenthesis are unnecessary.
If you want to choose a different file for each string you can use the captured string in the replacement string. e.g. rewrite "^/(.{10,500})$" /wiki/$1 last; would match example.com/agreatpage.html and turn it into example.com/wiki/agreatepage.html
To simply redirect to another page based on length something like rewrite "^/.{10,500}$" /Redirect.html last; should work
References:
http://nginx.org/en/docs/http/ngx_http_rewrite_module.html
Edit:
After further reading nginx is okay if the regular expression is enclosed in double quotes and you must do so if the expression contains { or }, otherwise the parser misinterprets these as opening a block and closing a block.
Edit2:
The only problem I see at the moment is:
rewrite "^/([a-z0-9]{4,8})$" /forward.php?shortcode=$1;
rewrite "^/.{10,500}$" /handleURL.html;
to the best of my knowledge should be:
rewrite "^/([a-z0-9]{4,8})$" /forward.php?shortcode=$1 last;
rewrite "^/.{10,500}$" /handleURL.html last;
The only way I can fix this remove all the rewrites and add index.php and pass everything to index.php I ended up with the following configuration.
server {
listen 80;
listen [::]:80;
root /var/www/vhosts/example.com/public;
index index.php index.html;
server_name example.com www.example.com;
log_format compression '$host - $remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" "$gzip_ratio"';
access_log /var/log/nginx/example.com/access.log compression;
error_log /var/log/nginx/example.com/error.log;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
try_files $uri /index.php =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Thank you guys!

Redirect an old php file to a new URL using Nginx

I have a website with URLs corresponding to PHP files:
www.mysite.com/cat.php?id=stuff
These PHP files don't exist anymore, how can I do a 301 redirect (for SEO reasons) to the new URL :
www.mysite.com/stuff
I tried
rewrite ^/cat\.php\?id=stuff http://www.mysite.com/stuff? permanent;
But it does not work, I get a "No input file specified".
Thank you for your help!
EDIT:
More about my config (website is powered by Wordpress):
index index.php;
root /var/www/mydirectory;
location / {
try_files $uri $uri/ /index.php?q=$uri&$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}
The issue is that you've added a ? to the end of your rewritten directory, so nginx is telling PHP to serve http://yourdomain.com/stuff?/index.php which doesn't exist.
Assuming mysites.com was a typo and you're redirecting to the same domain, try this:
rewrite ^/cat\.php\?id=(.*)$ /$1/ permanent;
There are a lot of issues with using rewrite and try_files together, I have a working config using these, something like:
I think the rule is that your rewrite rule has to come before try_files, so try this:
index index.php;
root /var/www/mydirectory;
location = / {
rewrite ^/cat\.php\?id=(.*)$ /$1/ permanent;
}
location ^(.*)$ {
try_files $uri $uri/ /index.php?$1;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
include fastcgi_params;
}