mardi 10 juin 2014

Resize an image with node js

Resize an image with gm & node js:
var fs = require('fs')
 , gm = require('gm')
 , express = require('express');

var port = (process.env.VCAP_APP_PORT || 3000);

var app = module.exports = express();

app.get('/image', function (req, res) {

 gm('DSC03282.JPG')
  .resize(width, height)
  .noProfile()
  .toBuffer(function (err, buffer) {
   res.writeHead(200, {'Content-Type': 'image/jpeg' });
   res.end(buffer, 'binary');
  });
});

app.listen(port);
console.log("Go Image API : 3000");

Create your own Cloud Image Api in few minutes



Links

heroku-buildpack-graphicsmagick : https://github.com/mcollina/heroku-buildpack-graphicsmagick
heroku-buildpack-multi : https://github.com/ddollar/heroku-buildpack-multi
image resize library for node Js : https://github.com/aheckmann/gm

Requirement:

this article : http://ibmbluemix.blogspot.com/2014/05/tips-if-you-have-problem-to-publish.html
the custom buildpack : https://github.com/dam1/cloudfoundry-custom
the Image Api demohttps://github.com/dam1/Imageapi-cloudfoundry

Tuto:

git clone git@github.com:dam1/Image-Service-Api-Example---Node-Js.git

cf push cloudimageapi --no-manifest  -b git://github.com/dam1/cloudfoundry-custom.git

"-b git://github.com/da..." let us choose a custom buildpacks

try http://cloudimageapi.ng.bluemix.net/image?width=400&height=300


You can create your own CDNConnect, Cloudinary, resrc.it, blitline !

mardi 20 mai 2014

lundi 19 mai 2014

How to Link Domain to a Bluemix app

you can't link a domain to a Bluemix app, you can link a subdomain to a Bluemix app. 

for Gymbirds.com i did a redirection from gymbirds.com to d.gymbirds.com the d.gymbirds.com is linked to gymbirds.ng.bluemix.net

 how to do that with Bluemix / Cloudfoundry ?

cf map-route gymbirds gymbirds.com -n d
"gymbirds" is the name of the App on Bluemix, "gymbirds.com" is the domain and "d" is the subdomain linked to the App


 So what's the new "grunt magic" ?

   changeroutebluemix: {
    command: function () {
     pkg = grunt.file.readJSON("package.json");
     var command =
      'cf map-route gymbirdstmp ng.bluemix.net -n gymbirds; ' +//map route gymbirds.ng.bluemix.net to gymbirds tmp
       'cf map-route gymbirdstmp gymbirds.com -n d; ' +
//map route d.gymbirds.com to gymbirdstmp
       'cf unmap-route gymbirds  ng.bluemix.net -n gymbirds; ' +
// unmap route gymbirds.ng.bluemix.net
       'cf unmap-route gymbirds  gymbirds.com -n d; ' +
// unmap route d.gymbirds.com
       'cf rename gymbirds gymbirds' + pkg.version + ' ;' +    
// rename app gymbirds into gymbirdslast
       'cf rename gymbirdstmp gymbirds'; 
// rename gymbirdstmp to gymbirds
     return command;
    }
   },

Example of "cf start myApp" successfull

Starting app gymbirds in org mail@memail.com / space PROD as mail@memail.com...
OK
-----> Downloaded app package (604K)
-----> Downloaded app buildpack cache (296K)
-----> Buildpack version: 2014.3.31.20140416
-----> Requested node range:  0.8.x
-----> Resolved node version: 0.8.26
-----> Downloading and installing node
-----> Found existing node_modules directory; skipping cache
-----> Rebuilding any native dependencies
       npm WARN package.json gymbirds@0.0.2 No repository field.
       mobile-detect@0.1.0 /tmp/staged/app/node_modules/mobile-detect
