REST API - Pytania Rekrutacyjne dla Backend Developer [2026]

Sławomir Plamowski 14 min czytania
api-design backend http java nodejs pytania-rekrutacyjne rest-api spring

REST API to standard komunikacji w nowoczesnych aplikacjach webowych i mobilnych. Na rozmowie rekrutacyjnej backend developer musi wykazać się znajomością nie tylko implementacji, ale też zasad projektowania dobrych API. Ten przewodnik zawiera 50+ pytań rekrutacyjnych z odpowiedziami - od podstaw HTTP po zaawansowane tematy jak wersjonowanie, bezpieczeństwo i optymalizacja.

Podstawy REST

Co to jest REST i jakie są jego główne zasady?

Odpowiedź w 30 sekund:

REST (Representational State Transfer) to styl architektoniczny oparty na 6 zasadach:

  1. Client-Server - separacja klienta od serwera
  2. Stateless - brak stanu sesji na serwerze
  3. Cacheable - odpowiedzi mogą być cache'owane
  4. Uniform Interface - standardowy interfejs
  5. Layered System - warstwy pośrednie
  6. Code on Demand - opcjonalny kod wykonywalny

Odpowiedź w 2 minuty:

REST opiera się na komunikacji klient-serwer za pomocą standardowych metod HTTP i zwracaniu danych w uniwersalnym formacie.

Client → Request (GET /users/1) → Server
       ← Response (JSON) + Status Code ←

Stateless - najważniejsza zasada:

// ❌ Stateful - serwer pamięta stan
session.setAttribute("user", user);

// ✅ Stateless - każdy request zawiera pełny kontekst
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Uniform Interface - 4 ograniczenia:

  1. Identyfikacja zasobów (URI)
  2. Manipulacja przez reprezentacje (JSON/XML)
  3. Self-descriptive messages (Content-Type, Accept)
  4. HATEOAS (hypermedia links)

Korzyści REST:

  • Skalowalność (stateless = łatwy load balancing)
  • Prostota (HTTP jest znany)
  • Niezależność (klient i serwer mogą ewoluować osobno)

Czym różni się REST od RESTful?

Odpowiedź w 30 sekund:

  • REST - styl architektoniczny, zbiór zasad
  • RESTful - API które implementuje te zasady

W praktyce większość API to "REST-ish" - implementuje część zasad (HTTP methods, JSON) ale nie wszystkie (np. pomija HATEOAS).

Odpowiedź w 2 minuty:

Stopień "restfulness" API można określić za pomocą modelu dojrzałości Richardsona, który klasyfikuje implementacje na cztery poziomy.

Poziomy dojrzałości REST (Richardson Maturity Model):

Level Opis Przykład
0 HTTP jako transport POST /api z XML
1 Zasoby GET /users, GET /orders
2 HTTP verbs GET, POST, PUT, DELETE
3 HATEOAS Linki w odpowiedziach
// Level 2 (typowe "REST" API)
GET /users/1
{
  "id": 1,
  "name": "John"
}

// Level 3 (RESTful z HATEOAS)
GET /users/1
{
  "id": 1,
  "name": "John",
  "_links": {
    "self": { "href": "/users/1" },
    "orders": { "href": "/users/1/orders" },
    "update": { "href": "/users/1", "method": "PUT" }
  }
}

Większość produkcyjnych API to Level 2. Level 3 (HATEOAS) jest rzadko w pełni implementowany.


HTTP Methods

Jakie metody HTTP używamy w REST i do czego?

Odpowiedź w 30 sekund:

Method Operacja Idempotentne Safe
GET Read Tak Tak
POST Create Nie Nie
PUT Replace Tak Nie
PATCH Update Nie* Nie
DELETE Delete Tak Nie

Odpowiedź w 2 minuty:

Każda metoda HTTP ma określony cel i właściwości, które determinują jej zachowanie w kontekście idempotentności i bezpieczeństwa.

# GET - pobierz zasób
GET /users/1 HTTP/1.1

# POST - utwórz nowy zasób
POST /users HTTP/1.1
Content-Type: application/json
{"name": "John", "email": "john@example.com"}

