code

JAX-RS service to proxy an HTTP request in groovy

By Jérémi Joslin · January 26, 2010 · Tags: , , ,

I needed a simple way to proxy an HTTP request and add an authorization header to it, so I created a REST service using JAX-RS and using groovy to call the server. I put the code on our eXo server thanks to eXo IDE, and click deploy and that's it :)

If you need something similar, here is the code:

import javax.ws.rs.Path
import javax.ws.rs.POST
import javax.ws.rs.FormParam

@Path("proxy")
public class Proxy {
  @POST
  @Path("basic_auth")
  public String basic_auth(@FormParam("url") String url, @FormParam("login") String login,
                      @FormParam("password") String password) {
    def encoded = "$login:$password".getBytes().encodeBase64().toString()
    def c= new URL(url).openConnection()
    c.setRequestProperty("Authorization", "Basic $encoded")
    return c.content.text
  }
}

To test it:

curl -d "url=http://TheUrl.com/test&login=my_login&password=my_pwd" \
http://YourDomain.com/rest/proxy/basic_auth/

Open source Sonar Gadget for the Enterprise Portal GateIn

By Jérémi Joslin · January 25, 2010 · Tags: , , ,

I published a new set of gadgets for Sonar on Github. You can add them to your GateIn or Jira Dashboard. This gadget does not need you to deploy anything else to work. You can directly install them from Google AppSpot.

Technically, nothing complex so it's a good example to look at the code to learn how to integrate third party application. Sonar has a simple webservice API that made it easy to reuse the code between the gadgets. The only thing I did not find how to do is how to know when the tendency of a metric should be red or green.

I created a file called sonar.js that is reused among all the gadgets. The sonar object simplifies the call to the API. It sends a request to the API of sonar through the gadget proxy to get the data:

sonar.GetMetrics = function(metrics, callback, extras) {
    var prefs = new gadgets.Prefs(), params = {}, url, key;
    url = prefs.getString("sonar_url") + "api/resources?format=json&resource=" + prefs.getString("sonar_project") + "&metrics=" + metrics + "&time=" + new Date().getTime();

    //if there is any extra parameters, we add them to the URL
    for (key in extras) {
        url = url + "&" + key + "=" + extras[key];
    }

    //We want to get the result as a JSON object
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
    //We send the request
    // It will call the function callback when the data will be loaded with the result in parameter
    gadgets.io.makeRequest(url, callback, params);
};

After, the callback fill-in an html template with the data:

function update_metrics() {
    sonar.GetMetrics("ncloc,lines,classes,packages,functions,accessors", function(res) {
        var resource = res.data[0];

        //Add the information about the project in the template
        $("#resource_name").text(resource.name);
        $("#resource_description").text(resource.description);

        for (var i = 0; i < resource.msr.length; i++) {
            var metric = resource.msr[i];
            //update the values in the template
            $("#m_" + metric.key).text(metric.frmt_val);
        }
        gadgets.window.adjustHeight($(document).height());
    }, {includetrends: "true"});
}

I did not implement all the possible gadgets for sonar, I invite you to take the code, and create your own. You can reuse sonar.js that handle the request to the sonar server and the preferences. Have a look at the gadget of the code overview, it's the easiest one.

Sonar Gadget in GateIn Dashboard:
sonar Gadget in GateIn Dashboard

Sonar Gadget in Jira4:
sonar Gadget in Jira4 Dashboard

Links:

Storing data in cookies in a secure manner

By Jérémi Joslin · January 12, 2010 · Tags: , ,

Having an hour to kill at starbucks without internet, I'm giving a look at the code of Tornado (framework made by the guys of friendfeed). I discovered something quite interesting: the secure cookie.

The concept of the secure cookie is instead of storing data in the session (usually stored in a database as by default in Django) storing the data in a cookie. But, you will tell me it's not secure, anyone can change the value and, for example, see the website with the id of another user. So to make sure the user can't change (or if he does, we can detect it), they sign the request with a secret key. Every time we want to get the value, they check if the signature is valid. The value is stored in clear, so don't store anything a user should not view.

