• Introducing WebPros Cloud - a fully managed infrastructure platform purpose-built to simplify the deployment of WebPros products !  WebPros Cloud enables you to easily deliver WebPros solutions — without the complexity of managing the infrastructure.
    Join the pilot program today!
  • The Horde component is removed from Plesk Installer. We recommend switching to another webmail software supported in Plesk.
  • The BIND DNS server has already been deprecated and removed from Plesk for Windows.
    If a Plesk for Windows server is still using BIND, the upgrade to Plesk Obsidian 18.0.70 will be unavailable until the administrator switches the DNS server to Microsoft DNS. We strongly recommend transitioning to Microsoft DNS within the next 6 weeks, before the Plesk 18.0.70 release.

Redirect (jpg|jpeg) files in a certain directory to php to process

Martin_Berlin

New Pleskian
I'm trying to redirect (jpg|jpeg) files in a certain directory (/pdf/) to php to process first end then deliver as image - but all I get is a 404.
That's my configuration:

YES (Intelligente Bearbeitung statischer Dateien)

YES (Statische Dateien direkt durch Nginx bedienen)
ac3 avi bmp bz2 css cue dat doc docx dts exe flv gz htm html img iso mkv mp3 mp4 mpeg mpg ogg ppt pptx qt rar rm swf tar tgz txt wav xls xlsx zip

YES (PHP von Nginx verarbeiten lassen)

Nginx directives:

if ($scheme !~* ^https ){
rewrite ^ https://$server_name$request_uri? permanent;
}

location ~ ^/pdf/(.*)\.(jpg|jpeg|test)$ {
rewrite ^/pdf/(.*)\.(jpg|jpeg|test)$ /pdf/image.php?id=$1 break;
}


if (!-e $request_filename){
rewrite ^(.*)$ /index.php break;
}

location ~* \.(eot|ttf|woff)$ {
add_header Access-Control-Allow-Origin '*';
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @fallback;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @fallback;
}

gzip on;
gzip_comp_level 6;
gzip_http_version 1.0;
gzip_proxied any;
gzip_types text/html application/xml+rss application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rdf+xml application/rss+xml application/schema+json application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-javascript application/x-web-app-manifest+json application/xhtml+xml application/xml font/eot font/opentype image/bmp image/svg+xml image/vnd.microsoft.icon image/x-icon text/cache-manifest text/css text/javascript text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy text/xml;
gzip_vary on;
gzip_disable "MSIE [1-6]\.(?!.*SV1)";


THANK YOU
 
@Martin_Berlin,

To be honest, your nginx configuration is pretty "ugly" and in desperate need of improvement.

See my suggestions below, step for step explained.

YES (PHP von Nginx verarbeiten lassen)

Leave PHP to Apache (with fpm), it is "good practice" (i.e. more efficient and simply better) to use Nginx as a "pure proxy".

In short, deactivate "PHP von Nginx verarbeiten verlassen".

if ($scheme !~* ^https ){
rewrite ^ https://$server_name$request_uri? permanent;
}

In Nginx, the general rule is "if is evil"!

For the enforcement of SSL/TLS (by default), one could put the following in the server block:

return 301 https://www.domain.com$request_uri;

Note that this line only has to be placed in the server block, handling the requests on port 80 (non-https connections).

location ~ ^/pdf/(.*)\.(jpg|jpeg|test)$ {
rewrite ^/pdf/(.*)\.(jpg|jpeg|test)$ /pdf/image.php?id=$1 break;
}

This is completely wrong, for many reasons:

- do not use "break" in this case, just use "last" or nothing at all
- the "^/pdf/(.*)\.(jpg|jpeg|test)$" is a complex match pattern, that is associated with a penalty on performance (i.e. this match pattern is not efficient)
- the "^/pdf/(.*)\.(jpg|jpeg|test)$" is very likely to be never matched due to the "(.*)\" part in the regexp

and so on.

Can you provide me some information about the directory structures and names?

if (!-e $request_filename){
rewrite ^(.*)$ /index.php break;
}

Again, "if is evil" AND "match patterns should be prevented, if possible". Moreover, this set of lines can probably be simplified.

I assume that you are using WordPress, given the nature of the contents in the "if statement".

