Tuesday, January 29, 2013

Angular JS Resource to support Header

I just made a pull request from 1.1.2 which support header parameters in resource actions which very useful for doing authentication.
 https://github.com/angular/angular.js/pull/1906

 Here is the example how to use it


  $scope.signIn = function () {
      Authenticate.signIn(null,null,
          function (data, headers) {
              console.log(headers('x-token'));
              tokenHandler.setToken(headers('x-token'));
          },
          function(data, status, headers, config) {
              console.log('fail');
          },
          { 'Authorization': 'Basic dGVzdGtrMTNssdfdfsgsdfzdC5jb206cGFzc3dvcmQhMQ==' }
      );

===
 And Here is the example to use Token Handler https://gist.github.com/4662548

Thursday, January 24, 2013

Cross-origin resource sharing (CORS)


Overview

Cross-origin resource sharing (CORS) is a mechanism that allows a web page to make XMLHttpRequests to another domain.[1] Such "cross-domain" requests would otherwise be forbidden by web browsers, per the same origin security policy. CORS defines a way in which the browser and the server can interact to determine whether or not to allow the cross-origin request.[2] It is more powerful than only allowing same-origin requests, but it is more secure than simply allowing all such requests.


Scenario

"Site A" needs to send GET/POST request to "Site B"
When "Site A" send a GET/POST request to "Site B" will automatically cancelled that request.
This type of request traditionally would not be allowed under the browser’s same origin policy.


Enable CORS

In order CORS to allow "Site A" to get the response from "Site B", we need to add Access-Control-Allow-Origin response header "Site B".
For Microsoft IIS7, merge this into the web.config file at the root of your application or site:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
   </httpProtocol>
 </system.webServer>
</configuration>
Check this page for more information [enable-cors.org/server.html]



Challenge 1 - Handling a special request

Cross-origin requests come in two flavors:
  • simple requests
  • "special requests" (a term I just made up)

Simple requests are requests that meet the following criteria:
  • HTTP Method matches (case-sensitive) one of: HEAD, GET, POST
  • HTTP Headers matches (case-insensitive): Accept, Accept-Language, Content-Language, Last-Event-ID, Content-Type
  • Content type :application/x-www-form-urlencoded, multipart/form-data, text/plain

If you send a request outside this simple request criteria which is "not-so-simple requests", The browser first issues a preflight request, which is like asking the server for permission to make the actual request.
preflight request will send a OPTIONS request.
Once permissions have been granted, the browser makes the actual request. The browser handles the details of these two requests transparently. The preflight response can also be cached so that it is not issued on every request.



Sample scenario : If you use [angularJS] v1.0.3 to make a $http request, It will add a custom header "X-Requested-With" into the request. Or we may also need to add custom header such as "X-BLA-*".
This kind of request will trigger preflight request which will ask the server permission to make the actual request.
To enable this request to be passed into the server, we need enable Access-Control-Allow-Headers response header However when we enable this Access-Control-Allow-Headers,
It requires us to provide specific origin in Access-Control-Allow-Origin response header.
<add name="Access-Control-Allow-Origin" value="http://localhost" />
<add name="Access-Control-Allow-Credentials " value="true" />
For more information, please check this site [html5rocks.com/cors]

.


Challenge 2 - Anti Forgery Session Token

Another challenge with CORS is dealing with [Anti Frogery Session Token]
There are 2 things you need to provide inside your POST request in order to satisfy Anti Frogery validation on the server.
  • The incoming request has a Request.Form entry called __RequestVerificationToken
  • Session ID which stored on your Cookie.

The server will use Session ID to get verification token and try to match this token with __RequestVerificationToken.

To solve this problem, both client and server need to allow credential to be shared between request and response.
  • Enable Access-Control-Allow-Credentials on the server.
<add name="Access-Control-Allow-Credentials " value="true" />
  • Enable .withCredentials on your request.
        $.ajax({

            // The 'type' property sets the HTTP method.
            // A value of 'PUT' or 'DELETE' will trigger a preflight request.
            type: 'POST',
            data: serializedData,
            
            // The URL to make the request to.
            url: $scope.url,

            xhrFields: {
                // The 'xhrFields' property sets additional fields on the XMLHttpRequest.
                // This can be used to set the 'withCredentials' property.
                // Set the value to 'true' if you'd like to pass cookies to the server.
                // If this is enabled, your server must respond with the header
                // 'Access-Control-Allow-Credentials: true'.
                withCredentials: true
            },
            ....
        });


Limitations

There are still 2 limitations which CORS can't handle at this moment.
  • 302 (Redirect) Response code with special request (Which initialize preflight request).
In Fiddler it will look like this
1. OPTIONS - http://siteB => 404 (not found)
2. POST - http://siteB => 302 (redirect with location)
3. GET - http://siteB/new location => 200 (OK) 
Even in fiddler, we get 200 response status, the browser keep reject this response.

  • Redirect from HTTP to HTTPS (vice versa)
This issue happen when your HTTP request redirects you to HTTPS protocol.
In Fiddler it will look like this
1. GET - http://siteB => 302 (redirect to HTTPS)
2. GET - https://siteB => 200 (OK)
Again, even in fiddler, we get 200 response status, the browser keep reject this response.



Sample code (end to ends)

  • Enable CORS on server side by adding this response header into web.config
<system.webServer>
    <httpProtocol>
      <customHeaders>
         <add name="Access-Control-Allow-Origin" value="http://localhost:55129" />
  <add name="Access-Control-Allow-Credentials " value="true" />
  <add name="Access-Control-Allow-Headers" value="X-Requested-With" /> 
      </customHeaders>
    </httpProtocol>
</system.webServer>

  • Client request using AJAX
  $.ajax({
            // The 'type' property sets the HTTP method.
            // A value of 'PUT' or 'DELETE' will trigger a preflight request.
            type: 'GET',

            // The URL to make the request to.
            url: 'http://siteB,

            // The 'contentType' property sets the 'Content-Type' header.
            // The JQuery default for this property is
            // 'application/x-www-form-urlencoded; charset=UTF-8', which does not trigger
            // a preflight. If you set this value to anything other than
            // application/x-www-form-urlencoded, multipart/form-data, or text/plain,
            // you will trigger a preflight request.
            contentType: 'text/plain',

            xhrFields: {
                // The 'xhrFields' property sets additional fields on the XMLHttpRequest.
                // This can be used to set the 'withCredentials' property.
                // Set the value to 'true' if you'd like to pass cookies to the server.
                // If this is enabled, your server must respond with the header
                // 'Access-Control-Allow-Credentials: true'.
                withCredentials: true
            },

            headers: {
                // Set any custom headers here.
                // If you set any non-simple headers, your server must include these
                // headers in the 'Access-Control-Allow-Headers' response header.
            },

            success: function (data, textStatus, jqXHR) {
                // Here's where you handle a successful response.
                $scope.data = data;
                $scope.$apply();
            },

            error: function (jqXHR, textStatus, errorThrown) {
                // Here's where you handle an error response.
                // Note that if the error was due to a CORS issue,
                // this function will still fire, but there won't be any additional
                // information about the error.
                alert('Woops, there was an error making the request. - with status ' + errorThrown);
            }
        });

  • Or Client request using $http module from angularJS
    $http.get($scope.url, {withCredentials : true}).
          success(function (data, status) {
              $scope.data = data;
              $scope.$apply();
          }).
          error(function (data, status) {
              $scope.data = data || "Request failed";
              $scope.$apply();
          }
        );

Friday, January 04, 2013

Graph DB on Azure - unable to access jarfile windows-service-wrapper-*.jar

Recently I tried to publish neo4j into Azure cloud.
Fortunately, There is brilliant readify guy has started this and did all the hard work.

I need fix problem related to windows power shell support error "Unable to access jar file windows-service-wrapper-*.jar" which seems doesn't recognise the wildcard command properly.

Thanks to "Valsaul", which provide me with a solution to edit bin\base.bat file and replace the line with
windows-service-wrapper-*.jar 
and changed it to
windows-service-wrapper-4.jar , which was the name of the file that came with M1.8.1.


If you need to use the latest Neo4j blob, clone my fork at
https://github.com/kkurni/Neo4j.Server.AzureWorkerHost

and you can put your latest Neo4j into neo4j-install.zip

Wednesday, January 02, 2013

Git Rebase PullRequest formula

If you want to do Git Rebase your pull request instead of merge you can follow this step wisely.


//checkout your branch
git checkout branchName

//git rebase to your master
git rebase master

//checkout master
git checkout master

//fast forward your master to your branch pointer by merge it.
git merge branchName

//push your master to your repository
Git push origin master

//push your branch to your repository with force
Git push –f origin branchName

---- Once you done this, Github will automatically detect your pull request rebase.
-----You can check on Github and hit delete button or you can do manually using this step

//delete your branch on your repository first
Git push origin :branchName

//delete your local branch
Git branch –D branchName