I had a niche need to automate yeoman, and spent a few hours trying to overcome
yeoman’s insistance on interactive prompts. As far as I can tell the prompting library,
Inquirer.js, has no way to read a response file, or at least
be commanded to run in non-interactive mode.
Enter an old-school POSIX friend in core-utils… yes
The yes utility continuously outputs ‘Y’ followed by a newline as long as another process is reading the stdout stream.
Very convenient for piping to another program.
Here’s how I automated Yeoman to generate a new AngularJS app:
12345678
# yeoman has a number of interactive prompts, and sadly doesn't support a batch mode# so we use the coreutils `yes` utility to accept all the default answers in yeoman;# yes is not part of msysgit, so skip this when running on windows without cygwinwhich yes > /dev/null
if[$? -eq 0 ]thenyes | yo angular
fi
I spent a couple of hours tonight sorting out how to wire a NodeJS Express app to use both
the Passport authentication strategy for GitHub OAuth with
Swagger for Express. Normally, this
would be fairly straightforward. A wrinkle with other examples is I needed to disallow
all anonymous access for an intranet app.
I’m a big fan of Swagger UI – it’s a great, DRY way to auto-document your REST APIs. I expected Swagger
to be a natural fit with NodeJS. Suprisingly, I found the Swagger.Net implmentation for .Net’s WebAPI
to be considerably easier to use compared to the NodeJS implementation.
Swagger.Net easily drops into an existing WebAPI project. Not so with NodeJS.
In Node, you really have to write your REST APIs from the ground up using the Swagger packge. The other
wacky part for me was you need two Express apps side-by-side to handle requests for both REST APIs and
static content.
As we’ll see below, the subapp sandboxes the Swagger package to the /api/* route.
(I use a local copy of the swagger-node-express package downloaded to my source tree because I found that
the npm package was considerably outdated compared to the master branch of the swagger-node-express repo.)
Next, we configure PassportJS to use GitHub OAuth. GitHub will POST back to the route
/auth/github/callback upon successful authentication.
A critical piece of wiring is a reusable function to verify authentication:
1234567891011
// middleware to ensure user is authenticatedfunctionauthenticate(req,res,next){if(req.isAuthenticated()){returnnext();}if(req.headers['x-requested-with']==='XMLHttpRequest'){res.send("Authentication required",401);}else{res.redirect('/login');}}
The next key wiring is to configure both Express apps to use Passport as well as our authenticate function.
This approach prevents infinite OAuth HTTP 302 redirects:
// configure express to use swagger for the `/api` routesubpath.configure(function(){subpath.use(express.cookieParser());subpath.use(express.bodyParser());subpath.use(express.methodOverride());subpath.use(express.session({secret:config['SESSION_TOKEN']}));subpath.use(passport.initialize());subpath.use(passport.session());subpath.use(authenticate);swagger.setAppHandler(subpath);});// configure express for the static content on the `/` routeapp.configure(function(){app.use(express.cookieParser());app.use(express.bodyParser());app.use(express.methodOverride());app.use(express.session({secret:config['SESSION_TOKEN']}));app.use(passport.initialize());app.use(passport.session());app.use(app.router);app.use(authenticate);app.use('/api',subpath);/* mount `/api` using the subapp */// default document middleware for swagger/index.htmlapp.use('/swagger',function(req,res,next){if(req.url==='/swagger'){res.redirect('/swagger/');}next();});app.use('/swagger',express.static(path.join(__dirname,'public/swagger')));app.use(express.static(path.join(__dirname,'public/client')));});
Finally, we define routes to handle OAuth logins and callbacks, then configure Swagger using the
route /api/doc, and finally start the server.
To all my UI devs out there, I finally had some time to rework json-proxy into a lean and meaner machine.
If you haven’t seen the proxy before, it enables a UI dev to proxy localhost URLs to a remote server.
Why do this? Say you are doing an AngularJS front end, and want to wire some data to a REST API call like $http.get('/api/foo/1').
Before, you had to mock out the JSON result, run the entire server stack locally, or just cross your fingers and hope it works on the integration server.
Well, the proxy lets you transparently reroute http://localhost/api/foo/1 from your local laptop to an integration server
like http://integration-server/api/foo/1. No CORS. No JSONP. No nonsense.
Grunt
With v0.1.0, the big change is the proxy now works right inside the Grunt server. Here’s an example config from the scaffold project:
1234567891011121314151617181920212223242526272829
connect:{options:{port:9000,// Change this to '0.0.0.0' to access the server from outside.hostname:'localhost'},livereload:{options:{middleware:function(connect){return[require('json-proxy').initialize({proxy:{forward:{'/api/':'http://integration-server:4040','/swagger/':'http://integration-server:4040',},headers:{'X-Forwarded-User':'John Doe','X-Forwarded-User-Email':'john.doe@example.com'}}}),lrSnippet,mountFolder(connect,'.tmp'),mountFolder(connect,yeomanConfig.app)];}}},
Auth Headers
Even better, you can inject headers into proxied request. So if you remote server requires an Authorization header with an OAuth-style token, or sits behind an Enterprise SSO appliance, you can add the headers to deal with bypassing the remote server authentication.
CLI
The CLI utility is also improved. The CLI properly supports global installation.
If you install using sudo npm install -g json-proxy, you can invoke the proxy simply as json-proxy with whatever args you want.
CLI usage info:
12345678910111213141516171819202122232425
json-proxy [-c configFile][-p port][-f proxy forwarding rule][-h header rule][-html5mode [defaultFile]][directory]Examples:
json-proxy -p 8080 -f "/api=http://server" -f "/=http://localhost:9000" .
json-proxy -h "X-Forwarded-User=johndoe" /tmp/folder
json-proxy -c "/tmp/config.json"By default, looks for a config file at ./json-proxy.json
Environmental variables:
JSON_PROXY_PORT see --port
JSON_PROXY_WEBROOT directory
JSON_PROXY_GATEWAY --gateway
JSON_PROXY_GATEWAY_AUTH "username:password" credentials for --gateway)Options:
-p, --port The TCP port for the proxy server
-f, --forward a forwarding rule (ex. /foo=server/foo) -h, --header a custom request header (ex. iv-user=johndoel) -c, --config a config file
-g, --gateway URL for a LAN HTTP proxy to use for forwarding requests
--html5mode support AngularJS HTML5 mode by catching 404s
-?, --help about this utility
--version version info
Just released a new “API” provider for the NodeJS authentication middelware Passport. The ReverseProxy API provider enables NodeJS apps to authenticate users via HTTP Request Proxies injected by a reverse HTTP proxy server. Reverse Proxy authentication is a technique seen in enterprise Single Sign On (SSO) where an authentication server sits in front of the web server/app server. The proxy server authenticates users against some enterprise store (e.g., LDAP Directory).
After successful authentication, the proxy will forward the original request to the target web server/app server.
Typically, the proxy will inject identifying information about the user (e.g., username, email address, display name) into custom HTTP request headers. IBM’s WebSeal application for SSO does exactly this.
Suprisingly, no one had written a passport strategy that uses custom HTTP headers yet. So, I coded up an implementation,
inspired by Passport’s passport-http strategy for HTTP basic authentication.
sudo npm install -g cordova
cordova create ~/MyApp MyApp
cd ~/MyApp
cordova platform add ios
cordova plugin add emailcomposer # using the http://plugins.cordova.io registrycordova build
# manually update the www/index.html file to link to www/examples/EmailComposer.html# run the app in the iOS 5.x+ simulator via Xcode
Major changes to the plugin include:
Support for file attachments using files paths, or file contents as encoded strings
Simpler JavaScript API
Support for cordova.require to load the plugin in JavaScript which means less global namespace pollution
I love shell scripting, which is probably why I seem to somehow get organically involved in “DevOps” on most of my project work. I’m drafting up a series of posts on tips and tricks for shell scripts (with love for both Windows and *nix) – it seems to be a fading art among recent comp sci grads. Until I finish those posts, I wanted to share a quick script I wrote to reassign the TCP/IP port binding for Microsoft’s Web Deployment Agent service.
I spend a lot of time in the Windows Command Prompt. Most developers I work with don’t know some of the tricks up the Command Prompt’s sleeve. So allow me to share some of my favorite settings.
I am fortunate enough to be with a company now that encourages professional writing, which hasn’t always been the case. Troy’s article really resonated with me that developers have an insatiatable appetite for consuming knowledge. We take information all the time, and there’s a duty on all our parts to give back and not just take. Thanks to both Troy any my colleague Alex for pushing me to do more!
Many years ago I learned an metaphor from a very accomplished veteran of the US military that is quite applicable to coding: “you have to either be tough or smart to succeed”. Say you want to navigate from point A to point B, and there just happens to be a tall mountain between the two points. The tough guy takes a straight line route, ardously ascending and descending the mountain. The smart guy circumnavigates the mountain, saving time and energy.
I know developers like to be the smartest person in the room, but, I am self-aware enough to admit I often fall into the “tough” camp – hacking into the late hours until the job is done. I suppose this blog will be a true measure of how many (or how few) smart/clever ideas I have up my sleeve!