# PUT - zastąp cały zasób
PUT /users/1 HTTP/1.1
Content-Type: application/json
{"name": "John Updated", "email": "john@example.com", "age": 30}

# PATCH - częściowa aktualizacja
PATCH /users/1 HTTP/1.1
Content-Type: application/json
{"email": "newemail@example.com"}

# DELETE - usuń zasób
DELETE /users/1 HTTP/1.1

Idempotentność:

GET /users/1    → wynik zawsze ten sam
PUT /users/1    → wielokrotne wywołanie = ten sam efekt
DELETE /users/1 → 1x delete = usunięte, 2x delete = nadal usunięte
POST /users     → każde wywołanie tworzy nowy zasób!

Safe methods (GET, HEAD, OPTIONS) nie modyfikują stanu - mogą być cache'owane, prefetchowane.


Czym różni się PUT od PATCH?

Odpowiedź w 30 sekund:

  • PUT - zastępuje cały zasób (wszystkie pola wymagane)
  • PATCH - aktualizuje tylko podane pola

PUT jest idempotentne, PATCH może nie być (zależy od implementacji).

Odpowiedź w 2 minuty:

Różnica między PUT a PATCH jest fundamentalna - PUT wymaga przesłania pełnej reprezentacji zasobu, podczas gdy PATCH aktualizuje tylko wybrane pola.

// Obecny zasób
{
  "id": 1,
  "name": "John",
  "email": "john@example.com",
  "age": 25
}

// PUT /users/1 - ZASTĘPUJE cały zasób
{
  "name": "John Updated"
}
// Wynik: {id: 1, name: "John Updated", email: null, age: null}
// Brakujące pola → null/default!

// PATCH /users/1 - aktualizuje TYLKO podane pola
{
  "name": "John Updated"
}
// Wynik: {id: 1, name: "John Updated", email: "john@example.com", age: 25}

Spring implementation:

// PUT - wymaga pełnego obiektu
@PutMapping("/{id}")
public User updateUser(@PathVariable Long id, @RequestBody User user) {
    user.setId(id);
    return userRepository.save(user);  // nadpisuje wszystko
}

// PATCH - częściowa aktualizacja
@PatchMapping("/{id}")
public User patchUser(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
    User user = userRepository.findById(id).orElseThrow();
    updates.forEach((key, value) -> {
        Field field = ReflectionUtils.findField(User.class, key);
        field.setAccessible(true);
        ReflectionUtils.setField(field, user, value);
    });
    return userRepository.save(user);
}

Kiedy używać POST a kiedy PUT?

Odpowiedź w 30 sekund:

  • POST - tworzenie zasobu gdy serwer generuje ID
  • PUT - tworzenie/update gdy klient zna ID

POST tworzy pod różnymi URI, PUT zawsze pod tym samym.

Odpowiedź w 2 minuty:

Wybór między POST a PUT zależy od tego, kto odpowiada za identyfikator zasobu - klient czy serwer.

# POST - serwer decyduje o ID
POST /users HTTP/1.1
{"name": "John"}

201 Created
Location: /users/42
{"id": 42, "name": "John"}

# PUT - klient podaje ID (upsert)
PUT /users/42 HTTP/1.1
{"id": 42, "name": "John"}

201 Created  # jeśli nie istniał
# lub
200 OK       # jeśli istniał i został zaktualizowany

Use cases:

Scenariusz Method
Nowy user, ID generowane POST /users
User z określonym ID PUT /users/{id}
Upload file z nazwą PUT /files/report.pdf
Action na zasobie POST /orders/1/cancel
Partial update PATCH /users/1
// Spring - POST zwraca 201 + Location header
@PostMapping
public ResponseEntity<User> createUser(@RequestBody User user) {
    User saved = userRepository.save(user);
    URI location = ServletUriComponentsBuilder
        .fromCurrentRequest()
        .path("/{id}")
        .buildAndExpand(saved.getId())
        .toUri();
    return ResponseEntity.created(location).body(saved);
}

HTTP Status Codes

Jakie kody HTTP status powinno zwracać REST API?

Odpowiedź w 30 sekund:

2xx - sukces:

  • 200 OK - ogólny sukces
  • 201 Created - zasób utworzony
  • 204 No Content - sukces bez body