In general, one can use:

location / {
try_files $uri $uri/ /index.php?$args;
}

or something similar.

The above location directive simply allows all non-existing files to be passed to index.php, with some arguments.

location ~* \.(eot|ttf|woff)$ {
add_header Access-Control-Allow-Origin '*';
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @fallback;
}

In short, the add_header Pragma public is (often) ineffective (i.e. "Pragma" is deprecated) AND the "try_files $uri @fallback;" is not effective (at least not in the current Nginx setup).

Just remove those lines, it can do no harm.

Furthermore, the line "add_header Access-Control-Allow-Origin '*';" is not strictly necessary, unless you are using a CDN and/or are serving fonts from external domains.

In fact, the Access-Control-Allow-Origin header is intended to increase security, by reducing vulnerability to cross-site scripting.

In your case, having this line "add_header Access-Control-Allow-Origin '*';" will compromise security in a "minor" fashion, i.e. it is used to increase vulnerability (due to the "*").

Simply stated: use the Access-Control-Allow-Origin header only for improving security (and not the other way around).

Just remove the line if you do not make use of a CDN and/or external domains.

location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires 30d;
add_header Pragma public;
add_header Cache-Control "public";
try_files $uri @fallback;
}

Naturally, the comments with respect to the previous location directive also apply to this location directive.

However, there is another (minor) issue: this specific location directive is not strictly necessary, it can be integrated with the earlier location directive, if and only if you do not use CDN or external domains.

The advantage is of integration of location directives, if possible, is that your Nginx configuration becomes a little bit more compact and more efficient.


I sincerely hope that (all) the above helps!

Regards....
 
Hi Trialotto,

thank you very much for your detailed explanation.

Let my explain:

Leave PHP to Apache (with fpm), it is "good practice" (i.e. more efficient and simply better) to use Nginx as a "pure proxy".
I will consider this (nevertheless I thought it was much quicker since I switched to nginx/php)

Note that this line only has to be placed in the server block, handling the requests on port 80 (non-https connections).
Where is the port 80 server block for nginx? I see only one for both?

Can you provide me some information about the directory structures and names?

if an image is requested like https://domain.com/pdf/image12345.jpg (or jpeg)
only in the subdirectory /pdf/ it should be handled by a php script instead of a static delivery and the image part image12345 should be the $_GET['id'] parameter.

I assume that you are using WordPress, given the nature of the contents in the "if statement".
Yes - it's wordpress

Furthermore, the line "add_header Access-Control-Allow-Origin '*';" is not strictly necessary, unless you are using a CDN and/or are serving fonts from external domains.
I'm using a CDN (aws/cloudfront) and before I had a coss-scripting error for the fonts

However, there is another (minor) issue: this specific location directive is not strictly necessary, it can be integrated with the earlier location directive, if and only if you do not use CDN or external domains.
Again - yes I'm using a CDN

So please - how should my configuration (with php handled by nginx for now) look like?

THANK YOU VERY MUCH
Martin
 
@Martin_Berlin/Martin,

A number of (various) statements were given by you and I will try to tackle them all.


First of all, you stated that you use a CDN, hence requiring the add_header directive, in order to allow for (primarily) fonts hosted on the CDN.

A proper add_header directive would not include the "*" (i.e. allow all), but should include the domain that is used by the CDN.

This domain can vary across CDN providers: the fastest way is to load your website and check the URLs used for serving fonts.

If you have a lot of URLs, try to get all the fonts on one CDN OR your current server (no harm in having your fonts on the server, it even works better).

The idea behind the above suggestion is that one would like to have one (1) "good" add_header directive of the form:

add_header Access-Control-Allow-Origin "*.<domain>.<tld>"

Note that this directive only allows for fonts from one (1) specific URL, i.e. one domain and associated subdomains.

Also note that I do prefer to define the domain explicitly, i.e. not using wildcards (since the rule becomes less strict and/or since regexp patterns should be prevented, if possible).


Second, you stated:
I will consider this (nevertheless I thought it was much quicker since I switched to nginx/php)

To that, I can only say that you will barely notice the difference: the Apache (with fpm) + Nginx (pure proxy) stack is more or less just as fast.

