<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-GB">
	<id>https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=Reverse_Proxy</id>
	<title>Reverse Proxy - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://training-course-material.com/index.php?action=history&amp;feed=atom&amp;title=Reverse_Proxy"/>
	<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=Reverse_Proxy&amp;action=history"/>
	<updated>2026-05-13T09:36:08Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://training-course-material.com/index.php?title=Reverse_Proxy&amp;diff=23945&amp;oldid=prev</id>
		<title>Cesar Chew at 17:31, 24 November 2014</title>
		<link rel="alternate" type="text/html" href="https://training-course-material.com/index.php?title=Reverse_Proxy&amp;diff=23945&amp;oldid=prev"/>
		<updated>2014-11-24T17:31:29Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt; {{Cat|Nginx}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;slideshow style=&amp;quot;nobleprog&amp;quot; headingmark=&amp;quot;⌘&amp;quot; incmark=&amp;quot;…&amp;quot; scaled=&amp;quot;true&amp;quot; font=&amp;quot;Trebuchet MS&amp;quot; &amp;gt;&lt;br /&gt;
;title: Reverse Proxy&lt;br /&gt;
;author: Bernard Szlachta (NobleProg Ltd)&lt;br /&gt;
&amp;lt;/slideshow&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== nginx as a reverse proxy ⌘===&lt;br /&gt;
* A popular use of nginx&lt;br /&gt;
* Minimises concurrent connections to proxy backend&lt;br /&gt;
* Put nginx in front of Tomcat&lt;br /&gt;
:* nginx serves all static content (images, css, javascript)&lt;br /&gt;
:* nginx proxies to Tomcat for dynamic content&lt;br /&gt;
=== A simple example ⌘===&lt;br /&gt;
 &lt;br /&gt;
 location /static/ {&lt;br /&gt;
    root /var/www/static/;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
 location / {&lt;br /&gt;
    proxy_pass http://localhost:8000/;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
=== Automatic URI rewriting ⌘===&lt;br /&gt;
* On the previous example the path would be unchanged because it is at the root&lt;br /&gt;
* If a path is specified in location and target, by default it is rewritten&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
  location /foo/ {&lt;br /&gt;
    proxy_pass http://localhost:8000/bar/;&lt;br /&gt;
  }&lt;br /&gt;
 &lt;br /&gt;
* The proxy target will see the request as though it had been made for /bar/&lt;br /&gt;
=== Rewriting Server Responses ⌘===&lt;br /&gt;
* Sometimes applications will generate 301/302&lt;br /&gt;
* Often this will include a path calculated from the local settings&lt;br /&gt;
* When used behind a proxy this may be wrong&lt;br /&gt;
=== Server response problem example ⌘===&lt;br /&gt;
&lt;br /&gt;
 location /foo/ {&lt;br /&gt;
   proxy_pass http://localhost:8000/bar/;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
 $ curl -I http://localhost/foo/&lt;br /&gt;
 HTTP/1.1 302 Moved Temporarily&lt;br /&gt;
 Location: http://localhost:8000/baz/&lt;br /&gt;
&lt;br /&gt;
=== Solution: Proxy Redirect ⌘===&lt;br /&gt;
 &lt;br /&gt;
 location /foo/ {&lt;br /&gt;
   proxy_pass http://localhost:8000/bar/;&lt;br /&gt;
   proxy_redirect on;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
=== Adding an X-Forwarded-For ⌘===&lt;br /&gt;
&lt;br /&gt;
* The proxy destination doesn&amp;#039;t know who made the original request&lt;br /&gt;
* Solution: Add an X-Forwarded-For header&lt;br /&gt;
 &lt;br /&gt;
 location /foo/ {&lt;br /&gt;
   proxy_pass http://localhost:8000/bar/;&lt;br /&gt;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
=== Dealing with legacy applications + cookies ⌘===&lt;br /&gt;
* Scenario: multiple applications need to be on a single domain&lt;br /&gt;
:* http://app.example.com/legacy1&lt;br /&gt;
:* http://app.example.com/legacy2 &lt;br /&gt;
* Problem: These applications set cookies for the domain they are on - not the new single domain &lt;br /&gt;
&lt;br /&gt;
=== nginx to the rescue, again ⌘===&lt;br /&gt;
&lt;br /&gt;
 location /legacy1 {&lt;br /&gt;
  proxy_cookie_domain legacy1.example.com app.example.com;&lt;br /&gt;
  proxy_cookie_path $uri /legacy1$uri;&lt;br /&gt;
  proxy_pass http://legacy1.example.com/;&lt;br /&gt;
 }&lt;br /&gt;
 location /legacy2 {&lt;br /&gt;
  proxy_cookie_domain legacy2.example.com app.example.com;&lt;br /&gt;
  proxy_cookie_path $uri /legacy2$uri;&lt;br /&gt;
  proxy_pass http://legacy2.example.com/;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== What did we do? ⌘===&lt;br /&gt;
* nginx will rewrite the cookie domain to app.example.com&lt;br /&gt;
* nginx adds a cookie path matching the URI&lt;br /&gt;
* Each app sees only its own cookies&lt;br /&gt;
=== Caching ⌘===&lt;br /&gt;
* nginx can be used to accelerate content from the upstream&lt;br /&gt;
* By caching dynamically generated content, performance can be improved massively&lt;br /&gt;
=== Simple caching example ⌘===&lt;br /&gt;
&lt;br /&gt;
 http {&lt;br /&gt;
 proxy_temp_path /var/spool/nginx;&lt;br /&gt;
 proxy_cache_path /var/spool/nginx keys_zone=CACHE:100m levels=1:2 inactive=6h max_size=1g;&lt;br /&gt;
  location / {&lt;br /&gt;
    proxy_pass http://localhost:8000/;&lt;br /&gt;
    proxy_cache CACHE;&lt;br /&gt;
  }&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== What we did ⌘===&lt;br /&gt;
* Configured a 100MB in-memory cache&lt;br /&gt;
* Configured a 1GB on-disk cache&lt;br /&gt;
* Told nginx to cache everything suitable&lt;br /&gt;
&lt;br /&gt;
=== What nginx does ⌘===&lt;br /&gt;
* nginx proxies requests to localhost:8000 as in previous examples&lt;br /&gt;
* nginx looks at the headers received to check if data is safe to cache, and for how long&lt;br /&gt;
* nginx stores a copy on disk&lt;br /&gt;
* Next time a request is made for this URL, on-disk cache is checked&lt;br /&gt;
* If it exists and is fresh, serve directly, storing a copy in RAM&lt;br /&gt;
&lt;br /&gt;
=== What is fresh? ⌘===&lt;br /&gt;
* Backend server should send appropriate headers to let nginx (and any other caches along the way) what is OK to cache, and how long for&lt;br /&gt;
* `Cache-Control: private`&lt;br /&gt;
:* don&amp;#039;t cache at all&lt;br /&gt;
* Cache-Control: public, max-age: 900&lt;br /&gt;
:* cache for 15 minutes&lt;br /&gt;
* Expires: Mon, 1  Jul 2013 01:00:00 GMT&lt;br /&gt;
:* cache until the specified date&lt;br /&gt;
&lt;br /&gt;
=== Cache stampedes ⌘===&lt;br /&gt;
* Cache stampedes are a big problems for sites using caching to scale&lt;br /&gt;
* Imaging the following scenario:&lt;br /&gt;
:* Proxy destination can handle max 50 requests/second&lt;br /&gt;
:* nginx is added, traffic is 300 requests/second&lt;br /&gt;
:* 25% of traffic is for the front page&lt;br /&gt;
:* what happens when max-age is reached?&lt;br /&gt;
=== Dogpile ⌘===&lt;br /&gt;
[[File:Dogpile.jpg]]&lt;br /&gt;
&lt;br /&gt;
=== Dogpile effect ⌘===&lt;br /&gt;
* Everyone tries to get the same URL at once&lt;br /&gt;
* It&amp;#039;s very slow / broken for everyone until a new copy gets into the cache&lt;br /&gt;
* Load graphs show waves of peaks&lt;br /&gt;
&lt;br /&gt;
=== nginx solution ⌘===&lt;br /&gt;
* nginx can be configured to serve stale content whilst updating&lt;br /&gt;
&lt;br /&gt;
 location / {&lt;br /&gt;
   proxy_pass http://localhost:8000/;&lt;br /&gt;
   proxy_cache CACHE;&lt;br /&gt;
   proxy_cache_use_stale updating;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=== Hiding errors ⌘===&lt;br /&gt;
* If old content is better than no content, nginx can also be configured to use stale content when it recieves no response or an error from the backend&lt;br /&gt;
* We also set a timeout value&lt;br /&gt;
&lt;br /&gt;
 location / {&lt;br /&gt;
   proxy_pass http://localhost:8000/;&lt;br /&gt;
   proxy_cache CACHE;&lt;br /&gt;
   proxy_cache_use_stale timeout http_500;&lt;br /&gt;
   proxy_read_timeout 15s;&lt;br /&gt;
 }&lt;/div&gt;</summary>
		<author><name>Cesar Chew</name></author>
	</entry>
</feed>