I have this configuration of nginx + phpfpm + phpmyadmin:
root /var/www/utils;
location ~ ^/phpmyadmin/.*\.(jpg|jpeg|gif|png|css|js|ico)$ {
root /var/www/utils;
}
location = /phpmyadmin {
index index.php;
}
location ~ ^/phpmyadmin.*(\.php|)$ {
index index.php;
fastcgi_index index.php;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
All is good, but if I remove "location = /phpmyadmin", I get 403 error on _http://server/phpmyadmin.
How can I access to the ALL subdirectories such as _http://server/phpmyadmin/setup ?
I get "Access to the script '/var/www/utils/phpmyadmin/setup' has been denied - on every directory without slash at the end, if I haven't written a special config for an each one.
As stated in nginx documentation:
$fastcgi_script_name variable takes value of incoming request URI, and in case URI is finished by a slash, then $fastcgi_script_name is appended with what is defined with fastcgi_index directive.
So if your request is "/phpmyadmin/setup/" and fastcgi_index is set to "index.php", then $fastcgi_script_name variable will be "/phpmyadmin/setup/index.php". Therefore $document_root plus $fastcgi_script_name will be "/var/www/utils/phpmyadmin/setup/index.php", which should work fine.
But if you make request like "/phpmyadmin/setup" (without slash at the end), then $fastcgi_script_name will not be appended by fastcgi_index, i.e. it would be just "/phpmyadmin/setup". And $document_root plus $fastcgi_script_name will be "/var/www/utils/phpmyadmin/setup", which won't work since there is not such file.
You should either use URIs with slashes, or define a rewrite rule (in a "server" block of configuration), which will be adding slash to the URIs that do not end with some extension (so that URIs like "/phpmyadmin/myscript.php" won't transformed into "/phpmyadmin/myscript.php/".
It should be like:
rewrite ^([^\.]*[^\/])$ $1/ break;
Did not test that myself, though.
Related
I developed a site that shows some products from a store. The site URL looks like that:
http://testsite.com
The site has the functionality of sharing the product (it's already working) generating a link that can be shared at facebook or WhatsApp or anywhere. The link of the shared product is:
http://testsite.com/product/1234
Where 1234 is the product ID. All the products have images with the ID name. Ex: 1234.jpg. The link for the image of the product ID 1234 is:
http://testsite.com/static/imgs/1234.jpg
This site is hosted using a simple NGINX server, that just provides the files.
At the head of my index.html file I have a default og:image for sharing:
<meta property="og:image" content="http://testsite.com/static/imgs/main.jpg">
I wanna the NGINX server to replace this default og:image by the shared ID image. I already know how to do that at NGINX. At the NGINX configuration file (/etc/nginx/conf.d/default.conf) I used the sub_filter option. My NGINX configuration file is:
server {
listen 80;
server_name *.testsite.com;
root /var/www/testsite.com/dist;
location / {
try_files $uri $uri/ /index.html;
index index.html index.htm;
}
location ~ /product/(.*) {
index index.html index.htm;
try_files $uri $uri/ /index.html;
sub_filter 'http://testsite.com/static/imgs/main.jpg'
'http://testsite.com/static/imgs/$1.jpg';
sub_filter_once on;
}
}
This configuration is working for the location /, but for the location ~ /product/(.*) it is not working.
When I test the sub_fiter option at the location / using any other image it replaces correctly.
QUESTIONS:
1) How can I get the product ID (1234) from the URL (http://testsite.com/product/1234)? $1 is not working.
2) I think that when entering at the location ~ /product/(.*), it also redirects for the location /. How can I fix this configuration file to works as expected?
I think your alias statement is the problem.
Reading in nginx docs:
location /i/ {
alias /data/w3/images/;
}
on request of “/i/top.gif”, the file /data/w3/images/top.gif will be sent.
It means that in your case on each ~/product/(.*) request /var/www/testsite.com/dist/index.html will be sent without taking product ID into account. You might want to configure alias on / to avoid that. This is also likely to be the reason you get "redirected" to /.
As for $1, it should work as you have it now. When you fix the alias, I think it will work then. If not, you can try the named match: (?<product>[0-9]+) instead of (.*), then you can use the $product variable to reference the id.
There's another small glitch in your code — you're adding extra quote marks on replace. The second argument to sub_filter is in quotes twice.
Working Example
UPDATE: Ok, I got it working on localhost with the following nginx config (testing on "Hello World"):
location ~ /product/(\d+)$ {
set $product $1;
try_files $uri $uri/ /index.html;
}
location / {
if ( $product = '' ) {
set $search 'Non-Existent-String';
}
if ( $product != '' ) {
set $search 'World'; # the string you want to replace
}
index index.html index.htm;
sub_filter '$search' 'Product #$product';
}
The key here is that when you use try_files, it does get to location /. So we need to sub_filter in /. We also don't want to sub_filter regular /index.html requests. Something like if ($product) sub_filter would be nice, but is impossible with nginx. So I just leave sub_filter but only set real search string for product requests.
I'm trying to integrate a Gem named blazer with my Rails application and I have to specify mysql database URL in blazer.yml file so that it can access data in staging and production environments.
I believe the standard format to define MySQL database URL is
mysql2://user:password#hostname:3306/database
I defined my URL in the same format as a string and when I validate the URI I get the below error
URI::InvalidURIError: bad URI(is not URI?):
mysql2://f77_oe_85_staging:LcCh%264855c6M;kG9yGhjghjZC?JquGVK#factory97-aurora-staging-cluster.cluster-cmj77682fpy4kjl.us-east-1.rds.amazonaws.com/factory97_oe85_staging
Defined Mysql database URL:
'mysql2://f77_oe_85_staging:LcCh%264855c6M;kG9yGhjghjZC?JquGVK#factory97-aurora-staging-cluster.cluster-cmj77682fpy4kjl.us-east-1.rds.amazonaws.com/factory97_oe85_staging'
Please advice
The URI is invalid.
The problem is the password contains characters which are not valid in a URI. The username:password is the userinfo part of a URI. From RFC 3986...
foo://example.com:8042/over/there?name=ferret#nose
\_/ \______________/\_________/ \_________/ \__/
| | | | |
scheme authority path query fragment
authority = [ userinfo "#" ] host [ ":" port ]
userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
pct-encoded = "%" HEXDIG HEXDIG
unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
/ "*" / "+" / "," / ";" / "="
Specifically it's the ? in the password LcCh%264855c6M;kG9yGhjghjZC?JquGVK. It looks like the password is only partially escaped.
I think a problem is the issue is not well isolated. Here is an example strategy of how to isolate it.
The error code of URI::InvalidURIError: bad URI(is not URI?): only indicates the library (blazer gem) successfully read a file, which may or may not be the file you have edited, /YOUR_DIR/blazer.yml or something, but nevertheless failed to parse the URI.
Now, the issues to consider include:
blazer gem really read /YOUR_DIR/blazer.yml?
does the preprocessor of the yml work as expected?
is the uri key specified correct?
mysql: or mysql2?
are the formats of IP, port, account name, password, and database name all correct? In particular, are special characters correctly escaped? (See MySql document about special characters)
I suppose the OP knows answers of some of these questions but we don't. So, let's assume any of them can be an issue.
Then a proposed strategy is this:
Find a URI that is at least in a correct format and confirm it is parsed and recognised correctly by Gem blazer. Note you only need to test the format and so dummy parameters are fine. For example, try a combination of the following and see which does not issue the error URI::InvalidURIError:
mysql://127.0.0.1/test
mysql://adam:alphabetonly#127.0.0.1/test
jdbc:mysql://adam:alphabetonly#127.0.0.1/test
Now, you know at least the potential issues (1),(3),(4) are irrelevant.
Replace the IP (hostname), account name, password, and database name one by one with the real one and find which raises the error URI::InvalidURIError. Now you have narrowed down which part causes a problem. In the OP's case, I suspect the problem is an incorrect escape of the special characters in the password part. Let's assume that is the case, and then,
properly escape the part so that they form a correct URI format as a whole. The answer by #Schwern is a good summary about the format. As a tip, you can get an escape URI by opening Rail's console (via rails c) and typing URI.encode('YOUR_PASSWORD') or alternatively, run ruby directly from the command-line in a (UNIX-shell) terminal:
ruby -ruri -e "puts URI.encode('YOUR_PASSWORD')"
Replace the password part in the URI in /YOUR_DIR/blazer.yml with the escaped string, and confirm it does not issue the error URI::InvalidURIError (hopefully).
In these processing, I deliberately avoided the preprocessor part, (2).
This answer to "Rails not parsing database URL on production" mentions about URI.encode('YOUR_PASSWORD') in a yml file, but it implicitly assumes a preprocessor works fine. During the test phase, that just adds another layer of complication, and so it is better to skip it. If you need it in your production (to mask the password etc), implement it later, when you know everything else works fine.
Hope by the time the OP has tried all of these, the problem is solved.
I'm doing my first steps in Puppet and ran into a problem. I've installed PHP on a Linux server and I want to do some slightly changes to php.ini file. I don't want to overwrite the whole ini file with one from repository, just change/create one simple config value.
I want to ensure, that the property upload_max_filesize in php.ini has the value of 10M.
How can I achieve this?
My preferred option would be to leave php.ini alone, and have puppet create a file in php's conf.d directory to override the values you want to change.
The less changes you make to php.ini, the easier it is to see what's going on when you need to merge your changes with the package providers changes when you upgrade php.ini in future.
file {'/etc/php5/conf.d/upload_limits.conf':
ensure => present,
owner => root, group => root, mode => 444,
content => "post_max_size = 10M \nupload_max_filesize = 10M \n",
}
There's basically 3 options:
Use augeas support in puppet (you'll need the ruby augeas libraries installed) like:
augeas { "php.ini":
notify => Service[httpd],
require => Package[php],
context => "/files/etc/php.ini/PHP",
changes => [
"set post_max_size 10M",
"set upload_max_filesize 10M",
];
}
You can use "augtool ls /files/etc/php.ini" to see the sections to understand how augeas is parsing the file and use that to work out the paths you need.
You can use an exec. Something like:
define set_php_var($value) {
exec { "sed -i 's/^;*[[:space:]]*$name[[:space:]]*=.*$/$name = $value/g' /etc/php.ini":
unless => "grep -xqe '$name[[:space:]]*=[[:space:]]*$value' -- /etc/php.ini",
path => "/bin:/usr/bin",
require => Package[php],
notify => Service[httpd];
}
}
set_php_var {
"post_max_size": value => '10M';
"upload_max_filesize": value => '10M';
}
Unfortunately, this solution doesn't understand the sections in php.ini, so adding a variable that's not already there would require extra effort. This will do the wrong thing if a variable appears in more than one section (but examples I'm looking at appear to have all unique variable names). This should work for a variable that's present but commented-out with a semi-colon.
Copy the original php.ini file into your puppet repository and use file with source => 'puppet:///...' or content => template(...) to replace the file entirely, as you indicated you would prefer not to do.
You could also use the file_line resource found in the stdlib module.
file_line{ 'php_upload_max_filesize':
path => '/path/to/php.ini',
line => "upload_max_filesize = 10M",
}
Since this will append the line to the file if one exactly matching it does not exist, and since the last instance of a config value takes precedence over those earlier in the file it will work. This is how I do it when i only have a couple things to change.
An alternative approach, if you're using Apache as your web server, is to set the php variable in your Apache virtualhost file (which will probably be somewhere in your Puppet manifests directory).
For example:
<VirtualHost *:80>
ServerName app.dev
DocumentRoot /srv/app/public
## etc...
php_value upload_max_filesize 10M
</VirtualHost>
This doesn't actually change php.ini, but - depending on your set-up - may be a simple way of achieving the same effect.
A bit down on this nginx config reference page you'll see:
rewrite ^ http://example.com$request_uri? permanent;
What is the meaning of ^ above?
For rewrite, the first argument is the match pattern and only applies to the path portion of the url, not the domain. In regular expressions, ^ matches the beginning of the input. For example, ^/photos/.*$ would match paths beginning in '/photos/'. By itself, ^ is a shortcut for all paths (since they all have a beginning).
So the jist of this is,
I have a file:
search.php
When I goto:
search.php?search=%23HashTag
The search returns: #HashTag
But when I use my .htaccess method:
/search/%23HashTag
Nothing is returned. And i've tested by putting the number sign later in the search and it returns upto that point.
This is what I have:
RewriteRule ^search/([^\.]+)$ search.php?search=$1 [NE,L]
What am I doing wrong..?
Change your flags to [NE,B,L].
http://httpd.apache.org/docs/current/rewrite/flags.html#flag_b
mod_rewrite unescapes the url before applying transformations. I'm not sure why it loses anything after the hash (maybe it re-interprets it as a url, and discards the fragment?). In any case, [B] re-escapes the url before running it through the rewrite rule.
Does replacing it with \%23 work ok?
(Clarity: Opposed to writing the # in the .htaccess file)