Browsed by
Month: November 2015

Intercept HTTP requests – AJAX/jQuery

Intercept HTTP requests – AJAX/jQuery

Working in JavaScript we often need to make some HTTP requests to server. Requests could pass some information or try to get some of it. This is a typical functionality in client-server architecture. However, there are some cases that could be useful to do some action for each HTTP request. For example, we may want to add custom headers to all our requests or add authentication code to login into system. We can also capture every response from server to validate something or handle errors globally. This requirements could be met using interceptors. They give us an opportunity to handle HTTP request before sending and after answer receiving.

In this post I will show you how useful interceptors can be in few simple situations with few different technologies.

JavaScript (XMLHttpRequest)

Let’s imagine that we have an application written in vanilla JS. You have implemented authentication system based on token that is passed with every request. It is generated on server and send back in Authorization header to server to confirm user identification for each HTTP request. This functionality is similar to OAuth (http://oauth.net/articles/authentication/). Therefore you want to add this header to your HTTP mechanism globally. It can be easily modifying XMLHttpRequest prototype. Also you want to log each response status

(function(open) {
    XMLHttpRequest.prototype.open = function(method, url, async, user, pass) {
        this.addEventListener("readystatechange", function() {
			if (this.readyState == 4) 
            { 
				console.log(this.status);
			}
        }, false);
        open.call(this, method, url, async, user, pass);
		this.setRequestHeader("Authorization", "Token 123")
    };
})(XMLHttpRequest.prototype.open);

In this example you can see two important things. In line 10 you can add your actions before request will be sent. While line 6 is the place where you can get response data and modify it.

Then you can execute some HTTP request and all magic will be done automatically.

var oReq = new XMLHttpRequest();
oReq.open("get", "www.example.com", true);
oReq.send();

JQuery

Now let’s imagine that you have the same problem as recently, but you should do this in jQuery. This will be much easier, because this library encapsulate each HTTP mechanism using special objects.

To intercept before sending a request you can use $.ajaxSetup function

$.ajaxSetup({
    beforeSend: function (xhr) {
        xhr.setRequestHeader('Authorization', 'Token 123')
    }
});

But to capture responses you should use global callback functions (http://api.jquery.com/ajaxSuccess/, http://api.jquery.com/ajaxError/) as it’s showed below

$( document ).ajaxSuccess(function( event, request, settings ) {
	console.log(request.status);
});

$( document ).ajaxError(function( event, request, settings ) {
	console.log(request.status);
});
Sprawdzanie aktualności rekordu

Sprawdzanie aktualności rekordu

Gdy klient posiada dany zasób w cache’u, a następnie wykonuje zapytanie o ten sam zasób, konieczne jest sprawdzenie jego aktualności. Jest to wykonywane za pomocą zapytań warunkowych. Polegają one na wysłaniu pytania o zasób, jednak zasób ten zostanie przesłany z powrotem tylko w przypadku spełnienia określonych warunków.

W przypadku sprawdzania aktualności rekordu stosuje się dwa podejścia:

  • Sprawdzenie po dacie ważności zasobu
  • Sprawdzenie po „sumie kontrolnej” zasobu

Oba sposoby zostaną później szerzej omówione.

Serwer może odpowiedzieć na takie warunkowe zapytanie na następujące sposoby:

  • Może wysłać odpowiedź ze statusem 304 (Not modified) – nie powoduje to aktualizacji treści przechowywanego zasobu, a jedynie jego daty i daty ważności (jeżeli były one uwzględnione w odpowiedzi serwera). W tym przypadku treść nie jest ponownie przesyłana, jako wynik zapytania zwracana jest wersja znajdująca się w cache
  • Może wysłać odpowiedź ze statusem 200 (OK). Wymusza zaktualizowanie bieżącej przechowywanej zawartości i to właśnie ona jest używana
  • W przypadku zwrócenia informacji o błędzie (na przykład sieciowym) przez serwer, mechanizm cache może zarówno zwrócić komunikat błędu jak i użyć ostatnio zachowanej wartości, aby chwilowo ukryć wystąpienie błędu.

Metoda HEAD także pozwala sprawdzić aktualność danych w cache, jednak nie potrafi ona zaktualizować stanu obiektu (ponieważ nie jest on przesyłany), więc zostanie on pobrany dopiero, gdy wykonamy zapytanie GET.

W przypadku poprawnego wykonania metod nie oznaczonych jako bezpieczne (PUT, POST, DELETE) konieczna jest dezaktualizacja obiektów w cache posiadających ten sam adres i host.

 

Angular – KendoUI Grid – How to integrate it properly

Angular – KendoUI Grid – How to integrate it properly

If you want to use both Angular and Kendo UI components sooner or later you will need to integrate this two libraries.
The majority of this task is quite easy and well documented (http://demos.telerik.com/kendo-ui/grid/angular), but the tricky part is in integration with Angular $http service (or in Angular factories in general). You can use standard Kendo Grid functionality like:

dataSource: {
	type: "aspnetmvc-ajax",
	transport: {
		read: {
			url: "user/registered"),
			type: "GET",
			beforeSend: function (req, options) {
				var authorizationToken = '...';
				req.setRequestHeader('Authorization', authorizationToken);
			},
			complete: function (e) {
				vm.loaded = true;
			}
		}
	}
	...
}

As you can see, you should add some data to each request and also there is custom behaviour when this request successed. But this solution uses jQuery ajax module, not Angular factories. If you want to keep modularity of your code you should use Angular data access methods instead.

In the internet you can find some information about it (1, 2 below), but that is not all. Let’s assume that we have userService factory with method getRegisteredUsers(parameters). We want use it to load data from server.

dataSource: {
	transport: {
		read: function (optionsData) {
			this.options = { prefix: "" };
			var data = kendo.data.transports["aspnetmvc-ajax"].prototype.options.parameterMap.call(this, optionsData.data, "read", false);
			
			var resource = userService.getRegisteredUsers(data).then(
				function success(data) {
					optionsData.success(data);

					vm.loaded = true;
				},
				function failure(data) {
					optionsData.error(data);
				});
		}
	}
	...
}

There are few worth attention elements here. In the first example an object was passed to transport.read property, but in that case we pass function with our custom implementation. On line 7 we use userService factory to obtain data from server, but we need parameters with information about filtering, sorting, etc. We have them in optionsData parameter, but we want have them in other format. To convert them we can use standard Kendo function parameterMap. We need to get these parameters straight from kendo.data.transports (line 5). Then we can pass them in correct format to our factory method and use result to fill dataSource structures (using optionsData.success(data)).
Also we could add our custom behaviour when data will be successfully loaded.

You might wonder, where we lost Authorization code. Because adding authorization header is global behavior, we can move this code to Angular interceptor. That let us implement it in just one place and use it in whole application.

You may read more about parameters conversions in (3, 4)

1 http://blog.falafel.com/using-angularjs-http-service-inside-kendo-ui-datasource/
2 http://blog.falafel.com/using-angularjs-http-service-inside-kendo-ui-datasource-part-2/
3 http://www.telerik.com/forums/parametermap
4 http://www.telerik.com/forums/datasource-transport-function-mode-read-and-wrong-request-parameters

Aktualność obiektu w cache

Aktualność obiektu w cache

Obiekt w cache możemy nazwać aktualnym, jeżeli nie minął jeszcze jego termin ważności. Czas ten jest liczony od momentu pobrania zasobu do momentu określonego przez nagłówki takie jak Expires lub Cache-Control. Jeżeli serwer chce spowodować unieważnienie zachowanego obiektu, powinien on wysłać datę ważności z przeszłości. Dzięki temu podczas najbliższego sprawdzania poprawności lub pobierania zawartości zasobu zostanie on bezwzględnie odświeżony (pobrany ponownie z serwera).

Do momentu aż minie czas ważności danego obiektu wszelkie żądania jego pobrania spowodują skorzystanie z zapamiętanej w cache wartości. Data użyta podczas definiowania czasu ważności, zawsze jest zapisana w strefie czasowej GMT lub UTC. Wskazuje na to skrót na końcu daty, który jest obowiązkowy. Przeciwdziała to problemom z niezgodnością stref czasowych serwera i klienta.

Czas życia może być ustalony za pomocą następujących nagłówków:

  1. dla współdzielonego cache’u używana jest dyrektywa s-max-age w Cache-Content
  2. dla zwykłego – max-age
  3. nagłówek Expires
  4. gdy żaden z wymienionych nagłówków nie wystąpi (czyli serwer w swojej odpowiedzi na zapytanie nie zdefiniuje czasu życia obiektu), zostanie użyta heurystyka do wyliczenia domniemanego czasu ważności

Heurystyczna metoda wyliczania czasu życia zależy od klienta (przeglądarki) z którego korzystamy, jednak często wykorzystuje ona obecność innych nagłówków, które mogą być wskazówką dla daty ważności całego zasobu. Możemy rozpoznać, że czas życia został obliczony, dzięki nagłówkowi:

Warning: 113 - "Heuristic Expiration"

W przypadku, gdy z jakichkolwiek powodów niemożliwe jest odświeżenie rekordu, przeglądarka może zwrócić nieaktualną wartość, dodając nagłówek:

Warning: 110 - "Response is Stale"
Nagłówek Age

Przekazuje informację o tym jak długo (w sekundach) obiekt będzie jeszcze aktualny w cache. Pole jest definiowane po stronie serwera, jednak klient przed użyciem go może dokonać pewnej modyfikacji wartości ze względu na opóźnienie sieciowe.

Expression> vs FUNC

Expression> vs FUNC

Both types of types: Expression<Func<T>> and Func<T> are very similar and could be used for the same type of tasks. I will try to dispel any doubts, when to use expressions or when just functions.

Let’s begin with Func<TResult> type. There is simple shortage encapsulation for delegate type taking no argument and returns value of type TResult. You can define this delegate explicitly:

public delegate TResult Func<in T, out TResult>(T arg)

There are also types like Func<T, TResult>, Func<T1, T2, TResult>, … which differ only with number of input parameters.

Full list of encapsulated delegates is below, but we don’t describe it more detailed:

  1. Func
  2. Action
  3. Predicate
  4. Converter
  5. Comparison

We can define Func both using lambda and by assigning other function

public int ExternalFunction 
{ 
   return 12; 
} 
Func<int> func1 = () => 12; 
Func<int> func2 = ExternalFunction;

Similarly we can define Expression<Func<T>>

Expression<Func<int>> func1 = () => 12;

but the behavior of this two object is different. The Expression type store additionally information (in a tree data structure) about what specific lambda expression does. Thanks to this information it could be possible to process this information and execute this function behavior in different way.

Entity Framework

The difference described above could be well presented in Entity Framework context. If we want to access some data in DbContext we refer to DbSet collection, where we can use Where methods.

This Where methods have different definitions:

IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);

As you can notice, there are two differences in definitions. The first one uses Func and operates on IEnumerable<T> collection, but the second one uses Expression and works on IQuerable<T>.

This example shows that using the Expression type Entity Framework can translate function into SQL query and return IQuerable object, so we can add additional query conditions to this query. By using Func type condition, all dataset will be loaded from database and filtering will be done in .NET application.

Conversions

To convert Expression<Func<T>> to Func<T> you can use Compile method

Func<T> func = expressionFunc.Compile();
Sposób działania cache

Sposób działania cache

Nagłówek Vary

Nagłówek Vary umożliwia określenie, które elementy wiadomości (poza standardowymi: metodą, adresem i hostem) jednoznacznie identyfikują dany zasób. Jest to szczególnie przydatne podczas korzystania z mechanizmu Content negotiation.

Dla przykładu odpowiedź zawierająca

Vary: accept-language

informuje, że nagłówek accept-language powinien być uwzględniony w kluczu obiektów cache. Może to wynikać z faktu, że nagłówek ten pozwala ustalić z klientem język wyniku zapytania, a więc dla każdego języka odpowiedź może się znacząco różnić.

Nagłówek Vary może przyjmować wartości:

  • * – oznacza, że wszystkie nagłówki mają znaczenie podczas identyfikacji odpowiedzi
  • lista nagłówków – wymienia nagłówki, które mają znaczenie.

Używając nagłówka Vary możemy sprawić, że 2 poniższe zapytania będą przez mechanizm cache rozpatrywane jako różne:

GET /resource HTTP 1.1
Host: example.com
Content-Type: text/html
Accepted-Language: pl-PL
Vary: accept-language
GET /resource HTTP 1.1
Host: example.com
Content-Type: text/html
Accepted-Language: en-US
Vary: accept-language

Serwer powinien definiować pola Vary w odpowiedzi tylko, jeżeli wygenerowana odpowiedź zależy ściśle od wartości tych pól. Jednak nie powinien on uwzględniać pól, które według definicji mają wpływ na powodzenie operacji np. nagłówka Authorization.

Sposób działania

Gdy zostaje wykonane zapytanie do serwera, możliwe jest (pod pewnymi warunkami) skorzystanie z zapamiętanej uprzednio zawartości. Posłużymy się przykładem pobierania zasobu przez przeglądarkę internetową. Odpowiedź przechowywana w cache może być ponownie użyta w przypadku, gdy:

  • jest ona aktualna, poprawnie zwalidowana z serwerem lub może być użyta przeterminowna (stale state). Szczegóły w kolejnym temacie Cache-Control
  • istnieje wpis w cache do szukanego URI i zdefiniowanego (w nagłówku Vary) zbioru nagłówków
  • użyta metoda umożliwia skorzystanie z zapamiętanej poprzednio wartości
  • nie jest użyty nagłówek no-cache
  • nie jest użyte szyfrowane połączenie HTTPS

W pewnych sytuacjach możliwe jest zwrócenie zachowanej odpowiedzi bez sprawdzenia jej aktualności. Tak może być w przypadku zerwania połączenia do serwera. Przeglądarka może wyjść z założenia, ze lepiej pokazać starszą wersją niż błąd ładowania danych.

Cache HTTP

Cache HTTP

Główną metodą pracy z użyciem HTTP jest pobieranie oraz zapisywanie zasobów z serwera. Najczęściej odczytujemy informacje, jednak z tym może wiązać się pewien problem. Pobieranie treści z serwera zawsze trwa pewien czas, w szczególności, jeżeli potrzebne jest przesłanie dużej ilości informacji. Może to powodować problemy z wydajnością zarówno ze strony klienta jak i serwera.
Klient musi pobierać wiele różnych informacji, aby je wykorzystać (np. zaprezentować). Z kolei serwer w przypadku podłączenia się do niego wielu klientów, może mieć problem z przepustowością łącz sieciowych. Nadmiarowy transfer jest także dodatkowym kosztem dla właścicieli serwerów, ponieważ część z nich jest rozliczana za gigabajty wykorzystanego transferu.
Warto zauważyć, że niektóre dane potrzebujemy pobierać wielokrotnie. Dobrym przykładem może tu być kod skryptu jQuery pobierany podczas każdego ładowania strony, która z niego korzysta. W wielu przypadkach zasób taki jest rzadko modyfikowany, więc nie musimy go za każdym razem pobierać z serwera. To jest sposób na zmniejszenie obciążenia sieci oraz skrócenie czasu przetwarzania zarówno po stronie klienta jak i serwera.
Cache HTTP jest to mechanizm lokalnego przechowywania wyników zapytań w celu ich późniejszego wykorzystania bez potrzeby ponownego pytania serwera. Mechanizm ten zarządza również kasowaniem przechowywanych odpowiedzi, które się zestarzały, oraz ich aktualizowaniem.
Przechowywana odpowiedź jest uznawana za aktualną, jeżeli może ona być wykorzystana bez ponownej walidacji zasobu.

Cache-not used

Każdy rekord przechowywany w cache jest identyfikowany na podstawie klucza. Odpowiada on parametrom wywołania, dla którego zapamiętana jest odpowiedź. Możliwe jest zachowywanie pełnych odpowiedzi, ale również przekierowań, informacji o błędach oraz częściowych odpowiedzi.
W przypadku korzystania z funkcjonalności negocjowania typu zawartości, może być przechowywane wiele wersji dla jednego zasobu, na przykład dla różnego typu lub języka.
Cache’owaniu mogą podlegać następujące metody:

  • GET,
  • POST – tylko przy użyciu nagłówków Cache-Control lub Expires,
  • HEAD – może być wykorzystywany do sprawdzania aktualności zachowanych obiektów.

W przypadku korzystania z zapytań typu GET w niektórych przypadkach potrzebne jest spełnienie dodatkowych warunków:

  • dla częściowych odpowiedzi wymagana jest obsługa nagłówków Range oraz Content-Range,
  • zapytania zawierające informacje autoryzacyjne (nagłówek Authorization) nie mogą być przechowywane.

Powyżej przedstawione zostały ogólne zasady działania mechanizmu cache. Konkretnymi zaś jego aspektami zajmiemy się później.

Visual Studio – TypeScript version problem

Visual Studio – TypeScript version problem

TypeScript project with Angular in Visual Studio – beginner problem
When you start writing your first project in TypeScript in Visual Studio you can notice some annoying behaviour. At first, you probably have installed TypeScript and configured project. Then you have started reading some tutorials. In my case, I started with tutorial: http://chsakell.com/2015/09/19/typescript-angularjs-gulp-and-bower-in-visual-studio-2015/
When I have started following this lessons, I noticed that hundreds of errors appears. Surprisingly, they were not in my code, but in Angular TypeScript definition file – angular.d.ts. I saw that it is a common problem, so I decided to describe my way to fix it.
typescript_errors
Solution for this problem is quite simple. The reason of errors is version’s differencies between  TypeScript compiler installed and definition files. To solve this, try to follow the steps listed below:
  1. Check on the typescript website http://www.typescriptlang.org/ number of the lastest version.
  2. Check version of TypeScript you have installed in Windows.
    It is usual located in C:Program Files (x86)Microsoft SDKsTypeScript. There could be many directories with version numbers. If you don’t have a current version installed, you should do this now.
  3. Check that PATH variable point this current version directory.
    You can also check that it works correctly in console using command

    tsc -v
  4. Then you should check the version of Typescript which is referenced in your project configuration (*.csproj) file. Open it in text editor and verify following line
    &amp;amp;lt;TypeScriptToolsVersion&amp;amp;gt;1.6&amp;amp;lt;/TypeScriptToolsVersion&amp;amp;gt;
  5. The last step is to ensure, that you are using proper definition files. To do this, update all typings via NuGet package manager
    or
    you can do it in console (depend on the way, you setup them earlier)

    tsd update --save --overwrite