Wyzwalacz i powiązania usługi Azure Web PubSub dla usługi Azure Functions

W tym dokumentacji wyjaśniono, jak obsługiwać zdarzenia Web PubSub w usłudze Azure Functions.

Web PubSub to usługa zarządzana przez platformę Azure, która ułatwia deweloperom łatwe tworzenie aplikacji internetowych z funkcjami w czasie rzeczywistym i wzorcem publikowania-subskrybowania.

Akcja Typ
Uruchamianie funkcji, gdy komunikaty pochodzą z usługi Powiązanie wyzwalacza
Wiązanie żądania z obiektem docelowym w obszarze Wyzwalacz HTTP na potrzeby negocjacji i żądań nadrzędnych Powiązanie wejściowe
Wywoływanie akcji wykonywania usługi Powiązanie wyjściowe

Dokumentacja interfejsu API | pakietu | źródłowego | — dokumentacja | produktu — przykłady

Dodawanie do aplikacji usługi Functions

Praca z wyzwalaczem i powiązaniami wymaga odwołania się do odpowiedniego pakietu. Pakiet NuGet jest używany dla bibliotek klas platformy .NET, podczas gdy pakiet rozszerzenia jest używany dla wszystkich innych typów aplikacji.

Język Dodaj według... Uwagi
C# Instalowanie pakietu NuGet w wersji wstępnej
Skrypt języka C#, JavaScript, Python, PowerShell Jawne instalowanie rozszerzeń, używanie pakietów rozszerzeń Rozszerzenie Azure Tools jest zalecane do użycia z programem Visual Studio Code.
Skrypt języka C# (tylko online w witrynie Azure Portal) Dodawanie powiązania Aby zaktualizować istniejące rozszerzenia powiązań bez konieczności ponownego publikowania aplikacji funkcji, zobacz Aktualizowanie rozszerzeń.

Najważniejsze pojęcia

Diagram showing the workflow of Azure Web PubSub service working with Function Apps.

(1)-(2) WebPubSubConnection powiązanie wejściowe za pomocą narzędzia HttpTrigger w celu wygenerowania połączenia klienta.

(3)-(4) WebPubSubTrigger powiązanie wyzwalacza lub WebPubSubContext powiązanie wejściowe za pomocą narzędzia HttpTrigger do obsługi żądania obsługi.

(5)-(6) WebPubSub powiązanie wyjściowe z usługą żądań wykonuje coś.

Powiązanie wyzwalacza

Użyj wyzwalacza funkcji do obsługi żądań z usługi Azure Web PubSub.

WebPubSubTrigger jest używany w przypadku konieczności obsługi żądań po stronie usługi. Wzorzec punktu końcowego wyzwalacza powinien być podobny do poniższego, który powinien być ustawiony po stronie usługi Web PubSub (portal: ustawienia —> procedura obsługi zdarzeń —> szablon adresu URL). We wzorcu punktu końcowego część code=<API_KEY> zapytania jest wymagana , gdy używasz aplikacji funkcji platformy Azure ze względów bezpieczeństwa . Klucz można znaleźć w witrynie Azure Portal. Znajdź zasób aplikacji funkcji i przejdź do pozycji Funkcje ->Klucze aplikacji ->Klucze systemowe ->webpubsub_extension po wdrożeniu aplikacji funkcji na platformie Azure. Jednak ten klucz nie jest potrzebny podczas pracy z funkcjami lokalnymi.

<Function_App_Url>/runtime/webhooks/webpubsub?code=<API_KEY>

Screenshot of get function system keys.

Przykład

[FunctionName("WebPubSubTrigger")]
public static void Run(
    [WebPubSubTrigger("<hub>", WebPubSubEventType.User, "message")] UserEventRequest request, ILogger log)
{
    log.LogInformation($"Request from: {request.ConnectionContext.UserId}");
    log.LogInformation($"Request message data: {request.Data}");
    log.LogInformation($"Request message dataType: {request.DataType}");
}

