{"version":3,"sources":["webapp/webapp_server.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA,8B;;AAEA,2B;AACA,+B;AACA,2B;AACA,+B;AACA,6B;AACA,mC;;AAEA,qC;AACA,yC;AACA,+B;;AAEA,0C;AACA,kC;;AAEA,kC;AACA,mC;;AAEA,Y;AACA,qB;;AAEA,8B;AACA,Y;AACA,yD;AACA,mB;AACA,G;AACA,E;;AAEA,mC;;AAEA,8B;AACA,2B;;AAEA,+C;AACA,kB;;AAEA,uB;;AAEA,gC;AACA,uC;AACA,wB;AACA,4B;AACA,E;;AAEA,4C;AACA,yD;AACA,E;;AAEA,yB;AACA,E;AACA,iE;AACA,kE;AACA,+C;AACA,E;AACA,wE;AACA,+D;AACA,sE;AACA,kE;AACA,W;AACA,E;AACA,kD;AACA,uE;AACA,E;AACA,uE;AACA,iE;AACA,gE;AACA,E;AACA,6D;AACA,qD;AACA,E;AACA,8E;AACA,8E;AACA,8E;AACA,sB;AACA,E;AACA,uE;AACA,qE;AACA,8C;AACA,E;AACA,mE;AACA,W;;;AAGA,yC;AACA,iC;AACA,8B;AACA,oC;AACA,4C;AACA,qE;AACA,G;AACA,wB;AACA,E;;AAEA,kD;AACA,oD;AACA,U;AACA,sC;AACA,4B;AACA,4B;AACA,2B;AACA,I;AACA,E;;AAEA,qD;AACA,kD;;AAEA,2C;AACA,U;AACA,wD;AACA,iC;AACA,I;AACA,E;;AAEA,8E;AACA,gF;AACA,4D;AACA,4B;AACA,4C;AACA,+B;AACA,oD;AACA,mC;AACA,4B;AACA,a;AACA,uC;AACA,oE;AACA,6C;AACA,K;AACA,4B;AACA,E;AACA,+C;AACA,gC;AACA,E;;AAEA,+B;AACA,6B;AACA,sD;AACA,iB;;AAEA,kE;AACA,kE;AACA,oE;AACA,oE;AACA,8D;AACA,kD;AACA,8B;AACA,iB;;AAEA,iE;AACA,gC;AACA,iB;;AAEA,wD;AACA,c;AACA,E;;;AAGA,sE;AACA,+D;AACA,E;AACA,mE;AACA,sE;AACA,E;AACA,oE;AACA,sD;AACA,oE;AACA,oE;AACA,6C;AACA,qD;AACA,E;AACA,4D;AACA,oE;AACA,oB;;AAEA,4B;AACA,8D;AACA,2C;AACA,8C;AACA,yE;AACA,I;;AAEA,+D;AACA,8C;AACA,wE;AACA,uB;AACA,8B;AACA,S;AACA,I;AACA,kE;AACA,8C;AACA,wE;AACA,uB;AACA,8B;AACA,S;AACA,I;AACA,mD;AACA,iC;AACA,0C;AACA,oB;;AAEA,+B;AACA,6D;AACA,uD;AACA,I;AACA,G;;;;AAIA,4E;AACA,wE;AACA,yE;AACA,6E;AACA,iC;AACA,gE;AACA,oE;AACA,sC;AACA,gF;AACA,kC;AACA,gD;AACA,sE;AACA,mD;AACA,mC;AACA,gC;AACA,yC;AACA,K;AACA,iE;AACA,E;;;AAGA,4C;AACA,8C;AACA,0B;AACA,gB;AACA,oB;AACA,2B;;AAEA,qE;AACA,+D;AACA,oE;AACA,qB;AACA,wE;AACA,6B;AACA,+C;;AAEA,kD;;AAEA,sE;AACA,mE;AACA,0D;AACA,gC;AACA,+C;AACA,mC;AACA,c;AACA,K;;AAEA,uC;AACA,mE;AACA,oC;AACA,O;AACA,G;AACA,sC;AACA,E;;AAEA,6D;AACA,iE;AACA,4E;AACA,8C;;AAEA,+B;AACA,uC;AACA,kD;AACA,I;;AAEA,kB;AACA,+B;AACA,0E;AACA,2E;AACA,uC;AACA,qB;AACA,U;AACA,uC;AACA,2D;AACA,G;;AAEA,wC;AACA,c;AACA,uC;AACA,sD;AACA,0B;AACA,kC;AACA,mC;AACA,yC;AACA,oB;AACA,iC;AACA,gC;AACA,c;AACA,W;AACA,U;AACA,gF;AACA,+E;AACA,gF;AACA,+E;AACA,+E;AACA,uD;AACA,4C;AACA,6D;AACA,gF;AACA,wC;AACA,qE;AACA,wC;AACA,O;AACA,yB;AACA,I;AACA,E;;AAEA,4E;AACA,wC;AACA,oE;AACA,wD;AACA,E;AACA,2C;AACA,wE;AACA,wD;;AAEA,gB;;AAEA,qD;AACA,qC;AACA,gF;AACA,oD;AACA,W;AACA,W;AACA,G;AACA,sD;AACA,O;AACA,4C;AACA,e;AACA,W;AACA,W;AACA,G;;AAEA,oC;AACA,wB;AACA,6D;AACA,O;AACA,iB;AACA,c;AACA,I;;AAEA,iD;AACA,iD;AACA,kD;AACA,mE;AACA,W;AACA,mD;AACA,yD;AACA,gD;AACA,W;AACA,G;;AAEA,sC;AACA,W;AACA,W;AACA,G;;AAEA,4E;AACA,2E;AACA,Y;;AAEA,mC;;AAEA,kE;AACA,8D;AACA,kC;AACA,I;AACA,6E;AACA,8E;AACA,kE;AACA,8E;AACA,0E;AACA,0E;AACA,gD;AACA,6B;AACA,mC;AACA,8B;;AAEA,0E;AACA,4E;AACA,4B;AACA,I;AACA,6E;AACA,0E;AACA,0B;AACA,gC;AACA,kE;AACA,qC;AACA,G;;AAEA,2B;AACA,2E;AACA,mC;AACA,6D;AACA,oC;AACA,qE;AACA,qE;AACA,4C;AACA,wD;AACA,K;AACA,G;;AAEA,qB;AACA,4B;AACA,c;AACA,U;AACA,gC;AACA,qB;AACA,2E;AACA,mC;AACA,sD;AACA,2B;AACA,kB;AACA,Q;AACA,oC;AACA,+D;AACA,2B;AACA,kB;AACA,Q;AACA,iB;AACA,G;AACA,E;;AAEA,2C;AACA,kE;AACA,gD;;AAEA,0E;AACA,yB;AACA,sC;AACA,iD;AACA,E;;AAEA,mC;AACA,2B;AACA,iD;;AAEA,4C;AACA,2D;AACA,I;;AAEA,sD;AACA,kC;AACA,uB;AACA,+D;AACA,8D;AACA,sE;AACA,+C;AACA,qD;AACA,sE;AACA,qD;AACA,oE;AACA,6D;;AAEA,4D;AACA,4D;;AAEA,kD;;AAEA,2C;AACA,0C;AACA,oD;AACA,kE;AACA,4D;AACA,wC;AACA,4C;AACA,8C;AACA,6B;AACA,c;;AAEA,iC;AACA,iF;AACA,2C;AACA,6E;AACA,mE;AACA,+B;AACA,gB;AACA,a;AACA,W;AACA,W;;AAEA,uB;AACA,6B;AACA,4E;AACA,2D;AACA,oE;AACA,U;;AAEA,8C;;AAEA,qE;AACA,mD;AACA,8D;AACA,2C;AACA,0B;AACA,sB;AACA,U;AACA,Q;;AAEA,W;AACA,sE;AACA,yD;AACA,oD;AACA,kD;AACA,W;;AAEA,8B;AACA,kD;AACA,mB;AACA,oE;AACA,wB;AACA,O;AACA,O;AACA,I;;AAEA,qD;AACA,2E;AACA,gF;AACA,4E;AACA,gF;AACA,iC;AACA,sB;AACA,iC;AACA,oE;AACA,uE;AACA,iE;AACA,wE;AACA,4D;AACA,oE;AACA,wD;AACA,8D;AACA,sE;AACA,qB;AACA,mE;AACA,iC;AACA,kD;AACA,gC;AACA,S;AACA,O;AACA,M;;AAEA,kC;AACA,kE;AACA,qC;AACA,sD;AACA,uC;AACA,6C;AACA,S;;AAEA,8C;AACA,+B;;AAEA,qD;AACA,uD;AACA,2C;AACA,kE;AACA,Q;AACA,O;AACA,I;;AAEA,yC;;AAEA,c;AACA,sB;;AAEA,iD;AACA,8B;;AAEA,wE;AACA,4C;AACA,qC;AACA,8B;;AAEA,2E;AACA,sB;AACA,oC;AACA,0C;AACA,a;AACA,a;AACA,K;AACA,uB;AACA,6B;AACA,c;AACA,K;;AAEA,6C;AACA,8C;AACA,oE;AACA,oD;AACA,gC;AACA,6E;AACA,+D;AACA,gF;AACA,4C;AACA,mF;AACA,6D;AACA,a;AACA,2E;AACA,a;AACA,4B;AACA,8B;AACA,qC;AACA,qB;AACA,Y;AACA,a;AACA,K;AACA,K;;AAEA,0E;AACA,6B;AACA,2B;;AAEA,0C;AACA,iD;AACA,qC;AACA,uB;AACA,wE;AACA,a;AACA,K;;AAEA,2E;AACA,kD;AACA,wC;AACA,iC;;AAEA,oC;AACA,+E;AACA,+E;AACA,mC;AACA,0C;AACA,6E;AACA,gB;AACA,a;AACA,K;AACA,gE;AACA,gC;AACA,K;;AAEA,qC;AACA,0B;AACA,oB;;AAEA,mB;AACA,iD;AACA,M;AACA,qB;AACA,sC;;AAEA,gD;;AAEA,wE;AACA,6E;AACA,gF;AACA,8D;AACA,0D;AACA,kC;AACA,8D;AACA,gB;AACA,uB;AACA,K;;AAEA,iD;AACA,wD;AACA,yC;AACA,6D;;AAEA,qE;AACA,mC;AACA,Y;AACA,+B;AACA,K;;AAEA,oB;AACA,S;AACA,qD;AACA,iB;AACA,gD;AACA,kC;AACA,gB;AACA,uB;AACA,K;;AAEA,gC;AACA,2B;AACA,c;AACA,qB;AACA,K;;AAEA,gE;AACA,+B;AACA,uB;AACA,c;AACA,K;;;AAGA,0C;AACA,gC;;AAEA,0E;AACA,+E;AACA,mC;AACA,8C;;AAEA,sE;AACA,gF;AACA,S;AACA,qE;;;AAGA,iB;AACA,oB;AACA,2C;AACA,2C;AACA,2B;AACA,mB;AACA,wC;AACA,mC;AACA,M;AACA,+B;AACA,+B;AACA,qC;AACA,U;AACA,Y;AACA,K;AACA,K;;AAEA,2E;AACA,gF;AACA,2B;AACA,0B;AACA,0C;;AAEA,+D;AACA,oD;AACA,mC;AACA,oC;AACA,6E;AACA,6C;AACA,0D;;AAEA,2C;AACA,kC;AACA,+C;;AAEA,qB;AACA,2C;AACA,kC;AACA,Q;;AAEA,oB;AACA,I;AACA,E;;;AAGA,kB;;;AAGA,gC;;AAEA,oD;AACA,8B;AACA,E;;AAEA,4D;AACA,+B;AACA,wC;AACA,E;;AAEA,2D;AACA,8B;AACA,wC;AACA,E;;AAEA,oE;AACA,wE;AACA,qE;AACA,sC;AACA,4B;AACA,mD;AACA,8D;AACA,E;;AAEA,qB;AACA,gD;AACA,wD","file":"/packages/webapp.js","sourcesContent":["////////// Requires //////////\n\nvar fs = Npm.require(\"fs\");\nvar http = Npm.require(\"http\");\nvar os = Npm.require(\"os\");\nvar path = Npm.require(\"path\");\nvar url = Npm.require(\"url\");\nvar crypto = Npm.require(\"crypto\");\n\nvar connect = Npm.require('connect');\nvar useragent = Npm.require('useragent');\nvar send = Npm.require('send');\n\nvar Future = Npm.require('fibers/future');\nvar Fiber = Npm.require('fibers');\n\nvar SHORT_SOCKET_TIMEOUT = 5*1000;\nvar LONG_SOCKET_TIMEOUT = 120*1000;\n\nWebApp = {};\nWebAppInternals = {};\n\nWebAppInternals.NpmModules = {\n  connect: {\n    version: Npm.require('connect/package.json').version,\n    module: connect\n  }\n};\n\nWebApp.defaultArch = 'web.browser';\n\n// XXX maps archs to manifests\nWebApp.clientPrograms = {};\n\n// XXX maps archs to program path on filesystem\nvar archPath = {};\n\nvar bundledJsCssPrefix;\n\nvar sha1 = function (contents) {\n  var hash = crypto.createHash('sha1');\n  hash.update(contents);\n  return hash.digest('hex');\n};\n\nvar readUtf8FileSync = function (filename) {\n  return Meteor.wrapAsync(fs.readFile)(filename, 'utf8');\n};\n\n// #BrowserIdentification\n//\n// We have multiple places that want to identify the browser: the\n// unsupported browser page, the appcache package, and, eventually\n// delivering browser polyfills only as needed.\n//\n// To avoid detecting the browser in multiple places ad-hoc, we create a\n// Meteor \"browser\" object. It uses but does not expose the npm\n// useragent module (we could choose a different mechanism to identify\n// the browser in the future if we wanted to).  The browser object\n// contains\n//\n// * `name`: the name of the browser in camel case\n// * `major`, `minor`, `patch`: integers describing the browser version\n//\n// Also here is an early version of a Meteor `request` object, intended\n// to be a high-level description of the request without exposing\n// details of connect's low-level `req`.  Currently it contains:\n//\n// * `browser`: browser identification object described above\n// * `url`: parsed url, including parsed query params\n//\n// As a temporary hack there is a `categorizeRequest` function on WebApp which\n// converts a connect `req` to a Meteor `request`. This can go away once smart\n// packages such as appcache are being passed a `request` object directly when\n// they serve content.\n//\n// This allows `request` to be used uniformly: it is passed to the html\n// attributes hook, and the appcache package can use it when deciding\n// whether to generate a 404 for the manifest.\n//\n// Real routing / server side rendering will probably refactor this\n// heavily.\n\n\n// e.g. \"Mobile Safari\" => \"mobileSafari\"\nvar camelCase = function (name) {\n  var parts = name.split(' ');\n  parts[0] = parts[0].toLowerCase();\n  for (var i = 1;  i < parts.length;  ++i) {\n    parts[i] = parts[i].charAt(0).toUpperCase() + parts[i].substr(1);\n  }\n  return parts.join('');\n};\n\nvar identifyBrowser = function (userAgentString) {\n  var userAgent = useragent.lookup(userAgentString);\n  return {\n    name: camelCase(userAgent.family),\n    major: +userAgent.major,\n    minor: +userAgent.minor,\n    patch: +userAgent.patch\n  };\n};\n\n// XXX Refactor as part of implementing real routing.\nWebAppInternals.identifyBrowser = identifyBrowser;\n\nWebApp.categorizeRequest = function (req) {\n  return {\n    browser: identifyBrowser(req.headers['user-agent']),\n    url: url.parse(req.url, true)\n  };\n};\n\n// HTML attribute hooks: functions to be called to determine any attributes to\n// be added to the '<html>' tag. Each function is passed a 'request' object (see\n// #BrowserIdentification) and should return null or object.\nvar htmlAttributeHooks = [];\nvar getHtmlAttributes = function (request) {\n  var combinedAttributes  = {};\n  _.each(htmlAttributeHooks || [], function (hook) {\n    var attributes = hook(request);\n    if (attributes === null)\n      return;\n    if (typeof attributes !== 'object')\n      throw Error(\"HTML attribute hook must return null or object\");\n    _.extend(combinedAttributes, attributes);\n  });\n  return combinedAttributes;\n};\nWebApp.addHtmlAttributeHook = function (hook) {\n  htmlAttributeHooks.push(hook);\n};\n\n// Serve app HTML for this URL?\nvar appUrl = function (url) {\n  if (url === '/favicon.ico' || url === '/robots.txt')\n    return false;\n\n  // NOTE: app.manifest is not a web standard like favicon.ico and\n  // robots.txt. It is a file name we have chosen to use for HTML5\n  // appcache URLs. It is included here to prevent using an appcache\n  // then removing it from poisoning an app permanently. Eventually,\n  // once we have server side routing, this won't be needed as\n  // unknown URLs with return a 404 automatically.\n  if (url === '/app.manifest')\n    return false;\n\n  // Avoid serving app HTML for declared routes such as /sockjs/.\n  if (RoutePolicy.classify(url))\n    return false;\n\n  // we currently return app HTML on all URLs by default\n  return true;\n};\n\n\n// We need to calculate the client hash after all packages have loaded\n// to give them a chance to populate __meteor_runtime_config__.\n//\n// Calculating the hash during startup means that packages can only\n// populate __meteor_runtime_config__ during load, not during startup.\n//\n// Calculating instead it at the beginning of main after all startup\n// hooks had run would allow packages to also populate\n// __meteor_runtime_config__ during startup, but that's too late for\n// autoupdate because it needs to have the client hash at startup to\n// insert the auto update version itself into\n// __meteor_runtime_config__ to get it to the client.\n//\n// An alternative would be to give autoupdate a \"post-start,\n// pre-listen\" hook to allow it to insert the auto update version at\n// the right moment.\n\nMeteor.startup(function () {\n  var calculateClientHash = WebAppHashing.calculateClientHash;\n  WebApp.clientHash = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest);\n  };\n\n  WebApp.calculateClientHashRefreshable = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest,\n      function (name) {\n        return name === \"css\";\n      });\n  };\n  WebApp.calculateClientHashNonRefreshable = function (archName) {\n    archName = archName || WebApp.defaultArch;\n    return calculateClientHash(WebApp.clientPrograms[archName].manifest,\n      function (name) {\n        return name !== \"css\";\n      });\n  };\n  WebApp.calculateClientHashCordova = function () {\n    var archName = 'web.cordova';\n    if (! WebApp.clientPrograms[archName])\n      return 'none';\n\n    return calculateClientHash(\n      WebApp.clientPrograms[archName].manifest, null, _.pick(\n        __meteor_runtime_config__, 'PUBLIC_SETTINGS'));\n  };\n});\n\n\n\n// When we have a request pending, we want the socket timeout to be long, to\n// give ourselves a while to serve it, and to allow sockjs long polls to\n// complete.  On the other hand, we want to close idle sockets relatively\n// quickly, so that we can shut down relatively promptly but cleanly, without\n// cutting off anyone's response.\nWebApp._timeoutAdjustmentRequestCallback = function (req, res) {\n  // this is really just req.socket.setTimeout(LONG_SOCKET_TIMEOUT);\n  req.setTimeout(LONG_SOCKET_TIMEOUT);\n  // Insert our new finish listener to run BEFORE the existing one which removes\n  // the response from the socket.\n  var finishListeners = res.listeners('finish');\n  // XXX Apparently in Node 0.12 this event is now called 'prefinish'.\n  // https://github.com/joyent/node/commit/7c9b6070\n  res.removeAllListeners('finish');\n  res.on('finish', function () {\n    res.setTimeout(SHORT_SOCKET_TIMEOUT);\n  });\n  _.each(finishListeners, function (l) { res.on('finish', l); });\n};\n\n\n// Will be updated by main before we listen.\n// Map from client arch to boilerplate object.\n// Boilerplate object has:\n//   - func: XXX\n//   - baseData: XXX\nvar boilerplateByArch = {};\n\n// Given a request (as returned from `categorizeRequest`), return the\n// boilerplate HTML to serve for that request. Memoizes on HTML\n// attributes (used by, eg, appcache) and whether inline scripts are\n// currently allowed.\n// XXX so far this function is always called with arch === 'web.browser'\nvar memoizedBoilerplate = {};\nvar getBoilerplate = function (request, arch) {\n\n  var htmlAttributes = getHtmlAttributes(request);\n\n  // The only thing that changes from request to request (for now) are\n  // the HTML attributes (used by, eg, appcache) and whether inline\n  // scripts are allowed, so we can memoize based on that.\n  var memHash = JSON.stringify({\n    inlineScriptsAllowed: inlineScriptsAllowed,\n    htmlAttributes: htmlAttributes,\n    arch: arch\n  });\n\n  if (! memoizedBoilerplate[memHash]) {\n    memoizedBoilerplate[memHash] = boilerplateByArch[arch].toHTML({\n      htmlAttributes: htmlAttributes\n    });\n  }\n  return memoizedBoilerplate[memHash];\n};\n\nWebAppInternals.generateBoilerplateInstance = function (arch,\n                                                        manifest,\n                                                        additionalOptions) {\n  additionalOptions = additionalOptions || {};\n\n  var runtimeConfig = _.extend(\n    _.clone(__meteor_runtime_config__),\n    additionalOptions.runtimeConfigOverrides || {}\n  );\n\n  var jsCssPrefix;\n  if (arch === 'web.cordova') {\n    // in cordova we serve assets up directly from disk so it doesn't make\n    // sense to use the prefix (ordinarily something like a CDN) and go out\n    // to the internet for those files.\n    jsCssPrefix = '';\n  } else {\n    jsCssPrefix = bundledJsCssPrefix ||\n      __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '';\n  }\n\n  return new Boilerplate(arch, manifest,\n    _.extend({\n      pathMapper: function (itemPath) {\n        return path.join(archPath[arch], itemPath); },\n      baseDataExtension: {\n        additionalStaticJs: _.map(\n          additionalStaticJs || [],\n          function (contents, pathname) {\n            return {\n              pathname: pathname,\n              contents: contents\n            };\n          }\n        ),\n        // Convert to a JSON string, then get rid of most weird characters, then\n        // wrap in double quotes. (The outermost JSON.stringify really ought to\n        // just be \"wrap in double quotes\" but we use it to be safe.) This might\n        // end up inside a <script> tag so we need to be careful to not include\n        // \"</script>\", but normal {{spacebars}} escaping escapes too much! See\n        // https://github.com/meteor/meteor/issues/3730\n        meteorRuntimeConfig: JSON.stringify(\n          encodeURIComponent(JSON.stringify(runtimeConfig))),\n        rootUrlPathPrefix: __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || '',\n        bundledJsCssPrefix: jsCssPrefix,\n        inlineScriptsAllowed: WebAppInternals.inlineScriptsAllowed(),\n        inline: additionalOptions.inline\n      }\n    }, additionalOptions)\n  );\n};\n\n// A mapping from url path to \"info\". Where \"info\" has the following fields:\n// - type: the type of file to be served\n// - cacheable: optionally, whether the file should be cached or not\n// - sourceMapUrl: optionally, the url of the source map\n//\n// Info also contains one of the following:\n// - content: the stringified content that should be served at this path\n// - absolutePath: the absolute path on disk to the file\n\nvar staticFiles;\n\n// Serve static files from the manifest or added with\n// `addStaticJs`. Exported for tests.\nWebAppInternals.staticFilesMiddleware = function (staticFiles, req, res, next) {\n  if ('GET' != req.method && 'HEAD' != req.method) {\n    next();\n    return;\n  }\n  var pathname = connect.utils.parseUrl(req).pathname;\n  try {\n    pathname = decodeURIComponent(pathname);\n  } catch (e) {\n    next();\n    return;\n  }\n\n  var serveStaticJs = function (s) {\n    res.writeHead(200, {\n      'Content-type': 'application/javascript; charset=UTF-8'\n    });\n    res.write(s);\n    res.end();\n  };\n\n  if (pathname === \"/meteor_runtime_config.js\" &&\n      ! WebAppInternals.inlineScriptsAllowed()) {\n    serveStaticJs(\"__meteor_runtime_config__ = \" +\n                  JSON.stringify(__meteor_runtime_config__) + \";\");\n    return;\n  } else if (_.has(additionalStaticJs, pathname) &&\n              ! WebAppInternals.inlineScriptsAllowed()) {\n    serveStaticJs(additionalStaticJs[pathname]);\n    return;\n  }\n\n  if (!_.has(staticFiles, pathname)) {\n    next();\n    return;\n  }\n\n  // We don't need to call pause because, unlike 'static', once we call into\n  // 'send' and yield to the event loop, we never call another handler with\n  // 'next'.\n\n  var info = staticFiles[pathname];\n\n  // Cacheable files are files that should never change. Typically\n  // named by their hash (eg meteor bundled js and css files).\n  // We cache them ~forever (1yr).\n  //\n  // We cache non-cacheable files anyway. This isn't really correct, as users\n  // can change the files and changes won't propagate immediately. However, if\n  // we don't cache them, browsers will 'flicker' when rerendering\n  // images. Eventually we will probably want to rewrite URLs of static assets\n  // to include a query parameter to bust caches. That way we can both get\n  // good caching behavior and allow users to change assets without delay.\n  // https://github.com/meteor/meteor/issues/773\n  var maxAge = info.cacheable\n        ? 1000 * 60 * 60 * 24 * 365\n        : 1000 * 60 * 60 * 24;\n\n  // Set the X-SourceMap header, which current Chrome, FireFox, and Safari\n  // understand.  (The SourceMap header is slightly more spec-correct but FF\n  // doesn't understand it.)\n  //\n  // You may also need to enable source maps in Chrome: open dev tools, click\n  // the gear in the bottom right corner, and select \"enable source maps\".\n  if (info.sourceMapUrl) {\n    res.setHeader('X-SourceMap',\n                  __meteor_runtime_config__.ROOT_URL_PATH_PREFIX +\n                  info.sourceMapUrl);\n  }\n\n  if (info.type === \"js\") {\n    res.setHeader(\"Content-Type\", \"application/javascript; charset=UTF-8\");\n  } else if (info.type === \"css\") {\n    res.setHeader(\"Content-Type\", \"text/css; charset=UTF-8\");\n  } else if (info.type === \"json\") {\n    res.setHeader(\"Content-Type\", \"application/json; charset=UTF-8\");\n    // XXX if it is a manifest we are serving, set additional headers\n    if (/\\/manifest.json$/.test(pathname)) {\n      res.setHeader(\"Access-Control-Allow-Origin\", \"*\");\n    }\n  }\n\n  if (info.content) {\n    res.write(info.content);\n    res.end();\n  } else {\n    send(req, info.absolutePath)\n      .maxage(maxAge)\n      .hidden(true)  // if we specified a dotfile in the manifest, serve it\n      .on('error', function (err) {\n        Log.error(\"Error serving static file \" + err);\n        res.writeHead(500);\n        res.end();\n      })\n      .on('directory', function () {\n        Log.error(\"Unexpected directory \" + info.absolutePath);\n        res.writeHead(500);\n        res.end();\n      })\n      .pipe(res);\n  }\n};\n\nvar getUrlPrefixForArch = function (arch) {\n  // XXX we rely on the fact that arch names don't contain slashes\n  // in that case we would need to uri escape it\n\n  // We add '__' to the beginning of non-standard archs to \"scope\" the url\n  // to Meteor internals.\n  return arch === WebApp.defaultArch ?\n    '' : '/' + '__' + arch.replace(/^web\\./, '');\n};\n\nvar runWebAppServer = function () {\n  var shuttingDown = false;\n  var syncQueue = new Meteor._SynchronousQueue();\n\n  var getItemPathname = function (itemUrl) {\n    return decodeURIComponent(url.parse(itemUrl).pathname);\n  };\n\n  WebAppInternals.reloadClientPrograms = function () {\n    syncQueue.runTask(function() {\n      staticFiles = {};\n      var generateClientProgram = function (clientPath, arch) {\n        // read the control for the client we'll be serving up\n        var clientJsonPath = path.join(__meteor_bootstrap__.serverDir,\n                                   clientPath);\n        var clientDir = path.dirname(clientJsonPath);\n        var clientJson = JSON.parse(readUtf8FileSync(clientJsonPath));\n        if (clientJson.format !== \"web-program-pre1\")\n          throw new Error(\"Unsupported format for client assets: \" +\n                          JSON.stringify(clientJson.format));\n\n        if (! clientJsonPath || ! clientDir || ! clientJson)\n          throw new Error(\"Client config file not parsed.\");\n\n        var urlPrefix = getUrlPrefixForArch(arch);\n\n        var manifest = clientJson.manifest;\n        _.each(manifest, function (item) {\n          if (item.url && item.where === \"client\") {\n            staticFiles[urlPrefix + getItemPathname(item.url)] = {\n              absolutePath: path.join(clientDir, item.path),\n              cacheable: item.cacheable,\n              // Link from source to its map\n              sourceMapUrl: item.sourceMapUrl,\n              type: item.type\n            };\n\n            if (item.sourceMap) {\n              // Serve the source map too, under the specified URL. We assume all\n              // source maps are cacheable.\n              staticFiles[urlPrefix + getItemPathname(item.sourceMapUrl)] = {\n                absolutePath: path.join(clientDir, item.sourceMap),\n                cacheable: true\n              };\n            }\n          }\n        });\n\n        var program = {\n          manifest: manifest,\n          version: WebAppHashing.calculateClientHash(manifest, null, _.pick(\n            __meteor_runtime_config__, 'PUBLIC_SETTINGS')),\n          PUBLIC_SETTINGS: __meteor_runtime_config__.PUBLIC_SETTINGS\n        };\n\n        WebApp.clientPrograms[arch] = program;\n\n        // Serve the program as a string at /foo/<arch>/manifest.json\n        // XXX change manifest.json -> program.json\n        staticFiles[path.join(urlPrefix, 'manifest.json')] = {\n          content: JSON.stringify(program),\n          cacheable: true,\n          type: \"json\"\n        };\n      };\n\n      try {\n        var clientPaths = __meteor_bootstrap__.configJson.clientPaths;\n        _.each(clientPaths, function (clientPath, arch) {\n          archPath[arch] = path.dirname(clientPath);\n          generateClientProgram(clientPath, arch);\n        });\n\n        // Exported for tests.\n        WebAppInternals.staticFiles = staticFiles;\n      } catch (e) {\n        Log.error(\"Error reloading the client program: \" + e.stack);\n        process.exit(1);\n      }\n    });\n  };\n\n  WebAppInternals.generateBoilerplate = function () {\n    // This boilerplate will be served to the mobile devices when used with\n    // Meteor/Cordova for the Hot-Code Push and since the file will be served by\n    // the device's server, it is important to set the DDP url to the actual\n    // Meteor server accepting DDP connections and not the device's file server.\n    var defaultOptionsForArch = {\n      'web.cordova': {\n        runtimeConfigOverrides: {\n          // XXX We use absoluteUrl() here so that we serve https://\n          // URLs to cordova clients if force-ssl is in use. If we were\n          // to use __meteor_runtime_config__.ROOT_URL instead of\n          // absoluteUrl(), then Cordova clients would immediately get a\n          // HCP setting their DDP_DEFAULT_CONNECTION_URL to\n          // http://example.meteor.com. This breaks the app, because\n          // force-ssl doesn't serve CORS headers on 302\n          // redirects. (Plus it's undesirable to have clients\n          // connecting to http://example.meteor.com when force-ssl is\n          // in use.)\n          DDP_DEFAULT_CONNECTION_URL: process.env.MOBILE_DDP_URL ||\n            Meteor.absoluteUrl(),\n          ROOT_URL: process.env.MOBILE_ROOT_URL ||\n            Meteor.absoluteUrl()\n        }\n      }\n    };\n\n    syncQueue.runTask(function() {\n      _.each(WebApp.clientPrograms, function (program, archName) {\n        boilerplateByArch[archName] =\n          WebAppInternals.generateBoilerplateInstance(\n            archName, program.manifest,\n            defaultOptionsForArch[archName]);\n      });\n\n      // Clear the memoized boilerplate cache.\n      memoizedBoilerplate = {};\n\n      // Configure CSS injection for the default arch\n      // XXX implement the CSS injection for all archs?\n      WebAppInternals.refreshableAssets = {\n        allCss: boilerplateByArch[WebApp.defaultArch].baseData.css\n      };\n    });\n  };\n\n  WebAppInternals.reloadClientPrograms();\n\n  // webserver\n  var app = connect();\n\n  // Auto-compress any json, javascript, or text.\n  app.use(connect.compress());\n\n  // Packages and apps can add handlers that run before any other Meteor\n  // handlers via WebApp.rawConnectHandlers.\n  var rawConnectHandlers = connect();\n  app.use(rawConnectHandlers);\n\n  // We're not a proxy; reject (without crashing) attempts to treat us like\n  // one. (See #1212.)\n  app.use(function(req, res, next) {\n    if (RoutePolicy.isValidUrl(req.url)) {\n      next();\n      return;\n    }\n    res.writeHead(400);\n    res.write(\"Not a proxy\");\n    res.end();\n  });\n\n  // Strip off the path prefix, if it exists.\n  app.use(function (request, response, next) {\n    var pathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX;\n    var url = Npm.require('url').parse(request.url);\n    var pathname = url.pathname;\n    // check if the path in the url starts with the path prefix (and the part\n    // after the path prefix must start with a / if it exists.)\n    if (pathPrefix && pathname.substring(0, pathPrefix.length) === pathPrefix &&\n       (pathname.length == pathPrefix.length\n        || pathname.substring(pathPrefix.length, pathPrefix.length + 1) === \"/\")) {\n      request.url = request.url.substring(pathPrefix.length);\n      next();\n    } else if (pathname === \"/favicon.ico\" || pathname === \"/robots.txt\") {\n      next();\n    } else if (pathPrefix) {\n      response.writeHead(404);\n      response.write(\"Unknown path\");\n      response.end();\n    } else {\n      next();\n    }\n  });\n\n  // Parse the query string into res.query. Used by oauth_server, but it's\n  // generally pretty handy..\n  app.use(connect.query());\n\n  // Serve static files from the manifest.\n  // This is inspired by the 'static' middleware.\n  app.use(function (req, res, next) {\n    Fiber(function () {\n     WebAppInternals.staticFilesMiddleware(staticFiles, req, res, next);\n    }).run();\n  });\n\n  // Packages and apps can add handlers to this via WebApp.connectHandlers.\n  // They are inserted before our default handler.\n  var packageAndAppHandlers = connect();\n  app.use(packageAndAppHandlers);\n\n  var suppressConnectErrors = false;\n  // connect knows it is an error handler because it has 4 arguments instead of\n  // 3. go figure.  (It is not smart enough to find such a thing if it's hidden\n  // inside packageAndAppHandlers.)\n  app.use(function (err, req, res, next) {\n    if (!err || !suppressConnectErrors || !req.headers['x-suppress-error']) {\n      next(err);\n      return;\n    }\n    res.writeHead(err.status, { 'Content-Type': 'text/plain' });\n    res.end(\"An error message\");\n  });\n\n  app.use(function (req, res, next) {\n    if (! appUrl(req.url))\n      return next();\n\n    var headers = {\n      'Content-Type':  'text/html; charset=utf-8'\n    };\n    if (shuttingDown)\n      headers['Connection'] = 'Close';\n\n    var request = WebApp.categorizeRequest(req);\n\n    if (request.url.query && request.url.query['meteor_css_resource']) {\n      // In this case, we're requesting a CSS resource in the meteor-specific\n      // way, but we don't have it.  Serve a static css file that indicates that\n      // we didn't have it, so we can detect that and refresh.\n      headers['Content-Type'] = 'text/css; charset=utf-8';\n      res.writeHead(200, headers);\n      res.write(\".meteor-css-not-found-error { width: 0px;}\");\n      res.end();\n      return undefined;\n    }\n\n    // /packages/asdfsad ... /__cordova/dafsdf.js\n    var pathname = connect.utils.parseUrl(req).pathname;\n    var archKey = pathname.split('/')[1];\n    var archKeyCleaned = 'web.' + archKey.replace(/^__/, '');\n\n    if (! /^__/.test(archKey) || ! _.has(archPath, archKeyCleaned)) {\n      archKey = WebApp.defaultArch;\n    } else {\n      archKey = archKeyCleaned;\n    }\n\n    var boilerplate;\n    try {\n      boilerplate = getBoilerplate(request, archKey);\n    } catch (e) {\n      Log.error(\"Error running template: \" + e);\n      res.writeHead(500, headers);\n      res.end();\n      return undefined;\n    }\n\n    res.writeHead(200, headers);\n    res.write(boilerplate);\n    res.end();\n    return undefined;\n  });\n\n  // Return 404 by default, if no other handlers serve this URL.\n  app.use(function (req, res) {\n    res.writeHead(404);\n    res.end();\n  });\n\n\n  var httpServer = http.createServer(app);\n  var onListeningCallbacks = [];\n\n  // After 5 seconds w/o data on a socket, kill it.  On the other hand, if\n  // there's an outstanding request, give it a higher timeout instead (to avoid\n  // killing long-polling requests)\n  httpServer.setTimeout(SHORT_SOCKET_TIMEOUT);\n\n  // Do this here, and then also in livedata/stream_server.js, because\n  // stream_server.js kills all the current request handlers when installing its\n  // own.\n  httpServer.on('request', WebApp._timeoutAdjustmentRequestCallback);\n\n\n  // start up app\n  _.extend(WebApp, {\n    connectHandlers: packageAndAppHandlers,\n    rawConnectHandlers: rawConnectHandlers,\n    httpServer: httpServer,\n    // For testing.\n    suppressConnectErrors: function () {\n      suppressConnectErrors = true;\n    },\n    onListening: function (f) {\n      if (onListeningCallbacks)\n        onListeningCallbacks.push(f);\n      else\n        f();\n    }\n  });\n\n  // Let the rest of the packages (and Meteor.startup hooks) insert connect\n  // middlewares and update __meteor_runtime_config__, then keep going to set up\n  // actually serving HTML.\n  main = function (argv) {\n    WebAppInternals.generateBoilerplate();\n\n    // only start listening after all the startup code has run.\n    var localPort = parseInt(process.env.PORT) || 0;\n    var host = process.env.BIND_IP;\n    var localIp = host || '0.0.0.0';\n    httpServer.listen(localPort, localIp, Meteor.bindEnvironment(function() {\n      if (process.env.METEOR_PRINT_ON_LISTEN)\n        console.log(\"LISTENING\"); // must match run-app.js\n\n      var callbacks = onListeningCallbacks;\n      onListeningCallbacks = null;\n      _.each(callbacks, function (x) { x(); });\n\n    }, function (e) {\n      console.error(\"Error listening:\", e);\n      console.error(e && e.stack);\n    }));\n\n    return 'DAEMON';\n  };\n};\n\n\nrunWebAppServer();\n\n\nvar inlineScriptsAllowed = true;\n\nWebAppInternals.inlineScriptsAllowed = function () {\n  return inlineScriptsAllowed;\n};\n\nWebAppInternals.setInlineScriptsAllowed = function (value) {\n  inlineScriptsAllowed = value;\n  WebAppInternals.generateBoilerplate();\n};\n\nWebAppInternals.setBundledJsCssPrefix = function (prefix) {\n  bundledJsCssPrefix = prefix;\n  WebAppInternals.generateBoilerplate();\n};\n\n// Packages can call `WebAppInternals.addStaticJs` to specify static\n// JavaScript to be included in the app. This static JS will be inlined,\n// unless inline scripts have been disabled, in which case it will be\n// served under `/<sha1 of contents>`.\nvar additionalStaticJs = {};\nWebAppInternals.addStaticJs = function (contents) {\n  additionalStaticJs[\"/\" + sha1(contents) + \".js\"] = contents;\n};\n\n// Exported for tests\nWebAppInternals.getBoilerplate = getBoilerplate;\nWebAppInternals.additionalStaticJs = additionalStaticJs;\n"]}