Ruby Proxy
Design Patterns: Proxy in Ruby – Refactoring.Guru
Hey, I have just reduced the price for all products. Let’s prepare our programming skills for the post-COVID era. Check it out »
Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client. A proxy receives client requests, does some work (access control, caching, etc. ) and then passes the request to a service object.
The proxy object has the same interface as a service, which makes it interchangeable with a real object when passed to a client.
Usage of the pattern in Ruby
Complexity:
Popularity:
Usage examples: While the Proxy pattern isn’t a frequent guest in most Ruby applications, it’s still very handy in some special cases. It’s irreplaceable when you want to add some additional behaviors to an object of some existing class without changing the client code.
Identification: Proxies delegate all of the real work to some other object. Each proxy method should, in the end, refer to a service object unless the proxy is a subclass of a service.
Conceptual Example
This example illustrates the structure of the Proxy design pattern. It focuses on answering these questions:
What classes does it consist of?
What roles do these classes play?
In what way the elements of the pattern are related?
Conceptual example
# The Subject interface declares common operations for both RealSubject and the
# Proxy. As long as the client works with RealSubject using this interface,
# you’ll be able to pass it a proxy instead of a real subject.
class Subject
# @abstract
def request
raise NotImplementedError, “#{} has not implemented method ‘#{__method__}'”
end
# The RealSubject contains some core business logic. Usually, RealSubjects are
# capable of doing some useful work which may also be very slow or sensitive –
# e. g. correcting input data. A Proxy can solve these issues without any changes
# to the RealSubject’s code.
class RealSubject < Subject
puts 'RealSubject: Handling request. '
# The Proxy has an interface identical to the RealSubject.
class Proxy < Subject
# @param [RealSubject] real_subject
def initialize(real_subject)
@real_subject = real_subject
# The most common applications of the Proxy pattern are lazy loading, caching,
# controlling the access, logging, etc. A Proxy can perform one of these
# things and then, depending on the result, pass the execution to the same
# method in a linked RealSubject object.
return unless check_access
quest
log_access
# @return [Boolean]
def check_access
puts 'Proxy: Checking access prior to firing a real request. '
true
def log_access
print 'Proxy: Logging the time of request. '
# The client code is supposed to work with all objects (both subjects and
# proxies) via the Subject interface in order to support both real subjects and
# proxies. In real life, however, clients mostly work with their real subjects
# directly. In this case, to implement the pattern more easily, you can extend
# your proxy from the real subject's class.
def client_code(subject)
#...
puts 'Client: Executing the client code with a real subject:'
real_subject =
client_code(real_subject)
puts "\n"
puts 'Client: Executing the same client code with a proxy:'
proxy = (real_subject)
client_code(proxy)
Execution result
Client: Executing the client code with a real subject:
RealSubject: Handling request.
Client: Executing the same client code with a proxy:
Proxy: Checking access prior to firing a real request.
Proxy: Logging the time of request.
Proxy in Other Languages
How do I update Ruby Gems from behind a Proxy (ISA-NTLM)
The firewall I’m behind is running Microsoft ISA server in NTLM-only mode. Hash anyone have success getting their Ruby gems to install/update via Ruby SSPI gem or other method?… or am I just being lazy?
Note: rubysspi-1. 2. 4 does not work.
This also works for “igem”, part of the IronRuby project
the Tin Man153k39 gold badges201 silver badges282 bronze badges
asked Aug 7 ’08 at 5:21
Brett VeenstraBrett Veenstra45. 5k17 gold badges68 silver badges85 bronze badges
2
For the Windows OS, I used Fiddler to work around the issue.
Install/Run Fiddler from Run gem:
$ gem install —proxy localhost:8888 $gem_name
answered Nov 15 ’10 at 17:45
5
I wasn’t able to get mine working from the command-line switch but I have been able to do it just by setting my HTTP_PROXY environment variable. (Note that case seems to be important). I have a batch file that has a line like this in it:
SET HTTP_PROXY=%USER%:%PASSWORD%@%SERVER%:%PORT%
I set the four referenced variables before I get to this line obviously. As an example if my username is “wolfbyte”, my password is “secret” and my proxy is called “pigsy” and operates on port 8080:
SET HTTP_PROXY=wolfbyte:secret@pigsy:8080
You might want to be careful how you manage that because it stores your password in plain text in the machine’s session but I don’t think it should be too much of an issue.
answered Aug 7 ’08 at 5:49
Mike MinutilloMike Minutillo50. 7k14 gold badges45 silver badges41 bronze badges
7
This totally worked:
gem install —proxy $gem_name
answered Mar 26 ’12 at 3:35
SethRockerSethRocker1, 4711 gold badge9 silver badges3 bronze badges
3
I tried some of these solutions, and none of them worked. I finally found a solution that works for me:
gem install -p proxy_ip:proxy_port rails
using the -p parameter to pass the proxy. I’m using Gem version 1. 9. 1.
answered Aug 1 ’12 at 23:32
kfoxkfox1, 13412 silver badges15 bronze badges
Create a file (either in /etc/gemrc or ~/ or for example with chef gem in /opt/chef/embedded/etc/gemrc) containing:
_proxy: proxy:3128
Then you can gem install as usual.
riemann2823 silver badges8 bronze badges
answered Dec 22 ’15 at 9:14
lukapiskelukapiske3593 silver badges8 bronze badges
1
This solved my problem perfectly:
gem install -p proxy_ip:proxy_port compass
You might need to add your user name and password to it:
gem install -p [username]:[password]@proxy_ip:proxy_port compass
answered Apr 9 ’14 at 8:48
HomTomHomTom4583 silver badges11 bronze badges
0
If you are having problems getting authenticated through your proxy, be sure to set the environment variables in exactly the format below:
set
set HTTP_PROXY_USER=user
set HTTP_PROXY_PASS=password
The user:password@ syntax doesn’t seem to work and there are also some badly named environment variables floating around on Stack Overflow and various forum posts.
Also be aware that it can take a while for your gems to start downloading. At first I thought it wasn’t working but with a bit of patience they started downloading as expected.
answered Feb 21 ’12 at 17:26
I tried all the above solutions, however none of them worked. If you’re on linux/macOS i highly suggest using tsocks over an ssh tunnel. What you need in order to get this setup working is a machine where you can log in via ssh, and in addition to that a programm called tsocks installed.
The idea here is to create a dynamic tunnel via SSH (a socks5 proxy). We then configure tsocks to use this tunnel and to start our applications, in this case:
tsocks gem install…
or to account for rails 3. 0:
tsocks bundle install
A more detailed guide can be found under:
Despite being written for Ubuntu the procedure should be applicable for all Unix based machines. An alternative to tsocks for Windows is FreeCap (). A viable SSH client on windows is called putty.
answered Sep 6 ’11 at 5:04
Christian FChristian F3523 silver badges5 bronze badges
Quick answer: Add proxy configuration with parameter for both install/update
gem install —proxy host:port/ package_name
gem update —proxy host:port/ package_name
answered Jun 17 ’19 at 18:50
ShantonuShantonu1, 11011 silver badges10 bronze badges
4
Posts abound regarding this topic, and to help others save hours of trying different solutions, here is the final result of my hours of tinkering.
The three solutions around the internet at the moment are:
rubysspi
apserver
cntlm
rubysspi only works from a Windows machine, AFAIK, as it relies on the Win32Api library. So if you are on a Windows box trying to run through a proxy, this is the solution for you. If you are on a Linux distro, you’re out of luck.
apserver seems to be a dead project. The link listed in the posts I’ve seen lead to 404 page on sourceforge. I search for “apserver” on sourceforge returns nothing.
The sourceforge link for cntlm that I’ve seen redirects to, but that times out. A search on sourceforge turns up this link, which does work:
After downloading and configuring cntlm I have managed to install a gem through the proxy, so this seems to be the best solution for Linux distros.
answered Mar 10 ’09 at 10:33
A workaround is to install on your local machine, configure it and run gems through this proxy.
Install: Just download apserver 097 (and not the experimental 098! ) and unpack.
Configure: Edit the file and put the values for your MS proxy in PARENT_PROXY and PARENT_PROXY_PORT. Enter the values for DOMAIN and USER. Leave PASSWORD blank (nothing after the colon) – you will be prompted when launching it.
Run apserver: cd aps097; python
Run Gems: gem install—-proxy localhost:5865/ library
Csa774799 silver badges17 bronze badges
answered Aug 7 ’08 at 5:25
Jarin UdomJarin Udom1, 8493 gold badges19 silver badges23 bronze badges
I am working behind a proxy and just installed SASS by downloading directly from
I then ran sudo gem install [path/to/downloaded/gem/file]. I cannot say this will work for all gems, but it may help some people.
answered Nov 26 ’12 at 11:23
ZanderZander1, 8852 gold badges24 silver badges47 bronze badges
This worked for me in a Windows box:
set HTTP_PROXY=server:port
set HTTP_PROXY_USER=username
set HTTP_PROXY_PASS=userparssword
set HTTPS_PROXY=server:port
set HTTPS_PROXY_USER=username
set HTTPS_PROXY_PASS=userpassword
I have a batch file with these lines that I use to set environment values when I need it.
The trick, in my case, was HTTPS_PROXY sets. Without them, I always got a 407 proxy authentication error.
answered Jan 13 ’15 at 11:35
If you are on a *nix system, use this:
export _proxy=${}:${port}
and then try:
gem install ${gem_name}
answered Oct 25 ’13 at 17:50
If behind a proxy, you can navigate to Ruby downloads, click on Download, which will download the specified update ( or Gem) to a desired location.
Next, via Ruby command line, navigate to the downloaded location by using: pushd [directory]
eg: pushd D:\Setups
then run the following command: gem install [update name] –local
eg: gem install rubygems-update –local.
Tested on Windows 7 with Ruby update version 2. 4. 1.
To check use following command: ruby -v
answered Aug 11 ’14 at 13:27
ArNumbArNumb1871 gold badge3 silver badges10 bronze badges
Rather than editing batch files (which you may have to do for other Ruby gems, e. g. Bundler), it’s probably better to do this once, and do it properly.
On Windows, behind my corporate proxy, all I had to do was add the HTTP_PROXY environment variable to my system.
Start -> right click Computer -> Properties
Choose “Advanced System Settings”
Click Advanced -> Environment Variables
Create a new System variable named “HTTP_PROXY”, and set the Value to your proxy server
Reboot or log out and back in again
Depending on your authentication requirements, the HTTP_PROXY value can be as simple as:
proxy-server-name
Or more complex as others have pointed out
username:password@proxy-server-name:port-number
answered May 16 ’14 at 6:27
testworkstestworks3651 silver badge9 bronze badges
for anyone tunnelling with SSH; you can create a version of the gem command that uses SOCKS proxy:
Install socksify with gem install socksify (you’ll need to be able to do this step without proxy, at least)
Copy your existing gem exe
cp $(command which gem) /usr/local/bin/proxy_gem
Open it in your favourite editor and add this at the top (after the shebang)
require ‘socksify’
if ENV[‘SOCKS_PROXY’]
host, port = ENV[‘SOCKS_PROXY’](‘:’)
cks_server = host || ‘localhost’
cks_port = _i || 1080
end
Set up your tunnel
ssh -D 8123 -f -C -q -N user@proxy
Run your gem command with proxy_gem
SOCKS_PROXY=localhost:8123 proxy_gem push mygem
answered Apr 3 ’20 at 14:10
Mike CampbellMike Campbell7, 7202 gold badges35 silver badges50 bronze badges
Not the answer you’re looking for? Browse other questions tagged ruby proxy rubygems ironruby or ask your own question.
Proxy Pattern – Ruby Blog
10 November 2017
Patterns
Ruby
Proxy Pattern
Follow @makagon
In this article, we will cover Proxy pattern and its types. We will implement each of them using Ruby.
Intent
Let’s begin with the intent of this pattern. In “Design Patterns: Elements of Reusable Object-Oriented Software” book they describe the intent of Proxy as:
Provide a surrogate or placeholder for another object to control access to it
This pattern is also known as Surrogate.
I like the example they provide in that book:
Consider a document editor that can embed graphical objects in a document. Some graphical objects, like large raster images, can be expensive to create. But opening a document should be fast, so we should avoid creating all the expensive objects at once when the document is opened. [… ]
The solution is to use another object, like image proxy, that acts as a stand-in for the real image. The proxy acts just like the image and takes care of instantiating it when required.
Dependencies would look like this:
TextDocument would use ImageProxy to show some placeholder initially, and ImageProxy would load actual Image when required.
Applicability
Proxy is useful whenever there is a need for a more sophisticated reference to an object. It’s applicable as:
Virtual proxy
Protection proxy
Remote proxy
Smart reference
Virtual Proxy
Creates expensive objects on demand
Example with ImageProxy described above is exactly this type of proxy.
Let’s implement it with Ruby.
We have TextDocument class with 2 methods:
class TextDocument
attr_accessor:elements
def load
{ |el|}
end
def render
It has just two methods: load and render. We assume that we want to load all elements for the document and then we want to render them.
Let’s say that we have Image element that takes too long to load:
class Image
#… takes too much time
# render loaded image
So if we want to load document with image:
document =
()
# => takes too much time because of image
It will take too long because of the load time of the image.
We can create a virtual proxy for an image that would implement lazy loading:
class LazyLoadImage
attr_reader:image
def initialize(image)
@image = image
Now if we use LazyLoadImage proxy, it will not hold document loading. It happens because LazyLoadImage doesn’t load image until render call.
image =
((image))
# => fast
# => slow because image is being loaded
We could use SimpleDelegator to implement proper delegation from LazyLoadImage to Image as we did for Decorator Pattern.
Protection Proxy
A protection Proxy controls access to the original object
This one is pretty obvious, if you want to apply some protection rules before calling the original object, you can wrap it in a Protection Proxy
class Folder
def (name)
# creating folder
# deleting folder
class FolderProxy
def (user, folder_name)
raise ‘Only Admin Can Create Folders’ unless
(folder_name)
raise ‘Only Admin Can Delete Folders’ unless
I must admit that in this example we have a different interface between Proxy and original class. Folder accepts just one param for create and delete, whereas FolderProxy accepts user as well. I’m not sure if it’s the best implementation of this type of proxy. Let me know in comments if you have better example;)
Remote Proxy
A remote proxy provides a local representative for an object in different address space
For example, if you use remote procedure calls (RPC), you can easily create Proxy that would handle RPC calls. I’ll use xml-rpc gem for example.
To make a remote procedure call we can use this code:
require ‘xmlrpc/client’
server = w2(“myproject/api/user”)
result = (“”, id)
Let’s create Remote Proxy that would handle it for us:
class UserProxy
def find(id)
(“”, id)
private
def server
@server ||= w2(“myproject/api/user”)
Now we have Proxy that we can use to get access to an object in a different address space.
Smart Reference
A smart reference is a replacement for a bare pointer that performs additional actions when an object is accessed
One of the usages is to load a persistent object into memory when it’s first referenced.
Using this type of Proxy we can create Memoization for response.
Let’s say that we have a third-party tool that does some heavy calculation for us. Usually, they would provide a gem for us. Let’s imagine that it looks like this:
class HeavyCalculator
def calculate
# takes some time to calculate
Because it’s third-party gem, we can not add memoization there. At the same time, we don’t want to wait too long for every call to HeavyCalculator. In this case, we can create a Smart Reference proxy that would add memoization for us:
class MemoizedHeavyCalculator
@result ||= lculate
def calculator
@calculator ||=
Now we can use MemoizedHeavyCalculator to call calculate as many times as we need, and it will make the actual call just once. For any further call, it will use memoized value.
Using Proxy as a smart reference, we could add logging as well. For example: if we have third-pary service that provides some quotes for us (we can not change it’s code) and we want to add logging for each call to that service. We could implement it this way:
class ExpensiveService
def get_quote(params)
#… sending request
class ExpensiveServiceWithLog
puts “Getting quote with params: #{params}”
t_quote(params)
def service
@service ||=
We can not change the implementation of ExpensiveService because it’s a third-party code. But using ExpensiveServiceWithLog we can add any sort of logging we need. Just for sake of simplicity, I used puts there.
Related Patterns
Some implementations of a Proxy pattern are really similar to implementation of Decorator Pattern. But these two patterns have different intent. A Decorator adds responsibilities to an object, whereas proxy controls access to an object.
A Proxy might look similar to Adapter pattern. But adapter provides a different interface to the object it adapts. A Proxy provides the same interface as its subject.
PS: the proxy object should respond to all methods of the original object. In examples above, I’ve just implemented methods of the original object in the proxy class. The original object could have many methods and it would be a lot of repetitive code in proxy class.
Since implementation of Proxy pattern and Decorator pattern is almost the same, I highly recommend you to read about SimpleDelegator which helps to delegate methods from proxy to original object.
Thanks for reading!
Follow @makagon
Frequently Asked Questions about ruby proxy
What is a Proxy ruby?
Proxy is a structural design pattern that provides an object that acts as a substitute for a real service object used by a client. A proxy receives client requests, does some work (access control, caching, etc.) and then passes the request to a service object.
What does a Proxy do?
A proxy server provides a gateway between users and the internet. It is a server, referred to as an “intermediary” because it goes between end-users and the web pages they visit online. When a computer connects to the internet, it uses an IP address.
What are adapters in rails?
Adapter is a structural design pattern, which allows incompatible objects to collaborate. The Adapter acts as a wrapper between two objects. It catches calls for one object and transforms them to format and interface recognizable by the second object.