-----> Writing a custom .npmrc to circumvent npm bugs
-----> Installing dependencies
       npm WARN package.json gymbirds@0.0.2 No repository field.
       npm http GET https://registry.npmjs.org/express/3.3.8
       npm http 200 https://registry.npmjs.org/express/3.3.8
       npm http GET https://registry.npmjs.org/express/-/express-3.3.8.tgz
       npm http 200 https://registry.npmjs.org/express/-/express-3.3.8.tgz
       npm http GET https://registry.npmjs.org/connect/2.8.8
       npm http GET https://registry.npmjs.org/commander/1.2.0
       npm http GET https://registry.npmjs.org/range-parser/0.0.4
       npm http GET https://registry.npmjs.org/mkdirp/0.3.5
       npm http GET https://registry.npmjs.org/cookie/0.1.0
       npm http GET https://registry.npmjs.org/buffer-crc32/0.2.1
       npm http GET https://registry.npmjs.org/fresh/0.2.0
       npm http GET https://registry.npmjs.org/methods/0.0.1
       npm http GET https://registry.npmjs.org/send/0.1.4
       npm http GET https://registry.npmjs.org/cookie-signature/1.0.1
       npm http GET https://registry.npmjs.org/debug
       npm http 200 https://registry.npmjs.org/commander/1.2.0
       npm http GET https://registry.npmjs.org/commander/-/commander-1.2.0.tgz
       npm http 200 https://registry.npmjs.org/range-parser/0.0.4
       npm http 200 https://registry.npmjs.org/commander/-/commander-1.2.0.tgz
       npm http GET https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz
       npm http 200 https://registry.npmjs.org/buffer-crc32/0.2.1
       npm http GET https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz
       npm http 200 https://registry.npmjs.org/fresh/0.2.0
       npm http GET https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz
       npm http 200 https://registry.npmjs.org/methods/0.0.1
       npm http 200 https://registry.npmjs.org/range-parser/-/range-parser-0.0.4.tgz
       npm http GET https://registry.npmjs.org/methods/-/methods-0.0.1.tgz
       npm http 200 https://registry.npmjs.org/cookie/0.1.0
       npm http 200 https://registry.npmjs.org/methods/-/methods-0.0.1.tgz
       npm http 200 https://registry.npmjs.org/send/0.1.4
       npm WARN package.json range-parser@0.0.4 No repository field.
       npm http GET https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz
       npm http GET https://registry.npmjs.org/send/-/send-0.1.4.tgz
       npm http 200 https://registry.npmjs.org/connect/2.8.8
       npm http 200 https://registry.npmjs.org/fresh/-/fresh-0.2.0.tgz
       npm http GET https://registry.npmjs.org/connect/-/connect-2.8.8.tgz
       npm WARN package.json methods@0.0.1 No repository field.
       npm WARN package.json methods@0.0.1 No readme data.
       npm http 200 https://registry.npmjs.org/debug
       npm http GET https://registry.npmjs.org/debug/-/debug-0.8.1.tgz
       npm http 200 https://registry.npmjs.org/cookie-signature/1.0.1
       npm http 200 https://registry.npmjs.org/mkdirp/0.3.5
       npm http 200 https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.1.tgz
       npm http GET https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz
       npm http GET https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz
       npm http 200 https://registry.npmjs.org/send/-/send-0.1.4.tgz
       npm http 200 https://registry.npmjs.org/cookie/-/cookie-0.1.0.tgz
       npm http 200 https://registry.npmjs.org/connect/-/connect-2.8.8.tgz
       npm http 200 https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.5.tgz
       npm http 200 https://registry.npmjs.org/debug/-/debug-0.8.1.tgz
       npm http 200 https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.1.tgz
       npm WARN package.json cookie-signature@1.0.1 No repository field.
       npm http GET https://registry.npmjs.org/mime
       npm http GET https://registry.npmjs.org/keypress
       npm http 200 https://registry.npmjs.org/keypress
       npm http GET https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz
       npm http 200 https://registry.npmjs.org/mime
       npm http GET https://registry.npmjs.org/mime/-/mime-1.2.11.tgz
       npm http 200 https://registry.npmjs.org/mime/-/mime-1.2.11.tgz
       npm http GET https://registry.npmjs.org/qs/0.6.5
       npm http GET https://registry.npmjs.org/formidable/1.0.14
       npm http GET https://registry.npmjs.org/bytes/0.2.0
       npm http GET https://registry.npmjs.org/pause/0.0.1
       npm http GET https://registry.npmjs.org/uid2/0.0.2
       npm http 200 https://registry.npmjs.org/uid2/0.0.2
       npm http GET https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz
       npm http 200 https://registry.npmjs.org/keypress/-/keypress-0.1.0.tgz
       npm http 200 https://registry.npmjs.org/uid2/-/uid2-0.0.2.tgz
       npm WARN package.json uid2@0.0.2 No repository field.
       npm WARN package.json uid2@0.0.2 No readme data.
       npm http 200 https://registry.npmjs.org/bytes/0.2.0
       npm http 200 https://registry.npmjs.org/pause/0.0.1
       npm http GET https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz
       npm http GET https://registry.npmjs.org/pause/-/pause-0.0.1.tgz
       npm http 200 https://registry.npmjs.org/qs/0.6.5
       npm http GET https://registry.npmjs.org/qs/-/qs-0.6.5.tgz
       npm http 200 https://registry.npmjs.org/formidable/1.0.14
       npm http 200 https://registry.npmjs.org/bytes/-/bytes-0.2.0.tgz
       npm http GET https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz
       npm http 200 https://registry.npmjs.org/pause/-/pause-0.0.1.tgz
       npm http 200 https://registry.npmjs.org/qs/-/qs-0.6.5.tgz
       npm http 200 https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz
       npm WARN package.json bytes@0.2.0 No repository field.
       npm WARN package.json pause@0.0.1 No repository field.
       express@3.3.8 node_modules/express
       ├── methods@0.0.1
       ├── range-parser@0.0.4
       ├── debug@0.8.1
       ├── cookie-signature@1.0.1
       ├── fresh@0.2.0
       ├── buffer-crc32@0.2.1
       ├── cookie@0.1.0
       ├── mkdirp@0.3.5
       ├── commander@1.2.0 (keypress@0.1.0)
       ├── send@0.1.4 (mime@1.2.11)
       └── connect@2.8.8 (uid2@0.0.2, pause@0.0.1, qs@0.6.5, bytes@0.2.0, formidable@1.0.14)