Furthermore, this specific setup allows you to be more specific and effective when optimizing page load times: use Redis and FastCGI on the Apache (i.e. php) side and you can realize astonishing improvements in page load times (note that the Nginx proxy augments this performance by filtering requests for static files and directly serving those requests).

In short, a clean stack, that can be easily managed.


Third, you stated:
Where is the port 80 server block for nginx? I see only one for both?

I am not really sure where you are looking, but Plesk has two server blocks in the relevant config files, with those server blocks being of the kind:

server {
listen <IP address>:80;
....

}
server {
listen <IP address>:443 ssl;
....

}

However, irregardless of any miscommunication and/or mistakes, note the following: one cannot easily change the server blocks in the current default Nginx templates for Plesk.

The above simply implies that I do not advice to change templates and/or adjust server blocks and/or add server blocks, certainly not if Nginx configuration is unknown territory.

In short, a work-around has to be defined, in order to create automatic https redirection for a specific domain.

A suggestion for this work-around could be: go to Domains > "Domain" > Apache & nginx Settings > Additional nginx directives and add at the top

location ~ \.php {
return 301 https://www.domain.com$request_uri;
}


Note that the above location directive is a little bit crude, but it should be working.

One would rather have the return directive in a server block, but the "work-around" (i.e. placement in location directives) is actually required, as result of the default Nginx templates.

Anyway, with this "work-around", Nginx is used as a pure proxy that redirects http traffic to https connections, which in turn are handled by the server blocks, handling ssl/tls traffic.

All other traffic, being traffic for static files (i.e. traffic, not related to php files) will be served by Nginx, via http and https connections.

Sure, one can add the line with the return directive to each location block, in order to allow for https redirection of requests for static files. Note that this is not strictly necessary.


Fourth and final, you stated

if an image is requested like https://domain.com/pdf/image12345.jpg (or jpeg) only in the subdirectory /pdf/ it should be handled by a php script instead of a static delivery and the image part image12345 should be the $_GET['id'] parameter.

in relation to the location directive (used by you)

location ~ ^/pdf/(.*)\.(jpg|jpeg|test)$ {
rewrite ^/pdf/(.*)\.(jpg|jpeg|test)$ /pdf/image.php?id=$1 break;
}

and my response to the usage of that directive.

In response to your statement (see above), I must really ask you why you are using Nginx to point to the image rendering script called image.php.

It is better to

a) call image.php from another php script, OR
b) have a background process (automatically) create a pdf from a jpg, jpeg or test file, whenever this type of file is created in a specific directory.

The above methods (and certainly method b) are better, since they are more efficient, given the facts that these methods do not "bother" Nginx with unnecessary redirects (i.e. better and more compact configuration) AND do not "bother" Apache with redirection to a php script, that only converts specific files at request time (i.e. Apache performance improvement).

In general, your location directive is unnecessary and flawed in many areas, but I will not discuss that, for the sake of convenience.

Let´s assume that you really want the directive: go to Domains > "Domain" > Apache & nginx Settings > Additional nginx directives and add BEFORE the "php location directive"

location ~* \.(jpg|jpeg|test)$ {
rewrite ^/pdf/(.*)$ /image.php?<id>=$1 last;
}


and you should explicitly note that

- you place the image.php script in any subdirectory, but thus would change the line to: rewrite ^/pdf/(.*)$ /<path to subdirectory>/image.php?<id>=$1 last;
- Nginx will rewrite the URL and go on with processing until the "php location directive" is found: hence, "last" should be used and not "break"
- you should write the image.php script to receive parameters, as identified by <id> (i.e. the parameters can have any name and the proper name has to be used in the rewrite rule)

and the above should be working, even though you would be better off with calling a php script, in which the image.php script is included with parameters.

For instance, creating a specific page with php allows you to call the image.php script and loading this page would only require the "php location directive" (given the fact that you want standard https redirection) and, therefore, would make the "jpg/jpeg/test location directive" obsolete.

Sure, the image.php script can also be loaded directly (and hence render the image directly), if the script allows for parameters.

In short, try to prevent the "jpg/jpeg/test location directive" and improve the php scripts.


Hope the above helps.

Kind regards...
 
Back
Top