GIT – submodules – rozdzielenie repozytoriów

GIT logo

Jednym z założeń Shopping Manager było stworzenie aplikacji restowej – backend napisany w Go oraz frontend utworzony przy pomocy Angular2. Jako, że jest to również aplikacja konkursowa, na tegoroczną edycję Daj Się Poznać, zobligowany byłem całość umieścić w jednym repozytorium.

Proces dewelopmentu nie był przez to utrudniony. Wszak pracę nad aplikacją wykonuję cały czas sam. Nie zbaczając z toru, tkwiłem jednak w tym błędnym rozwiązaniu.

Moment krytyczny

Przyszedł jednak dzień, że aplikacja powinna opuścić localhosta. Wtedy też, chcąc nie chcąc, musiałem rozdzielić backend od frontendu.

Z pomocą przyszedł niezawodny GIT. Oferuje on rozwiązanie submodules, które doskonale nadaje się do rozwiązania wszystkich problemów. Pierwsze zdania z dokumentacji znakomicie odzwierciedlają mój problem:

It often happens that while working on one project, you need to use another project from within it. Perhaps it’s a library that a third party developed or that you’re developing separately and using in multiple parent projects. A common issue arises in these scenarios: you want to be able to treat the two projects as separate yet still be able to use one from within the other.

Dwa nowe repozytoria

Dotychczasowa struktura wyglądała następująco:

GIT - Shopping Manager

By rozdzielić repozytoria, trzeba wpierw założyć nowe. Dlatego stworzyłem odpowiednio shopping-manager-api i shopping-manager-web:

Po odpowiednim sformatowaniu plików i przygotowaniu niezależnych repozytoriów, możemy je umieścić w starym. Aby to zrobić należy posłużyć się komendą:

git submodule add nazwa_repozytorium

Dodatkowo zależało mi, by struktura projektu została taka sama. Dlatego po nazwie repozytorium podałem nazwę folderu, w którym submodule miał zostać stworzony:

git submodule add git@github.com:dawidrylko/shopping-manager-api.git api

Repozytorium zostało sklonowane do wskazanego katalogu. Został także stworzony plik .gitmodules, którego struktura przedstawia się następująco:

Jeżeli teraz spojrzymy na główne repozytorium, możemy zauważyć, że wygląd folderu się zmienił. Dodatkowo obok folderu widnieje commit na który wskazuje submodule.

GIT submodules

Aktualizacja

Repozytoria, które zawarte są w submodułach, wskazują na odpowiedniego commita. Aby zaaktualizować submodules wykonujemy komendę:

git submodule update --remote --merge

Angular2 – HTTP – wysyłanie danych – @angular/http

wysyłanie danych

Wysyłanie danych w Angular2 jest możliwe dzięki metodzie post() z pakietu http. W tym wpisie wykorzystamy reaktywny formularz stworzony wcześniej i wyślemy dane na backend naszej aplikacji.

Wysyłanie danych – http.post()

Do wysłania danych użyjemy metody post() z poznanego już pakietu http.

post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response>

Post składa się z trzech parametrów: url, body oraz options. Jako pierwszy parametr podajemy adres URL endpointa w postaci ciągu znaków np. 'http://localhost:8001/product'. Następnie body, czyli dane, które chcemy wysłać. Ostatni parametr to opcje. Jak widać po deklaracji tylko url i body są wymagane.

Nawiązując do przykładu prosty http.post() w naszej aplikacji wygląda następująco:

Opcje – Options

Aby dodać options należy zaimportować Headers i RequestOptions. Obie klasy znajdują się również w paczce http.post().

Tworzymy lokalną zmienną headers, która zawiera zdefiniowane przez nas nagłówki. Następnie tworzymy opcje, w których umieszczamy headers. Tak przygotowaną zmienną, przekazujemy jako trzeci parametr w metodzie post.

Wysyłanie danych

Aby nasza metoda zadziałała, należy ją wykorzystać w metodzie onSubmit w formularzu.

Wykorzystujemy tutaj stworzoną wcześniej metodę create() z naszego repozytorium. Narazie wyświetlamy console.info jeżeli request zakończy się powodzeniem lub console.error w przypadku błędu.

wysyłanie danych - http - 201 - Created

wysyłanie danych - http - 404 - error

CORS – golang – gorilla/handlers

gorilla/handlers - CORS

Dzisiejszy wpis został wymuszony przez zaistniałą sytuację. Powrócił bowiem jak bumerang problem, który zignorowałem wcześniej. Stąd też rozprawka zatytułowana: CORS – golang, która jest opisem problemu z Cross-Origin Resource Sharing na serwerze w języku Go.

Trochę teorii

CORS (Cross-Origin Resource Sharing) to technologia pozwalająca na wykonywanie asynchronicznych zapytań do każdego miejsca w sieci. Warunek jest jeden, musimy dostać zgodę na używanie zasobów tego miejsca.

Cross-origin resource sharing (w skrócie CORS) – mechanizm umożliwiający współdzielenie zasobów pomiędzy serwerami znajdującymi się w różnych domenach. Ściślej rzecz biorąc chodzi o możliwość wykonywania żądań AJAX między takimi serwerami przy zachowaniu pewnych ograniczeń co do dopuszczalnego źródła żądania. – za wikipedią

CORS – goolang

U mnie problem wystąpił w momencie wysyłania danych z formularza na wcześniej przygotowany endpoint.

CORS - golang - 404 Not found

Nasze zapytanie zostaje przerwane w momencie wysyłania OPTIONS, dostajemy status 404 Not Found. Dodatkowo w konsoli dostajemy poniższy komunikat:

XMLHttpRequest cannot load http://localhost:8001/product. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access. The response had HTTP status code 404.

Diagnoza

Błąd ewidentnie wskazuje na problem z CORSem. W celu przyspieszenia pracy nad API, poszedłem na pewne uproszczenia w konfiguracji. Dla przypomnienia start mojego serwera, bez ceregieli, wyglądał następująco:

http.ListenAndServe(":8001", Router)

gorilla/handlers

Na ratunek, przyszła biblioteka gorilla/handlers. Jak nazwa wskazuje, jest to zbiór handlerów do pakietu net/http. Użycie jest bardzo proste i intuicyjne.

Instalujemy bibliotekę:

go get github.com/gorilla/handlers

Po imporcie i wpięciu w serwer już widać różnicę. Zmienił się status na 403 Forbidden.

CORS - golang - 403 Forbidden

Teraz wystarczy ustawić minimalne wymagane nagłówki i problem zażegnany:

CORS - golang - 200 OK