-----> Caching node_modules directory for future builds
-----> Cleaning up node-gyp and npm artifacts
-----> No Procfile found; Adding npm start to new Procfile
-----> Building runtime environment
-----> Uploading droplet (6.0M)

1 of 1 instances running

App started

Showing health and status for app gymbirds in org mail@memail.com / space PROD as mail@memail.com...
OK

requested state: started
instances: 1/1
usage: 1G x 1 instances
urls: gymbirds.ng.bluemix.net

     state     since                    cpu    memory        disk          
#0   running   2014-05-18 11:48:10 PM   0.0%   34.2M of 1G   22.9M of 1G   

How to publish / start a NodeJs App on Bluemix



The package.json is important for publish an app on Bluemix

Here is a sample of a package.json,  you should have something like that but with differents dependencies.
When you install a package with npm use "--save"
ex: "npm install stripe --save" automatically save the dependency in the package.json

{
 "name": "myApp",
 "version": "0.0.2",
 "engines": {
  "node":     ">=0.10.0"
 },
 "scripts": {
  "start": "node app.js"
 },
 "dependencies": {
  "stripe": "~2.5.3",
  "cors": "~2.3.1",
  "express": "~4.2.0",
  "body-parser": "~1.2.0",
  "email-templates": "~0.1.8",
  "nodemailer": "~0.6.5",
  "moment": "~2.6.0"
 }
}
the command following just upload you app on bluemix:
cf push myApp --no-manifest --no-start -c "node app.js"
the command following read you package.json, install al the dependencies, and then start your App, so if you forget one you will not be able to start the app:
cf start myApp

How to redirect on the mobile or desktop version ?

https://www.npmjs.org/package/mobile-detect

app.get('*', function (req, res) {
 md = new MobileDetect(req.headers['user-agent']);
 if (md.mobile() != null) {
  res.writeHead(301,
   {Location: 'http://m.gymbirds.com'}
  );
  res.end();
  console.log('mobile');
 }
 else {
  res.sendfile(__dirname + '/' + req.path);
  console.log('desktop');
 }
});