4xx - błąd klienta:

  • 400 Bad Request - nieprawidłowe dane
  • 401 Unauthorized - brak autoryzacji
  • 403 Forbidden - brak uprawnień
  • 404 Not Found - zasób nie istnieje

5xx - błąd serwera:

  • 500 Internal Server Error

Odpowiedź w 2 minuty:

Poprawne używanie kodów HTTP status pomaga klientom API zrozumieć wynik operacji i odpowiednio zareagować na błędy.

# 200 OK - GET, PUT, PATCH sukces
GET /users/1 → 200 + body

# 201 Created - POST sukces
POST /users → 201 + Location header + body

# 204 No Content - DELETE sukces (lub PUT bez zwracania body)
DELETE /users/1 → 204

# 400 Bad Request - złe dane wejściowe
POST /users {"email": "invalid"} → 400

# 401 Unauthorized - brak lub nieprawidłowy token
GET /users (no token) → 401

# 403 Forbidden - token OK, ale brak uprawnień
DELETE /admin/users/1 (as regular user) → 403

# 404 Not Found - zasób nie istnieje
GET /users/9999 → 404

# 409 Conflict - konflikt (np. duplicate email)
POST /users {"email": "existing@email.com"} → 409

# 422 Unprocessable Entity - walidacja biznesowa
POST /orders {"quantity": -5} → 422

# 429 Too Many Requests - rate limiting
GET /api/... → 429 + Retry-After header

Spring - globalna obsługa błędów:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleNotFound(EntityNotFoundException e) {
        return ResponseEntity.status(404)
            .body(new ErrorResponse("NOT_FOUND", e.getMessage()));
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidation(MethodArgumentNotValidException e) {
        String message = e.getBindingResult().getFieldErrors().stream()
            .map(error -> error.getField() + ": " + error.getDefaultMessage())
            .collect(Collectors.joining(", "));
        return ResponseEntity.badRequest()
            .body(new ErrorResponse("VALIDATION_ERROR", message));
    }
}

Czym różni się 401 od 403?

Odpowiedź w 30 sekund:

  • 401 Unauthorized - nie wiem kim jesteś (brak/nieprawidłowy token)
  • 403 Forbidden - wiem kim jesteś, ale nie masz uprawnień

401 = "Zaloguj się", 403 = "Nie masz dostępu"

Odpowiedź w 2 minuty:

Te dwa kody błędów są często mylone, ale mają zupełnie różne znaczenie w kontekście bezpieczeństwa API.

# 401 Unauthorized - brak tokenu
GET /users
Authorization: (brak)
→ 401 Unauthorized
WWW-Authenticate: Bearer

# 401 Unauthorized - nieprawidłowy/wygasły token
GET /users
Authorization: Bearer expired-token
→ 401 Unauthorized

# 403 Forbidden - token OK, user nie jest adminem
DELETE /admin/users/1
Authorization: Bearer valid-user-token
→ 403 Forbidden

Spring Security:

