Using grunt-connect-proxy
Update 2014/01/13: The interface of grunt-contrib-connect
has slightly changed. Please check my article on how to add middleware. The proxy middleware is still the same, tough.
With any application that communicates with some sort of backend interface exchanging JSON data, you're often in the need to use proxies in your own server configuration to overcome CORS restrictions (either that, or use jsonp, which always seems like a workaround to me). Previously --- in the times we worked with our local Apache servers -- it was always a bit tedious and also caused a lot of time running into the project setup for every team member. Now with our yeoman-grunt-bower setup, it mostly takes no longer than a minute. Cause guess what, there's a already Grunt-task for that.
The problem
Why do we need proxies? Well, I assume your app uses JSON for data transfer, so by calling an URL like http://someserver.com/API/Login
you get all the data you need for your JavaScript application. And in most cases your application is located on the same server, which makes those calls really easy. However, if your are developing locally on your machine and try to call this server, you'll soon see that you won't come very far. Due to CORS restrictions you are not allowed to retrieve data from a different domain than yours.
Proxies help with that. They stand in for the server you want to reach, get the required data, while letting your browser think that you're all in the right domain. So instead by calling http://someserver.com/API
you can call http://localhost/API
.
Creating a proxy with Grunt
Task-runner Grunt has quickly become my most favorite tool when it comes to front-end development. It builds up on Node.js, which allows me to easily create new tasks, plus there are already a lot of great tasks out there which help me with my everyday development. Also for proxies, like the one created by Drewzboto.
Recently we switched our scaffolding process from a GitHub clone clusterf**k to a more streamlined process with Bower and Yeoman, and Yeoman heavily uses Grunt. So this short tutorial will show you how to add a proxy to your already existing Yeoman-like Gruntfile (with connect
and livereload
already set in place.
Installing
Coulnd't be easier. Just type
npm install --save-dev grunt-connect-proxy
With the parameter --save-dev
the module gets added to your package.json
, the one file you have to make available in your code repository for your co-developers.
Setting up a proxy
Search your connect
task in your Gruntfile and add this little snippet:
This snippet tells us, that any call which can't be answered by your machine will be forwared to someserver.com
. There are a lot more options, you might also need https
or port
parameters for instance. Check out the GitHub repo for more information on that.
Add this part to the top of your Gruntfile.js
, right before module.exports
.
and call the proxySnippet
middleware in your livereload
configuration:
Now you're all set up. The last thing you've to do is to call configureProxies
before using connect
in your task, and everything's ready to go:
It's as easy as that. We added this to our main Gruntfile we use for scaffolding our projects, so everytime we need a proxy, it's just peace of cake instead of endless subdomain and subserver configuration in the old httpd-vhosts.conf
file.
Directing to more than one server
This was actually a part which required a lot more thinking and understanding of proxies to get this done right. We had the -- at least for us -- rather specific use case to retrieve our data from more than one server at the same time. Mainly because there was one server handling the content, and one server which took care of all the user data. As you can see, the proxies
option in the default task is actually an array, which means we can easily define more than one proxy configuration.
Creating the new context user
which should allow me to use http://localhost:9000/user
to get to http://userserver.com
. I put that one before the other on purpose, cause at the moment this will actually do nothing at all.
Reason is that the proxy can't decide why to redirect all the user
calls to the other service. We need to define a redirection for the original proxy to make this happen:
This rewrite rule tells the proxy that ever call which starts with user
gets redirected to the user
context we defined earlier. It won't work the other way round, since the context has to be defined beforehand, but that shouldn't matter actually. Feel free to include as many proxies and rewrites. Using this structure everything should work fine.
Bottom line
I've to admit that I've grown on Grunt. Not only that everything just seams so easy to create, it's also one definition that works on every workstation in our department. No need for petty set up phases, just everything is on the go and ready if another team member joins a project. Proxies have been the crux for each project, often leading us to switch to JSONP files just for convenience, and because the Backend guys could actually implement that much, much quicker. No need for that anymore.
Update
In the meantime Grunt's interfaces have changed and Yeoman's generators use the newgrunt-contrib-connect package
instead of the deprecated grunt-connect
one that has been used before. This package includes livereload as a default, though it's not that easy anymore to add middleware than it was before. I addressed this topic in my recent article on The magic behind grunt-contrib-connect. Check it out and add your proxySnippet where it belongs!