The cookie will look like this:

uid=1234|1234567890|d32b9e9c67274fa062e2599fd659cc14

Parts:

  1. uid is the name of the key
  2. 1234 is your value in clear
  3. 1234567890 is the timestamp
  4. d32b9e9c67274fa062e2599fd659cc14 is the signature made from the value and the timestamp

The interesting code (from Tornado's web.py):

def set_secure_cookie(self, name, value, expires_days=30, **kwargs):
    """Signs and timestamps a cookie so it cannot be forged.

    You must specify the 'cookie_secret' setting in your Application
    to use this method. It should be a long, random sequence of bytes
    to be used as the HMAC secret for the signature.

    To read a cookie set with this method, use get_secure_cookie().
    """
    timestamp = str(int(time.time()))
    value = base64.b64encode(value)
    signature = self._cookie_signature(value, timestamp)
    value = "|".join([value, timestamp, signature])
    self.set_cookie(name, value, expires_days=expires_days, **kwargs)

def get_secure_cookie(self, name):
    """Returns the given signed cookie if it validates, or None."""
    value = self.get_cookie(name)
    if not value: return None
    parts = value.split("|")
    if len(parts) != 3: return None
    if self._cookie_signature(parts[0], parts[1]) != parts[2]:
        logging.warning("Invalid cookie signature %r", value)
        return None
    timestamp = int(parts[1])
    if timestamp < time.time() - 31 * 86400:
        logging.warning("Expired cookie %r", value)
        return None
    try:
        return base64.b64decode(parts[0])
    except:
        return None

def _cookie_signature(self, *parts):
    self.require_setting("cookie_secret", "secure cookies")
    hash = hmac.new(self.application.settings["cookie_secret"],
                    digestmod=hashlib.sha1)
    for part in parts: hash.update(part)
    return hash.hexdigest()

The main use I see for this is to scale. if you don't need to store a lot of things in your session, you can store it in a cookie, so you have one request less to the session store (database or server). Also, you can add easily new server without problem of session replication.

What do you think about this?

Creating a chart with raphael.js from a google spreadsheet

By Jérémi Joslin · January 5, 2010 · Tags: , , , ,

We want to get data from a google spreadsheet and display it as a chart using gRaphaël. We are going to transform the following spreadsheet into a bar graph.

example of graph made with graphael

gRaphaël’s goal is to help you create stunning charts on your website. gRaphaël is based on raphael.js. Raphael.js is a small JavaScript library that should simplify your work with vector graphics on the web. It currently supports Firefox 3.0+, Safari 3.0+, Opera 9.5+ and Internet Explorer 6.0+.

You can download the code of the sample at the end of this article.

1. Loading data from a Google Spreadsheet in javascript

Google spreadsheet offers to serve its data thanks to the Google Data Protocol. The Gdata format that suite to our needs is JSONP. They call it JSON in script. Basically, what we are going to do, is include a script tag in the page that point to the spreadsheet data and when the data is loaded, it will call a function with this data in parameter.

1.1 Preparing our spreadsheet

  • Create a spreadsheet that look like our (2 columns: the first one contain the label, and the second one the data)
  • Save and publish the spreadsheet (Warning! Don't publish private data!)
  • Click on "More Publishing Options," change file format to ATOM & generate URL
  • The URL should look something like 'http://spreadsheets.google.com/feeds/list/[spreadsheetid]/[worksheetid]/public/values.'
  • Find the parts of the URL that match the example below and keep them for the second part.

1.2 Loading the spreadsheet data

/*
 * Specify the information about our spreadsheet
 */
var spreadsheet_id = "tiRm6cBSE3AZJnyLC6Wlysw",
worksheet_id = "od6";

/*
 * Creates a script tag in the page that loads in the 
 * JSON feed for the specified spreadsheet_id/worksheet_id. 
 * Once loaded, it calls loadGraphJSON.
 */
function getJSON() {
  var script = document.createElement('script');

  script.setAttribute('src', 'http://spreadsheets.google.com/feeds/list'
                         + '/' + spreadsheet_id + '/' + worksheet_id + '/public/values' +
                        '?alt=json-in-script&callback=loadGraphJSON');
  // insert the script tag into the header
  document.documentElement.firstChild.appendChild(script);
}

/*
 * Extract the information we need into 2 lists (data and labels)
 * We iterate over the rows (json.feed.entry)
 * and extract our day and distance columns int 2 lists.
 * Once this list created, we call drawChart to draw the graph.
 */
function loadGraphJSON(json) {
    var data = [];
    var labels = [];
    for (var i = 0; i < json.feed.entry.length; i++) {
        var entry = json.feed.entry[i];
        //this is our first column
        labels.push(entry["gsx$day"].$t);
        // this is our second column
        // We need to convert it to float because we get the data as string
        data.push(parseFloat(entry["gsx$distance"].$t));
    }
    drawChart(labels, data);
}

Now that we have loaded the data from the google spreadsheet, we can pass to the second part of this article: displaying the data with raphael.js.

2. Displaying the data with raphael.js

We are going to need some javascript library. insert them at the beginning of your page in the header tag. you can find them on the raphael.js website, or at the end of this article in the downloads.

<script src="raphael.js"></script>
<script src="g.raphael.js"></script>
<script src="g.bar.js"></script>

We can now pass at the interesting part: drawing the chart with raphael.js.

function drawChart(labels, data) {
    /* 
     * Create an instance of raphael and specify:
     * the ID of the div where to insert the graph
     * the width
     * the height
     * Tip: Remember that the reference point (0, 0) is at the top left position.
     */
    var r = Raphael("holder", 600, 300);

    /*
     * Create the chart at the position with the parameters:
     * * pos on the x axis where the drawing start
     * * pos on the y axis where is drawing start
     * * width
     * * height
     * * the values: it needs to be a list of list since you can have multiple data
     * * extra parameters:
     *      stacked: Putting stacked to false seems to create a problem with the labels
     *      type: the end of the bar, it can be: round sharp soft
     */
    var chart = r.g.barchart(10, 10, 580, 280, [data], {stacked: true, type: "soft"});

    /*
     * Create an hover effect to display the value when the mouse is over the graph.
     */
    chart.hover(function() {
        // Create a popup element on top of the bar
        this.flag = r.g.popup(this.bar.x, this.bar.y, (this.bar.value || "0") + " km").insertBefore(this);
    }, function() {
        // hide the popup element with an animation and remove the popup element at the end
        this.flag.animate({opacity: 0}, 300, function () {this.remove();});
    });

    /*
     * Define the default text attributes before writing the labels
     * you can find pore information about the available attributes at:
     *   http://raphaeljs.com/reference.html#attr
     * and in the SVG specification:
     *   http://www.w3.org/TR/SVG/
     */ 
    r.g.txtattr = {font:"12px Fontin-Sans, Arial, sans-serif", fill:"#000", "font-weight": "bold"};

    /*
     * We write the labels.
     * There is a bug not fixed at the time of writing this article. We added a patch to 
     * g.bar.js : http://github.com/DmitryBaranovskiy/g.raphael/issues#issue/11
     */
    chart.label(labels);

    /*
     * Set all the bar greater or equals than 15 to red
     */
    // iterate over all the bar
    for (var i = 0; i < chart.bars[0].length; i++) {
        var bar = chart.bars[0][i];
        // if the value of the bar is greater or equals to 15 we change the color to red
        if (bar.value >= 15) {
            bar.attr("fill", "#bf2f2f");
            bar.attr("stroke", "#bf2f2f");
        }
    }
}

You have now a beautiful Graph. see the result

Download

The code of this howto is available on github: http://github.com/jeremi/raphael-graph-demo.

Download the source

Links

Archive