@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/public/**").permitAll()
                .requestMatchers("/admin/**").hasRole("ADMIN")  // 403 jeśli nie admin
                .anyRequest().authenticated()  // 401 jeśli niezalogowany
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt())
            .build();
    }
}

API Design

Jak projektować URL-e w REST API?

Odpowiedź w 30 sekund:

  1. Rzeczowniki (nie czasowniki) - /users nie /getUsers
  2. Liczba mnoga - /users nie /user
  3. Hierarchia zasobów - /users/1/orders
  4. Kebab-case - /user-profiles nie /userProfiles
  5. Filtry w query params - /users?status=active

Odpowiedź w 2 minuty:

Dobrze zaprojektowane URL-e są intuicyjne, spójne i odzwierciedlają hierarchię zasobów w systemie.

# ✅ DOBRZE
GET    /users              # lista użytkowników
GET    /users/1            # konkretny użytkownik
POST   /users              # utwórz użytkownika
PUT    /users/1            # aktualizuj użytkownika
DELETE /users/1            # usuń użytkownika
GET    /users/1/orders     # zamówienia użytkownika
GET    /users/1/orders/5   # konkretne zamówienie użytkownika

# ❌ ŹLE
GET    /getUsers
GET    /user/1
POST   /createUser
GET    /getUserOrders/1
DELETE /deleteUser/1

# Akcje jako sub-zasoby lub POST
POST   /orders/1/cancel     # akcja na zasobie
POST   /users/1/activate    # akcja na zasobie

# Query params dla filtrowania, sortowania, paginacji
GET /users?status=active&sort=name&page=1&size=20
GET /products?category=electronics&minPrice=100&maxPrice=500

Zagnieżdżone zasoby:

# Płytkie zagnieżdżenie (zalecane)
GET /users/1/orders

# Głębokie zagnieżdżenie (unikaj)
GET /users/1/orders/5/items/3/reviews  # za głęboko!

# Lepiej - bezpośredni dostęp gdy zasób ma globalne ID
GET /orders/5
GET /order-items/3

Jak obsługiwać paginację w REST API?

Odpowiedź w 30 sekund:

Query params: ?page=1&size=20 lub ?offset=0&limit=20 Odpowiedź zawiera metadata: total, hasNext, links.

Odpowiedź w 2 minuty:

Efektywna paginacja wymaga nie tylko podziału danych na strony, ale także dostarczenia metadanych ułatwiających nawigację.

GET /users?page=0&size=20&sort=name,asc

HTTP/1.1 200 OK
{
  "content": [
    {"id": 1, "name": "Alice"},
    {"id": 2, "name": "Bob"}
  ],
  "page": {
    "number": 0,
    "size": 20,
    "totalElements": 150,
    "totalPages": 8
  },
  "_links": {
    "self": "/users?page=0&size=20",
    "next": "/users?page=1&size=20",
    "last": "/users?page=7&size=20"
  }
}

Spring Data:

@GetMapping
public Page<User> getUsers(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "20") int size,
    @RequestParam(defaultValue = "id") String sortBy
) {
    Pageable pageable = PageRequest.of(page, size, Sort.by(sortBy));
    return userRepository.findAll(pageable);
}

// Spring HATEOAS
@GetMapping
public PagedModel<EntityModel<User>> getUsers(Pageable pageable) {
    Page<User> users = userRepository.findAll(pageable);
    return pagedResourcesAssembler.toModel(users);
}

Cursor-based pagination (dla dużych zbiorów):

GET /events?after=cursor123&limit=20

{
  "data": [...],
  "cursors": {
    "before": "cursor122",
    "after": "cursor143"
  },
  "hasMore": true
}

Cursor jest lepszy gdy dane się zmieniają (unikasz duplicate/skip).


Jak wersjonować REST API?

Odpowiedź w 30 sekund:

3 podejścia:

  1. URL path - /api/v1/users (najpopularniejsze)
  2. Query param - /api/users?version=1
  3. Header - Accept: application/vnd.api.v1+json

Odpowiedź w 2 minuty:

1. URL versioning (zalecane):

GET /api/v1/users
GET /api/v2/users
@RestController
@RequestMapping("/api/v1/users")
public class UserControllerV1 { }

@RestController
@RequestMapping("/api/v2/users")
public class UserControllerV2 { }

Zalety: jasne, łatwe w dokumentacji, testowaniu Wady: zmienia URI zasobu

2. Header versioning:

GET /api/users
Accept: application/vnd.myapi.v1+json
@GetMapping(produces = "application/vnd.myapi.v1+json")
public UserV1 getUserV1() { }

@GetMapping(produces = "application/vnd.myapi.v2+json")
public UserV2 getUserV2() { }

Zalety: URI stabilne Wady: trudniejsze testowanie (curl, browser)

Strategia wersjonowania:

  • Nowa wersja gdy breaking change (zmiana struktury, usunięcie pola)
  • Addytywne zmiany (nowe pola) - bez nowej wersji
  • Deprecate starą wersję z notice period
  • Sunset header: Sunset: Sat, 1 Jan 2025 00:00:00 GMT

Bezpieczeństwo API

Jak zabezpieczyć REST API?

Odpowiedź w 30 sekund:

  1. HTTPS - zawsze, bez wyjątków
  2. Authentication - JWT, OAuth2
  3. Authorization - sprawdzaj uprawnienia
  4. Input validation - waliduj wszystko
  5. Rate limiting - ochrona przed DDoS

Odpowiedź w 2 minuty:

Bezpieczeństwo REST API wymaga warstwowego podejścia - od zabezpieczenia transportu przez autentykację, po walidację danych wejściowych.

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            // HTTPS tylko
            .requiresChannel(channel -> channel.anyRequest().requiresSecure())
            // CSRF dla stateless API
            .csrf(csrf -> csrf.disable())
            // JWT authentication
            .oauth2ResourceServer(oauth2 -> oauth2.jwt())
            // Authorization rules
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers(HttpMethod.GET, "/api/users/**").hasRole("USER")
                .requestMatchers(HttpMethod.DELETE, "/api/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            // No session
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .build();
    }
}

Walidacja input:

@PostMapping
public User createUser(@Valid @RequestBody CreateUserRequest request) {
    // @Valid automatycznie waliduje
}

public record CreateUserRequest(
    @NotBlank @Size(max = 100) String name,
    @Email String email,
    @Min(18) @Max(120) Integer age
) {}

Rate limiting (Bucket4j):

@GetMapping
@RateLimiter(name = "api")
public List<User> getUsers() { }

Czym różni się autentykacja od autoryzacji?

Odpowiedź w 30 sekund:

  • Autentykacja - "Kim jesteś?" (weryfikacja tożsamości)
  • Autoryzacja - "Co możesz zrobić?" (weryfikacja uprawnień)

Autentykacja → Autoryzacja (w tej kolejności)

Odpowiedź w 2 minuty:

Proces zabezpieczania żądania przebiega w dwóch krokach - najpierw weryfikujemy tożsamość, potem sprawdzamy uprawnienia.

Request → Autentykacja → Autoryzacja → Controller
             ↓               ↓
         "To jest John"   "John może czytać users"

Autentykacja (Authentication):

# Basic Auth (nie zalecane)
Authorization: Basic am9objpwYXNzd29yZA==

# Bearer Token (JWT)
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

# API Key (dla integracji)
X-API-Key: sk_live_abc123

Autoryzacja (Authorization):

// Role-based
@PreAuthorize("hasRole('ADMIN')")
public void deleteUser(Long id) { }

// Permission-based
@PreAuthorize("hasAuthority('users:delete')")
public void deleteUser(Long id) { }

// Resource-based (sprawdź czy user jest właścicielem)
@PreAuthorize("@userService.isOwner(#id, authentication)")
public void updateUser(Long id, User user) { }

JWT claims dla autoryzacji:

{
  "sub": "user123",
  "roles": ["USER", "EDITOR"],
  "permissions": ["users:read", "posts:write"],
  "exp": 1704067200
}

Jak działa JWT i jakie ma wady?

Odpowiedź w 30 sekund:

JWT (JSON Web Token) = Header.Payload.Signature

  • Self-contained (zawiera wszystkie dane)
  • Stateless (serwer nie przechowuje sesji)
  • Nie można unieważnić przed expiration (główna wada)

Odpowiedź w 2 minuty:

JWT składa się z trzech części oddzielonych kropkami - każda zakodowana w Base64URL. Header określa algorytm, Payload zawiera claims (dane), a Signature potwierdza integralność.

eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ1c2VyMTIzIiwiZXhwIjoxNzA0MDY3MjAwfQ.signature
     HEADER           .        PAYLOAD          .  SIGNATURE
// Header
{"alg": "HS256", "typ": "JWT"}

// Payload
{
  "sub": "user123",
  "name": "John Doe",
  "roles": ["USER"],
  "iat": 1704063600,
  "exp": 1704067200
}

// Signature
HMACSHA256(base64(header) + "." + base64(payload), secret)

Zalety:

  • Stateless - łatwe skalowanie
  • Self-contained - brak database lookup
  • Cross-domain / microservices

Wady:

  • Nie można unieważnić (tylko czekać na exp)
  • Payload czytelny (base64, nie szyfrowany)
  • Rozmiar tokenu większy niż session ID

Rozwiązania wad:

// Short-lived access token + refresh token
Access Token: 15 min expiration
Refresh Token: 7 days, stored in DB (można unieważnić)

// Blacklist (dla logout)
Set<String> blacklistedTokens = new ConcurrentHashSet<>();

public boolean isValid(String token) {
    return !blacklistedTokens.contains(token) && !isExpired(token);
}

Obsługa błędów

Jak projektować odpowiedzi błędów w REST API?

Odpowiedź w 30 sekund:

Standardowa struktura:

{
  "error": "VALIDATION_ERROR",
  "message": "Invalid input",
  "details": [...],
  "timestamp": "2024-01-15T10:30:00Z",
  "path": "/api/users"
}

Odpowiedź w 2 minuty:

RFC 7807 Problem Details:

{
  "type": "https://api.example.com/errors/validation",
  "title": "Validation Error",
  "status": 400,
  "detail": "One or more fields failed validation",
  "instance": "/api/users",
  "errors": [
    {
      "field": "email",
      "message": "must be a valid email address",
      "rejectedValue": "invalid-email"
    },
    {
      "field": "age",
      "message": "must be at least 18",
      "rejectedValue": 15
    }
  ]
}

Spring implementation:

@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(EntityNotFoundException.class)
    public ProblemDetail handleNotFound(EntityNotFoundException e, WebRequest request) {
        ProblemDetail problem = ProblemDetail.forStatus(HttpStatus.NOT_FOUND);
        problem.setTitle("Resource Not Found");
        problem.setDetail(e.getMessage());
        problem.setProperty("timestamp", Instant.now());
        return problem;
    }

    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatusCode status,
            WebRequest request) {

        ProblemDetail problem = ProblemDetail.forStatus(status);
        problem.setTitle("Validation Error");

        List<Map<String, String>> errors = ex.getBindingResult()
            .getFieldErrors()
            .stream()
            .map(error -> Map.of(
                "field", error.getField(),
                "message", error.getDefaultMessage()
            ))
            .toList();

        problem.setProperty("errors", errors);
        return ResponseEntity.status(status).body(problem);
    }
}

Optymalizacja

Jak zoptymalizować wydajność REST API?

Odpowiedź w 30 sekund:

  1. Caching - ETag, Cache-Control headers
  2. Compression - gzip responses
  3. Paginacja - nie zwracaj wszystkiego
  4. Projection - zwracaj tylko potrzebne pola
  5. Connection pooling - HTTP/2, keep-alive

Odpowiedź w 2 minuty:

HTTP Caching:

# Response
HTTP/1.1 200 OK
Cache-Control: max-age=3600
ETag: "abc123"

# Conditional request
GET /users/1
If-None-Match: "abc123"

# If not modified
HTTP/1.1 304 Not Modified
@GetMapping("/{id}")
public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = userService.findById(id);
    String etag = Integer.toHexString(user.hashCode());

    return ResponseEntity.ok()
        .eTag(etag)
        .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
        .body(user);
}

Compression:

# application.yml
server:
  compression:
    enabled: true
    mime-types: application/json,application/xml,text/html
    min-response-size: 1024

Sparse fieldsets:

GET /users/1?fields=id,name,email

# Response (tylko wybrane pola)
{
  "id": 1,
  "name": "John",
  "email": "john@example.com"
}

Batch requests:

POST /batch
{
  "requests": [
    {"method": "GET", "path": "/users/1"},
    {"method": "GET", "path": "/users/2"},
    {"method": "GET", "path": "/users/3"}
  ]
}

Zobacz też


Ten artykuł jest częścią serii przygotowującej do rozmów rekrutacyjnych na stanowisko Backend Developer. Sprawdź nasze fiszki z pytaniami rekrutacyjnymi.

Chcesz więcej pytań rekrutacyjnych?

To tylko jeden temat z naszego kompletnego przewodnika po rozmowach rekrutacyjnych. Uzyskaj dostęp do 800+ pytań z 13 technologii.

Kup pełny dostęp Zobacz bezpłatny podgląd
Powrót do blogu

Zostaw komentarz

Pamiętaj, że komentarze muszą zostać zatwierdzone przed ich opublikowaniem.