WebPubSubTrigger Powiązanie obsługuje również wartość zwracaną w scenariuszach synchronizacji, na przykład zdarzenia systemu Connect i użytkownika, gdy serwer może sprawdzać i odrzucać żądanie klienta lub wysyłać komunikaty bezpośrednio do obiektu wywołującego. Connectzdarzenia z uwzględnieniem ConnectEventResponseUserEventResponse zdarzeń i EventErrorResponse, oraz zdarzeń użytkownika i EventErrorResponse, typy rest nie pasujące do bieżącego scenariusza są ignorowane. A jeśli EventErrorResponse zostanie zwrócona, usługa pominie połączenie klienta.

[FunctionName("WebPubSubTriggerReturnValueFunction")]
public static UserEventResponse Run(
    [WebPubSubTrigger("hub", WebPubSubEventType.User, "message")] UserEventRequest request)
{
    return request.CreateResponse(BinaryData.FromString("ack"), WebPubSubDataType.Text);
}

Atrybuty i adnotacje

W bibliotekach klas języka C# użyj atrybutu WebPubSubTrigger .

WebPubSubTrigger Oto atrybut w podpisie metody:

[FunctionName("WebPubSubTrigger")]
public static void Run([WebPubSubTrigger("<hub>", <WebPubSubEventType>, "<event-name>")] 
    WebPubSubConnectionContext context, ILogger log)
{
    ...
}

Pełny przykład można znaleźć w przykładzie języka C#.

Konfigurowanie

W poniższej tabeli opisano właściwości konfiguracji powiązania ustawione w pliku function.json .

function.json, właściwość Właściwość atrybutu opis
type nie dotyczy Wymagane — musi być ustawiona na webPubSubTriggerwartość .
direction nie dotyczy Wymagane — musi być ustawiona na inwartość .
name nie dotyczy Required — nazwa zmiennej używana w kodzie funkcji dla parametru, który odbiera dane zdarzenia.
Koncentratora Piasta Wymagane — wartość musi być ustawiona na nazwę centrum Web PubSub, aby funkcja została wyzwolona. Obsługujemy ustawianie wartości w atrybucie jako wyższy priorytet lub można ją ustawić w ustawieniach aplikacji jako wartość globalną.
eventType WebPubSubEventType Wymagane — wartość musi być ustawiona jako typ zdarzenia komunikatów, które mają być wyzwalane przez funkcję. Wartość powinna mieć wartość user lub system.
Eventname EventName Wymagane — wartość musi być ustawiona jako zdarzenie komunikatów, które mają być wyzwalane przez funkcję.
W przypadku system typu zdarzenia nazwa zdarzenia powinna mieć connectwartość , connected, disconnected.
W przypadku podprotocol zdefiniowanych przez użytkownika nazwa zdarzenia to message.
W przypadku podprotocol json.webpubsub.azure.v1.obsługiwanego przez system nazwa zdarzenia to nazwa zdarzenia zdefiniowanego przez użytkownika.
Połączenia Connection Opcjonalnie — nazwa ustawień aplikacji lub kolekcji ustawień, która określa nadrzędną usługę Azure Web PubSub. Wartość jest używana do walidacji podpisu. A wartość jest automatycznie rozpoznawana przy użyciu ustawień aplikacji "WebPubSub Połączenie ionString" domyślnie. Oznacza to null , że weryfikacja nie jest potrzebna i zawsze kończy się powodzeniem.

Zwyczaje

W języku C# WebPubSubEventRequest jest typem rozpoznany parametr powiązania, parametry rest są powiązane przez nazwę parametru. Zapoznaj się z tabelą poniżej dostępnych parametrów i typów.

W słabo wpisanym języku, na przykład JavaScript, name w function.json jest używany do powiązania obiektu wyzwalacza dotyczącego poniższej tabeli mapowania. I uwzględnianie dataType w function.json celu odpowiedniego przekonwertowania komunikatu, gdy name jest ustawiony data jako obiekt powiązania dla danych wejściowych wyzwalacza. Wszystkie parametry można odczytać i context.bindingData.<BindingName> przekonwertować JObject .

Nazwa powiązania Typ powiązania opis Właściwości
żądanie WebPubSubEventRequest Opisuje żądanie nadrzędne Właściwość różni się w zależności od różnych typów zdarzeń, w tym klas pochodnych ConnectEventRequest, ConnectedEventRequestUserEventRequest iDisconnectedEventRequest
Connectioncontext WebPubSubConnectionContext Typowe informacje o żądaniu EventType, EventName, Hub, Połączenie ionId, UserId, Headers, Origin, Signature, States
dane BinaryData,string,Stream,byte[] Żądanie danych komunikatów od klienta w zdarzeniu użytkownika message -
Datatype WebPubSubDataType Request message dataType, który obsługuje binary, , textjson -
oświadczenia IDictionary<string, string[]> Oświadczenia użytkownika w żądaniu systemowym connect -
zapytanie IDictionary<string, string[]> Zapytanie użytkownika w żądaniu systemowym connect -
subprotocols IList<string> Dostępne podprotocols w żądaniu systemowym connect -
Clientcertificates IList<ClientCertificate> Lista odcisków palca certyfikatu od klientów w żądaniu systemowym connect -
reason string Przyczyna żądania systemowego disconnected -

Ważne

W języku C#, wiele typów obsługiwanych parametrów MUSI być umieszczonych w pierwszym, tj. request lub data innym niż domyślny BinaryData typ, aby powiązanie funkcji było poprawne.

Zwracana odpowiedź

WebPubSubTrigger szanuje, że klient zwrócił odpowiedź na zdarzenia synchroniczne zdarzenia connect i zdarzenia użytkownika. Tylko dopasowana odpowiedź jest wysyłana z powrotem do usługi, w przeciwnym razie jest ignorowana. WebPubSubTrigger Poza tym obiekt return obsługuje użytkowników w celu SetState() zarządzania metadanymi połączenia i ClearStates() zarządzania nimi. Rozszerzenie scala wyniki z wartości zwracanej z oryginalnymi z żądania WebPubSubConnectionContext.States. Wartość w istniejącym kluczu jest zastępowana, a wartość w nowym kluczu jest dodawana.

Zwracany typ opis Właściwości
ConnectEventResponse Odpowiedź na connect zdarzenie Grupy, role, UserId, Subprotocol
UserEventResponse Odpowiedź na zdarzenie użytkownika DataType, Data
EventErrorResponse Odpowiedź na błąd zdarzenia synchronizacji Kod, ErrorMessage
*WebPubSubEventResponse Podstawowy typ odpowiedzi obsługiwanych używanych w przypadku niepewnych przypadków powrotu -

Powiązanie wejściowe

Nasze rozszerzenie udostępnia dwa powiązania wejściowe przeznaczone dla różnych potrzeb.

  • WebPubSubConnection

    Aby umożliwić klientowi nawiązanie połączenia z usługą Azure Web PubSub Service, musi on znać adres URL punktu końcowego usługi i prawidłowy token dostępu. Powiązanie WebPubSubConnection wejściowe generuje wymagane informacje, więc klient nie musi obsługiwać samego generowania tokenu. Ponieważ token jest ograniczony czasowo i może służyć do uwierzytelniania określonego użytkownika w połączeniu, nie buforuj tokenu ani nie udostępniaj go między klientami. Wyzwalacz HTTP pracujący z tym powiązaniem wejściowym może służyć klientom do pobierania informacji o połączeniu.

  • WebPubSubContext

    W przypadku korzystania z usługi Static Web Apps HttpTrigger jest jedynym obsługiwanym wyzwalaczem i w scenariuszu Web PubSub udostępniamy WebPubSubContext powiązanie wejściowe, które pomaga użytkownikom deserializować nadrzędne żądanie HTTP po stronie usługi w ramach protokołów Web PubSub. Dzięki temu klienci mogą uzyskać podobne wyniki w porównaniu do WebPubSubTrigger łatwego obsługi w funkcjach. Zobacz przykłady poniżej. W przypadku użycia z HttpTriggerprogramem klient musi odpowiednio skonfigurować adres URL uwidoczniony przez narzędzie HttpTrigger w procedurze obsługi zdarzeń.

Przykład- WebPubSubConnection

W poniższym przykładzie pokazano funkcję języka C#, która uzyskuje informacje o połączeniu z usługą Web PubSub przy użyciu powiązania wejściowego i zwraca ją za pośrednictwem protokołu HTTP. W poniższym przykładzie element UserId jest przekazywany za pośrednictwem części zapytania żądania klienta, takiej jak ?userid={User-A}.

[FunctionName("WebPubSubConnectionInputBinding")]
public static WebPubSubConnection Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req,
    [WebPubSubConnection(Hub = "<hub>", UserId = "{query.userid}")] WebPubSubConnection connection)
{
    return connection;
}

Uwierzytelnione tokeny

Jeśli funkcja jest wyzwalana przez uwierzytelnionego klienta, możesz dodać oświadczenie identyfikatora użytkownika do wygenerowanego tokenu. Uwierzytelnianie można łatwo dodać do aplikacji funkcji przy użyciu uwierzytelniania usługi App Service.

Uwierzytelnianie usługi App Service ustawia nagłówki HTTP o nazwie x-ms-client-principal-id i x-ms-client-principal-name zawierają odpowiednio identyfikator jednostki klienta i nazwę uwierzytelnionego użytkownika.

Właściwość UserId powiązania można ustawić na wartość z nagłówka przy użyciu wyrażenia powiązania: {headers.x-ms-client-principal-id} lub {headers.x-ms-client-principal-name}.

[FunctionName("WebPubSubConnectionInputBinding")]
public static WebPubSubConnection Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req,
    [WebPubSubConnection(Hub = "<hub>", UserId = "{headers.x-ms-client-principal-name}")] WebPubSubConnection connection)
{
    return connection;
}

Uwaga

Ograniczone do typów parametrów powiązania nie obsługują sposobu przekazywania listy ani tablicy, WebPubSubConnection ale nie jest w pełni obsługiwany ze wszystkimi parametrami zestawu SDK serwera, zwłaszcza roles, a także zawiera groups i expiresAfter. W przypadku, gdy klient musi dodać role lub opóźnić utworzenie tokenu dostępu w funkcji, zaleca się pracę z zestawem SDK serwera dla języka C#.

[FunctionName("WebPubSubConnectionCustomRoles")]
public static async Task<Uri> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req)
{
    var serviceClient = new WebPubSubServiceClient(new Uri(endpoint), "<hub>", "<web-pubsub-connection-string>");
    var userId = req.Query["userid"].FirstOrDefault();
    // your method to get custom roles.
    var roles = GetRoles(userId);
    return await serviceClient.GetClientAccessUriAsync(TimeSpan.FromMinutes(5), userId, roles);
}

Przykład- WebPubSubContext

W poniższym przykładzie przedstawiono funkcję języka C#, która uzyskuje informacje o żądaniu nadrzędnym web PubSub przy użyciu powiązania wejściowego w obszarze connect typu zdarzenia i zwraca je za pośrednictwem protokołu HTTP.

[FunctionName("WebPubSubContextInputBinding")]
public static object Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req,
    [WebPubSubContext] WebPubSubContext wpsContext)
{
    // in the case request is a preflight or invalid, directly return prebuild response by extension.
    if (wpsContext.IsPreflight || wpsContext.HasError)
    {
        return wpsContext.Response;
    }
    var request = wpsContext.Request as ConnectEventRequest;
    var response = new ConnectEventResponse
    {
        UserId = wpsContext.Request.ConnectionContext.UserId
    };
    return response;
}

Konfigurowanie

WebPubSub Połączenie ion

W poniższej tabeli opisano właściwości konfiguracji powiązania ustawione w pliku function.json i atrybucie WebPubSubConnection .

function.json, właściwość Właściwość atrybutu opis
type nie dotyczy Musi być ustawiona na webPubSubConnection
direction nie dotyczy Musi być ustawiona na in
name nie dotyczy Nazwa zmiennej używana w kodzie funkcji dla obiektu powiązania połączenia wejściowego.
Koncentratora Piasta Wymagane — wartość musi być ustawiona na nazwę centrum Web PubSub, aby funkcja została wyzwolona. Obsługujemy ustawianie wartości w atrybucie jako wyższy priorytet lub można ją ustawić w ustawieniach aplikacji jako wartość globalną.
Userid Identyfikator użytkownika Opcjonalnie — wartość oświadczenia identyfikatora użytkownika, która ma zostać ustawiona w tokenie klucza dostępu.
Połączenia Connection Wymagane — nazwa ustawienia aplikacji zawierającego usługę Web PubSub Service parametry połączenia (domyślnie to "WebPubSub Połączenie ionString").

WebPubSubContext

W poniższej tabeli opisano właściwości konfiguracji powiązania ustawione w pliku functions.json i atrybut.WebPubSubContext

function.json, właściwość Właściwość atrybutu opis
type nie dotyczy Musi być ustawiona wartość webPubSubContext.
direction nie dotyczy Musi być ustawiona wartość in.
name nie dotyczy Nazwa zmiennej używana w kodzie funkcji dla wejściowego żądania Web PubSub.
Połączenia Connection Opcjonalnie — nazwa ustawień aplikacji lub kolekcji ustawień, która określa nadrzędną usługę Azure Web PubSub. Wartość jest używana na potrzeby ochrony przed nadużyciami i weryfikacji podpisu. Wartość jest automatycznie rozpoznawana za pomocą polecenia "WebPubSub Połączenie ionString" domyślnie. Oznacza to null , że weryfikacja nie jest potrzebna i zawsze kończy się powodzeniem.

Sposób użycia

WebPubSub Połączenie ion

WebPubSubConnection zawiera poniższe właściwości.

Nazwa powiązania Typ powiązania opis
Baseuri Identyfikator URI Identyfikator URI połączenia klienta web PubSub.
Identyfikator URI Identyfikator URI Bezwzględny identyfikator URI połączenia Web PubSub zawiera AccessToken wygenerowaną bazę na żądanie.
AccessToken string AccessToken Generowane na podstawie identyfikatora UserId żądania i informacji o usłudze.

WebPubSubContext

WebPubSubContext zawiera poniższe właściwości.

Nazwa powiązania Typ powiązania opis Właściwości
żądanie WebPubSubEventRequest Żądanie od klienta, zobacz poniższą tabelę, aby uzyskać szczegółowe informacje. WebPubSubConnectionContext z nagłówka żądania i inne właściwości deserializowane z treści żądania opisują żądanie, na przykład Reason dla DisconnectedEventRequest.
odpowiedź HttpResponseMessage Rozszerzenie tworzy odpowiedź głównie w przypadku AbuseProtection przypadków błędów i . -
komunikat o błędzie string Opisz szczegóły błędu podczas przetwarzania nadrzędnego żądania. -
hasError bool Flaga wskazująca, czy jest to prawidłowe żądanie nadrzędne Web PubSub. -
isPreflight bool Flaga wskazująca, czy jest to żądanie wstępne .AbuseProtection -

W przypadku WebPubSubEventRequestprogramu jest deserializowany do różnych klas, które zawierają różne informacje o scenariuszu żądania. W przypadku PreflightRequest nieprawidłowych przypadków użytkownik może sprawdzić flagi IsPreflight i HasError wiedzieć. Zaleca się bezpośrednie zwrócenie odpowiedzi kompilacji WebPubSubContext.Response systemu lub klient może rejestrować błędy na żądanie. W różnych scenariuszach klient może odczytać właściwości żądania, jak pokazano poniżej.

Klasa pochodna opis Właściwości
PreflightRequest Używany w AbuseProtection przypadku, gdy IsPreflight ma wartość true -
ConnectEventRequest Używane w typie zdarzeń systemowych Connect Oświadczenia, zapytanie, podprotocols, ClientCertificates
ConnectedEventRequest Używane w typie zdarzeń systemowych Connected -
UserEventRequest Używany w typie zdarzenia użytkownika Dane, Typ danych
DisconnectedEventRequest Używane w typie zdarzeń systemowych Disconnected Przyczyna

Uwaga

WebPubSubContext Chociaż jest to powiązanie wejściowe zapewnia podobny sposób deserializacji żądania w HttpTrigger porównaniu z WebPubSubTrigger, istnieją ograniczenia, tj. stan połączenia po scaleniu nie jest obsługiwany. Odpowiedź zwrotna jest nadal przestrzegana przez usługę, ale użytkownicy muszą sami utworzyć odpowiedź. Jeśli użytkownicy muszą ustawić odpowiedź na zdarzenie, należy zwrócić HttpResponseMessage komunikaty zawierające ConnectEventResponse lub dla zdarzenia użytkownika jako treść odpowiedzi i umieścić stan połączenia z kluczem ce-connectionstate w nagłówku odpowiedzi.

Powiązanie wyjściowe

Użyj powiązania wyjściowego Web PubSub, aby wywołać usługę Azure Web PubSub, aby coś zrobić. Możesz rozgłasić komunikat do:

  • Wszyscy połączeni klienci
  • Połączenie klientów uwierzytelnionych w określonym użytkowniku
  • Połączenie klientów dołączonych do określonej grupy
  • Określone połączenie klienta

Powiązanie wyjściowe umożliwia również zarządzanie klientami i grupami, a także udzielanie/odwoływanie uprawnień przeznaczonych dla określonego identyfikatora connectionId z grupą.

  • Dodawanie połączenia do grupy
  • Dodawanie użytkownika do grupy
  • Usuwanie połączenia z grupy
  • Usuwanie użytkownika z grupy
  • Usuwanie użytkownika ze wszystkich grup
  • Zamknij wszystkie połączenia klienckie
  • Zamykanie określonego połączenia klienta
  • Zamykanie połączeń w grupie
  • Udzielanie uprawnień do połączenia
  • Odwoływanie uprawnień do połączenia

Aby uzyskać informacje na temat konfiguracji i konfiguracji, zobacz omówienie.

Przykład

[FunctionName("WebPubSubOutputBinding")]
public static async Task RunAsync(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req,
    [WebPubSub(Hub = "<hub>")] IAsyncCollector<WebPubSubAction> actions)
{
    await actions.AddAsync(WebPubSubAction.CreateSendToAllAction("Hello Web PubSub!", WebPubSubDataType.Text));
}

WebPubSubAction

WebPubSubAction jest podstawowym abstrakcyjnym typem powiązań wyjściowych. Typy pochodne reprezentują serwer akcji, który chce wywołać usługę.

W języku C# udostępniamy kilka metod statycznych, WebPubSubAction które ułatwiają odnajdywanie dostępnych akcji. Na przykład użytkownik może utworzyć obiekt SendToAllAction za pomocą wywołania WebPubSubAction.CreateSendToAllAction().

Klasa pochodna Właściwości
SendToAllAction Dane, Typ danych, Wykluczone
SendToGroupAction Grupa, Dane, Typ danych, Wykluczone
SendToUserAction UserId, Data, DataType
SendToConnectionAction Połączenie ionId, Data, DataType
AddUserToGroupAction UserId, Group
RemoveUserFromGroupAction UserId, Group
RemoveUserFromAllGroupsAction Identyfikator użytkownika
AddConnectionToGroupAction Połączenie ionId, Grupa
RemoveConnectionFromGroupAction Połączenie ionId, Grupa
CloseAllConnectionsAction Wykluczone, przyczyna
CloseClientConnectionAction Połączenie ionId, przyczyna
CloseGroupConnectionsAction Grupa, Wykluczone, Przyczyna
GrantPermissionAction Połączenie ionId, Permission, TargetName
RevokePermissionAction Połączenie ionId, Permission, TargetName

Konfigurowanie

WebPubSub

W poniższej tabeli opisano właściwości konfiguracji powiązania ustawione w pliku function.json i atrybucie WebPubSub .

function.json, właściwość Właściwość atrybutu opis
type nie dotyczy Musi być ustawiona na webPubSub
direction nie dotyczy Musi być ustawiona na out
name nie dotyczy Nazwa zmiennej używana w kodzie funkcji dla obiektu powiązania wyjściowego.
Koncentratora Piasta Wartość musi być ustawiona na nazwę centrum Web PubSub, aby funkcja została wyzwolona. Obsługujemy ustawianie wartości w atrybucie jako wyższy priorytet lub można ją ustawić w ustawieniach aplikacji jako wartość globalną.
Połączenia Connection Nazwa ustawienia aplikacji zawierającego parametry połączenia Web PubSub Service (domyślnie to "WebPubSub Połączenie ionString").

Rozwiązywanie problemów

Konfigurowanie rejestrowania konsoli

Możesz również łatwo włączyć rejestrowanie konsoli, jeśli chcesz dokładniej zapoznać się z żądaniami, które podejmujesz względem usługi.

Następne kroki

Użyj tych zasobów, aby rozpocząć tworzenie własnej aplikacji: