News:

SMF 2.1.4 has been released! Take it for a spin! Read more.

Main Menu

Proxy Images without Proxy.php (Nginx Users)

Started by MobileCS, February 18, 2018, 04:30:46 PM

Previous topic - Next topic

MobileCS

If you're using Nginx, here is how to proxy images without calling the Proxy.php file.

Using this method will prevent expensive calls to PHP on Apache, PHP-FPM, etc to show the image. Nginx can handle this using a lot less ram and resources.

To make this work, you will need to modify your nginx website vhost file + modify 3 forum files.

In your Nginx website's vhost file, add this at the bottom :


location ~* /proxy/ {

# prevent search engines from caching your proxy url's
add_header X-Robots-Tag "noindex, nofollow";

# return a 404 error if the image type is not allowed
        # adjust the allowed image types below
if ($args !~ "^(?:http:\/\/.+\.(?:png|jpe?g|gif|bmp|ico|svg).*)") { return 404; }

# use Google DNS servers to resolve domain names + cache results for 5 minutes
resolver 8.8.8.8 8.8.4.4 valid=300s;

# allow several redirects using the error_page directive
recursive_error_pages on;

# if the image no longer exists, redirects or throws an error - handle them
proxy_intercept_errors  on;
error_page      301 302 307 = @proxy_redirects;
error_page      404 = @proxy_not_found;

        # everything looks good - let's grab the image
proxy_pass      $args;
}

location @proxy_redirects {

set $image_loc   $upstream_http_location;

add_header X-Robots-Tag "noindex, nofollow";

resolver 8.8.8.8 8.8.4.4 valid=300s;

proxy_intercept_errors  on;

        # the image redirected to a new URL - let's grab the new URL and process it again
error_page      301 302 307 = /proxy/?$image_loc;

        # the image does not exist - throw a 404 error
error_page      404 = @proxy_not_found;

        # let's grab the image
proxy_pass      $image_loc;
}

location @proxy_not_found {
return 404;
}


Restart Nginx and let's test to make sure what we have now is working. Modify example.com to your own domain name.

https://example.com/proxy/?http://png.icons8.com/metro/1600/reddit.png

If you see the reddit logo, it's working! If not, confirm you have the code in the correct vhost file and that the Nginx server was restarted.

Now let's modify the forum files. Change all instances of example.com to your domain name!

Sources/Load.php :

Find:

$user_settings['avatar'] = strtr($boardurl, array('http://' => 'https://')) . '/proxy.php?request=' . urlencode($user_settings['avatar']) . '&hash=' . md5($user_settings['avatar'] . $image_proxy_secret);

Replace:

$user_settings['avatar'] = 'https://example.com/proxy/?' . $user_settings['avatar'];


Find:

$row['avatar'] = $boardurl . '/proxy.php?request=' . urlencode($row['avatar']) . '&hash=' . md5($row['avatar'] . $image_proxy_secret);

Replace:

$row['avatar'] = 'https://example.com/proxy/?' . $row['avatar'];


            
Sources/Subs.php :

Find both instances of:

$data = $boardurl . '/proxy.php?request=' . urlencode($data) . '&hash=' . md5($data . $image_proxy_secret);

Replace them with:

$data = 'https://example.com/proxy/?' . $data;


Find:

$context['user']['avatar']['href'] = $boardurl . '/proxy.php?request=' . urlencode($user_info['avatar']['url']) . '&hash=' . md5($user_info['avatar']['url'] . $image_proxy_secret);

Replace:

$context['user']['avatar']['href'] = 'https://example.com/proxy/?' . $user_info['avatar']['url'];


               
Sources/Profile-Modify.php :

Find:
if ($image_proxy_enabled && !empty($cur_profile['avatar_original']) && $cur_profile['avatar_original'] != $cur_profile['avatar'] && stristr($cur_profile['avatar'], $boardurl . '/proxy.php'))


Replace :

if ($image_proxy_enabled && !empty($cur_profile['avatar_original']) && $cur_profile['avatar_original'] != $cur_profile['avatar'] && stristr($cur_profile['avatar'], 'https://example.com/proxy/'))



To enable the proxy, open the forum/Settings.php file  :

Find:
$image_proxy_enabled = 0;

Replace:
$image_proxy_enabled = 1;


If you have any questions or improvement suggestions, please share them below!

Suki

Seems good, you don't really need to do the !$image_proxy_enabled change since you are inverting the effect that setting has, making it more complicated for the user than it needs to be.  Just leave the setting as it is, if the user enables it then nginx will kick in, if not, then nothing will happen.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

MobileCS

The only issue with that is I'm doing a "find / add after" (not replace) on all the edits.

I wanted to still have proxy.php support available for the forum. That is why I am using "!$image_proxy_enabled" - so the user can $image_proxy_enabled = 0; for Nginx proxy, and $image_proxy_enabled = 1; for the forum built in proxy.

I'm not sure to make it less confusing without having to add an additional 8 edits. (set special variable in settings.php + global that variable in 7 locations).

Suki

Well, this is a trick specifically for nginx users and those who would want to implement the trick won't have any need for the regular SMF proxy, if they still had any need for the regular proxy then they wouldn't be implementing this trick ;)

Having both options available seems redundant. It seems simpler to just replace the regular proxy with ngnix, leaving the setting logic intact.
Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

MobileCS

Quote from: Suki on February 21, 2018, 05:12:59 PM
Well, this is a trick specifically for nginx users and those who would want to implement the trick won't have any need for the regular SMF proxy, if they still had any need for the regular proxy then they wouldn't be implementing this trick ;)

I really can't argue that! I've updated my code to your new recommendations.  :)

Handling it your method also requires less template editing. So it's much easier and cleaner to implement.

Suki

Disclaimer: unless otherwise stated, all my posts are personal and does not represent any views or opinions held by Simple Machines.

albertlast

A small note,
this feature would be intraged in smf2.1 (when nothing goes wrong): https://github.com/SimpleMachines/SMF2.1/pull/4565

Advertisement: