Automatyczny Api Endpoint ?- adres.com/route/api/(UUID}

0

Nie wiem czy potrafię to jasno wyjaśnić co chce uzyskać. Bardzo możliwe że robię to z ** strony no ale może pomożecie.

Chce mieć jeden endpoint który po wysłaniu JSON-a będzie mu tworzył automatycznie ID.

Czyli przykładowo wrzucam:

{
"user": "marek",
"wiek": "20"
}

a końcowy json wygląda:

{
"user": "marek",
"wiek": "20"
"ID": "1"
}

gdzie: ID to może byc każda kolejna liczba porządkowa ale może też to być po prostu unikalny znak - czyli np korzystając z UUID.

I w takim sposób chce wrzucać kolejnych użytkowników:

{
"user": "janek",
"wiek": "34"
}

a finałowy json wygląda:
{
"user": "janek",
"wiek": "34",
"ID": "2"
}
//

I teraz tak, chce aby adres mojego JEDNEGO enpointa wygląda następująco : adres.com/route/api/
natomiast każdego usera mogę wyłapać dalej poprzez adres.com/route/api/ID (opcjonalnie)

Jak mam to zrobić ?

0
etato napisał(a):

Nie wiem czy potrafię to jasno wyjaśnić co chce uzyskać. Bardzo możliwe że robię to z ** strony no ale może pomożecie.

...

I teraz tak, chce aby adres mojego JEDNEGO enpointa wygląda następująco : adres.com/route/api/
natomiast każdego usera mogę wyłapać dalej poprzez adres.com/route/api/ID (opcjonalnie)

Jak mam to zrobić ?

Nie rozumiem tego zdania. Pytasz i implementację backendu? W jakim języku?
Przykłady są jasne, dlatego wyciąłem.

Co do szczegółów, zasadą rest jest budowa URL tak (z nazwą obiektu - a słowo route czy skrót API w gruncie rzeczy zbędny):
adres.com/route/api/users
lub
adres.com/route/users lub adres.com/api/users

I tu poczytaj: https://www.restapitutorial.com/lessons/httpmethods.html

0
AnyKtokolwiek napisał(a):
etato napisał(a):

Nie wiem czy potrafię to jasno wyjaśnić co chce uzyskać. Bardzo możliwe że robię to z ** strony no ale może pomożecie.

...

I teraz tak, chce aby adres mojego JEDNEGO enpointa wygląda następująco : adres.com/route/api/
natomiast każdego usera mogę wyłapać dalej poprzez adres.com/route/api/ID (opcjonalnie)

Jak mam to zrobić ?

Nie rozumiem tego zdania. Pytasz i implementację backendu? W jakim języku?
Przykłady są jasne, dlatego wyciąłem.

Co do szczegółów, zasadą rest jest budowa URL tak (z nazwą obiektu - a słowo route czy skrót API w gruncie rzeczy zbędny):
adres.com/route/api/users
lub
adres.com/route/users lub adres.com/api/users

I tu poczytaj: https://www.restapitutorial.com/lessons/httpmethods.html

prostą implementacje mam już zrobioną.
Czyli wysyłam dowolny json ale minus jest taki że muszę zawsze dać jakies ID do endpointa
A chce aby to ID samo się uzupełniało..\

sorry za nazewnictwo ale nie wiem jak to wszystko nazwać po polskiemu ..

język - jak dział wskazuje - js..

0

Pokaż kod który już napisałeś ew. podaj nazwę frameworka z którego korzystasz.

0

Czyli wysyłam dowolny json ale minus jest taki że muszę zawsze dać jakies ID do endpointa
A chce aby to ID samo się uzupełniało..\

zawsze możesz ustawić jakiś najprostszy autoincrement na polu z ID w bazie (dostaniesz IDki w stylu 1, 2, 3.... ew. 1001, 1011, 1021, albo walnąć jakiś UUID.randomUUID() po drodze i będziesz miał losowo generowane IDki jako UUID. w czym problem?

0
Markuz napisał(a):

Pokaż kod który już napisałeś ew. podaj nazwę frameworka z którego korzystasz.

To jest mój plik - Stwórz nowego użytkownika:

const Responses = require('../common/API_Responses');
const Dynamo = require('../common/Dynamo');

const table = process.env.table;

exports.handler = async event => {
    console.log('event', event);

    if (!event.pathParameters || !event.pathParameters.ID) {
        // failed without an ID
        return Responses._400({ message: 'missing the ID from the path' });
    }

    let ID = event.pathParameters.ID;
    const user = JSON.parse(event.body);
    user.ID = ID;

    const newUser = await Dynamo.write(typer, table).catch(err => {
        console.log('error in dynamo write', err);
        return null;
    });

    if (!newUser) {
        return Responses._400({ message: 'Failed to write typer!! by ID' });
    }

    return Responses._200({ newUser });
};

a to jest do dynamodb

const AWS = require('aws-sdk');

const DC = new AWS.DynamoDB.DocumentClient();

const Dynamo = {
    async get (ID, table){
        const params = {
            table,
            Key:
            {
                ID,
            },
        };
        
        const data = await DC.get(params).promise();
            
        if (!data || !data.Item) {
            throw Error(`we cant fetch ID which is ${ID} from ${table}`);
        }
        
        console.log(data);
        
        return data.Item;
    },
    
                            async write(data, table) {
                                if (!data.ID) {
                                    throw Error('no ID on the data');
                                }
                        
                                const params = {
                                    table,
                                    Item: data,
                                };
                        
                                const res = await DC.put(params).promise();
                        
                                if (!res) {
                                    throw Error(`There was an error inserting ID of ${data.ID} in table ${table}`);
                                }
                        
                                return data;
                            }
};


module.exports = Dynamo;

1

Ok. Masz taki fragment podczas tworzenia użytkownika:

    let ID = event.pathParameters.ID;
    const user = JSON.parse(event.body);
    user.ID = ID;

Ale Ty chcesz żeby ID tworzyło się automatycznie. Możesz skorzystać z np. https://www.npmjs.com/package/uuid czyli instalujesz paczkę i robisz:

import { v4 as uuidv4 } from 'uuid';
...
const user = JSON.parse(event.body);
user.ID = uuidv4();
0
Markuz napisał(a):

Ok. Masz taki fragment podczas tworzenia użytkownika:

    let ID = event.pathParameters.ID;
    const user = JSON.parse(event.body);
    user.ID = ID;

Ale Ty chcesz żeby ID tworzyło się automatycznie. Możesz skorzystać z np. https://www.npmjs.com/package/uuid czyli instalujesz paczkę i robisz:

import { v4 as uuidv4 } from 'uuid';
...
const user = JSON.parse(event.body);
user.ID = uuidv4();

**tak dokładnie dzięki za pomoc ! - chyba tak to należy zrobić **
I co najważniejsze chyba działa dobrze dzięki!

Problem w tym że nie do konca jeszcze to rozumiem.
Jak mogę to UUID ustawić aby za każdym razem dawało kolelną liczbę porządkową a nie losoway ciąg znaków?
Czyli np zaczynami od 1, później 2,3,4 itp ?

1

Nie możesz. UUID to po prostu unikalny ciąg znaków który może służyć jako ID.
Ty chcesz zrobić "auto increment id".

Problem w tym, że baza danych z której korzystasz tj. "AWS.DynamoDB" nie wspiera takiego rodzaju ID. Jak chcesz wiedzieć dlaczego możesz poczytać o np. "ID collisions in a distributed system".

Możesz kombinować wymyślając jakieś własne obejście na ID typu 1, 2, 3 (np. przed zapisaniem użytkownika wyszukiwać ostatnio dodanego użytkownika i dodawać do id 1, ale to trochę słabe rozwiązanie)
Zmienić bazę danych na inną (MySQL, PostgreSQL).
Zostawić UUID.

0
Markuz napisał(a):

Nie możesz. UUID to po prostu unikalny ciąg znaków który może służyć jako ID.
Ty chcesz zrobić "auto increment id".

Problem w tym, że baza danych z której korzystasz tj. "AWS.DynamoDB" nie wspiera takiego rodzaju ID. Jak chcesz wiedzieć dlaczego możesz poczytać o np. "ID collisions in a distributed system".

Możesz kombinować wymyślając jakieś własne obejście na ID typu 1, 2, 3 (np. przed zapisaniem użytkownika wyszukiwać ostatnio dodanego użytkownika i dodawać do id 1, ale to trochę słabe rozwiązanie)
Zmienić bazę danych na inną (MySQL, PostgreSQL).
Zostawić UUID.

ad1. Dlaczego 1,2,3 to słabe rozwiązanie?

ad2. Czy nowsze rozwiązanie jak MongoDB nadadzą się ?

ad3. Zostawiłbym UUID.
Tylko teraz problematyczne jest uzyskanie dostępu do danego użytkownika.

mam endpoint get-user/b974711c-757a-4208-85ff-26cabd6y4b00 ktory działa ale jest lekko problematyczny.
Na pewno wygodniejsza była by pojedyncza cyfra. No ale to tylko ID. Jak najsprawniej dodać opcje wyszukiwania może po parametrach ? Czyli np get-user/{gdzie name=Michał oraz Data Dodania=12.07-10-07} (zakładam że wówczas mam pewność jednego wyniku zamiast ID? Dobrze to chce zrobić tak w ogóle czy kompletnie okrężną drogą to rozumuje ??

2
etato napisał(a):

ad1. Dlaczego 1,2,3 to słabe rozwiązanie?

Bo mogą wystąpić kolizje. Mogą się pojawić dwa żądania utworzenia zasobu, zostaną obsłużone współbieżnie, oba stwierdzą że ostatni ID to 1234 więc utworzone zostaną dwa zasoby o ID 1235. Bęc, kolizja.

Jeśli spróbujesz zapobiec kolizjom np. blokując tabele (nawet nie próbuj!) to będzie jeszcze gorzej - bo może i nie będziesz miał kolizji, ale praktycznie sparaliżujesz sobie aplikację.

ad2. Czy nowsze rozwiązanie jak MongoDB nadadzą się ?

Nowsze / bardziej fancy rozwiązania nie uchronią Cię przed kiepskimi decyzjami.

https://www.mongodb.com/blog/post/generating-globally-unique-identifiers-for-use-with-mongodb

Sekcja "Use a single counter document to generate unique identifiers one at a time" mówi wprost:

The approach described in this section is generally not recommended due to the potential for the single counter document to become a bottleneck in the application.

ad3. Zostawiłbym UUID.
Tylko teraz problematyczne jest uzyskanie dostępu do danego użytkownika.

Nie powinno być problematyczne, tworząc zasób zwracasz jego ID lub np. nagłówek Location z odnośnikiem do zasobu (w którym jest ID).

Dopóki apka na froncie ma ID, nawet nie musisz go nikomu pokazywać i nikt go nie ogląda (chyba że w pasku z adresem), nie przepisuje.

Do wyszukiwania zasobu tworzysz jakiś endpoint do wyszukiwania po innych parametrach i po problemie.

GET https://moja-apka.com/users?username=franekkimono
0

@Markuz: @superdurszlak

dobra panowie wstrzymałem się z pisaniem ale poddałem się po wielu próbach (chałupniczych ale jednak..) . Co prawda idę z poradnikiem ale nie chce tylko bezmyślnie korzystać z gotowców i kopiować.

Tak więc mam kod który podałem. I teraz bez problemu mogę dostać się każdego użytkownika poprzez UUID czyli wpisuje adres.com/route/api/users/[IDktóreistniejewbazie]
czyli np:
{
"id" : "którepisałem"
"user": "janek",
"wiek" : "20"
}

no i działa. I teraz wiem że to zapewne podstawa ze wszystkich podstaw ale .. Jak mam wyświetlić wszystkie recordy które mam w bazie pod adresem **adres.com/route/api/users **

czyli

[ {
"id" : "którepisałem"
"user": "janek",
"wiek" : "20"
},
{
"id" : "555"
"user": "wacek",
"wiek" : "70"
},
{
"id" : "222"
"user": "euastachy",
"wiek" : "120"
},
]

0

Definiujesz go podobnie do tego, który zwraca pojedynczego usera na podstawie ID. Różnica jest taka, że endpoint nie będzie przyjmował żadnego parametru w ścieżce, pod spodem wyciągasz wszystkich zamiast jednego i zwracasz kolekcję (tablicę, listę, czy jak to tam zwał).

Potem pewnie będziesz chciał móc filtrować zasoby albo zrobić paging, więc możesz dodać jakiś parametr query np. adres.com/route/api/users?wiek=65, wyciągnąć przesłane parametry i obsłużyć żądanie z ich uwzględnieniem - zależnie od frameworka mogą być mapowane na argumenty metody obsługującej żądanie, mogą być do wyciągnięcia jako jakaś mapa z obiektu żądania albo jakoś inaczej, nie piszę w JS i prawdę mówiąc nie wiem jak to rozwiązuje powiedzmy NodeJS

1 użytkowników online, w tym zalogowanych: 0, gości: 1