HTTP Request Methods

Master GET, POST, PUT, PATCH, DELETE and advanced request features

Intermediate 20 min read

Understanding HTTP Methods

Apisto provides intuitive methods for all HTTP verbs with built-in error handling, retry logic, and request customization. Let's explore each method with practical examples.

💡 RESTful Principles: Each HTTP method has a specific purpose in REST APIs: GET (read), POST (create), PUT (replace), PATCH (update), DELETE (remove).

GET Requests

Used for retrieving data from the server. Apisto provides multiple ways to make GET requests.

📝 Basic GET


// Simple GET request
const users = await api.get('/users');
console.log('Users:', users);

// With query parameters
const filteredUsers = await api.get('/users', {
  active: true,
  role: 'admin',
  page: 1,
  limit: 10
});
            

⚡ Advanced GET


// GET with custom headers and options
const user = await api.get('/users/123', {
  headers: {
    'X-Custom-Header': 'value',
    'Accept-Language': 'en-US'
  },
  cache: 'no-cache',
  timeout: 5000
});

// Using the generic request method
const products = await api.request('/products', {
  method: 'GET',
  query: { category: 'electronics' }
});
            

POST Requests

Used for creating new resources on the server. Apisto automatically handles JSON serialization.

📝 Basic POST


// Create a new user
const newUser = await api.post('/users', {
  name: 'John Doe',
  email: 'john@example.com',
  role: 'user'
});

console.log('Created user:', newUser);

// POST with additional options
const result = await api.post('/orders', {
  productId: '123',
  quantity: 2
}, {
  headers: {
    'X-Request-ID': 'unique-123'
  }
});
            

📋 Form Data POST


// POST with FormData (for file uploads)
const formData = new FormData();
formData.append('name', 'John Doe');
formData.append('avatar', fileInput.files[0]);

const user = await api.post('/users', formData, {
  // No Content-Type header needed for FormData
});

// URL-encoded form data
const urlEncodedData = new URLSearchParams({
  username: 'johndoe',
  password: 'secret'
});

const login = await api.post('/login', urlEncodedData, {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});
            

PUT & PATCH Requests

PUT replaces entire resources, while PATCH performs partial updates.

🔄 PUT (Replace)


// PUT - Replace entire resource
const updatedUser = await api.put('/users/123', {
  id: 123,
  name: 'John Smith',  // Full replacement
  email: 'john.smith@example.com',
  role: 'admin',
  createdAt: '2023-01-01'  // Must include all fields
});

// PUT for resource creation (if supported by API)
const newResource = await api.put('/resources/456', {
  title: 'New Resource',
  content: 'Resource content'
});
            

🎯 PATCH (Partial Update)


// PATCH - Update only changed fields
const patchedUser = await api.patch('/users/123', {
  name: 'John Smith',  // Only update name
  // email remains unchanged
});

// Multiple partial updates
const updatedOrder = await api.patch('/orders/789', {
  status: 'shipped',
  trackingNumber: 'TRK123456',
  shippedAt: new Date().toISOString()
});

// Using JSON Patch format (if API supports it)
const jsonPatch = await api.patch('/products/456', [
  { op: 'replace', path: '/price', value: 29.99 },
  { op: 'add', path: '/tags', value: ['sale'] }
]);
            

⚠️ Key Difference: PUT replaces the entire resource, while PATCH only updates the provided fields. Always use PATCH for partial updates to avoid overwriting data.

DELETE Requests

Used for removing resources from the server.


// Simple DELETE
await api.delete('/users/123');
console.log('User deleted successfully');

// DELETE with confirmation data
await api.delete('/orders/456', {
  body: JSON.stringify({
    reason: 'cancelled_by_user',
    notes: 'Customer requested cancellation'
  })
});

// DELETE with custom headers
await api.delete('/products/789', {
  headers: {
    'X-Delete-Reason': 'out_of_stock'
  }
});

// Batch delete (if API supports it)
await api.delete('/products', {
  body: JSON.stringify({
    ids: [123, 456, 789]
  })
});
          

Advanced Request Options

Apisto provides extensive options to customize every aspect of your requests.


// Complete request options example
const response = await api.request('/endpoint', {
  method: 'POST',
  
  // Request body
  body: { key: 'value' },
  
  // Headers
  headers: {
    'X-Custom-Header': 'value',
    'Authorization': 'Bearer token123',
    'Content-Type': 'application/json'
  },
  
  // Query parameters
  query: { page: 1, limit: 10 },
  
  // Timeout (overrides global config)
  timeout: 15000,
  
  // Retry configuration
  maxRetries: 5,
  retryCondition: (error) => error.status >= 500,
  
  // Cache control
  cache: 'no-cache',
  skipCache: true,
  
  // Cancellation
  signal: abortController.signal,
  
  // Authentication
  skipAuth: false,
  
  // Response handling
  responseType: 'json', // 'json', 'text', 'blob', 'arrayBuffer'
  parseResponse: true
});

// Common options in practice
const commonOptions = {
  // For sensitive data, disable caching
  cache: 'no-store',
  
  // For real-time data, shorter timeout
  timeout: 5000,
  
  // For large uploads, longer timeout
  timeout: 60000,
  
  // For critical operations, more retries
  maxRetries: 5,
  
  // For public APIs, include API key
  headers: {
    'X-API-Key': 'your-api-key'
  }
};
        

Comprehensive Error Handling

Apisto provides structured error handling for different failure scenarios.

🚨 Basic Error Handling


try {
  const data = await api.get('/users/999'); // Non-existent user
} catch (error) {
  if (error instanceof ApiError) {
    switch (error.status) {
      case 400:
        console.error('Bad request:', error.body);
        break;
      case 401:
        console.error('Unauthorized - please login');
        // Redirect to login
        window.location.href = '/login';
        break;
      case 403:
        console.error('Forbidden - insufficient permissions');
        break;
      case 404:
        console.error('Resource not found');
        break;
      case 500:
        console.error('Server error - please try again later');
        break;
      default:
        console.error(`HTTP ${error.status}:`, error.message);
    }
  } else if (error instanceof NetworkError) {
    console.error('Network issue - check your connection');
  } else {
    console.error('Unexpected error:', error);
  }
}
            

🛡️ Advanced Error Recovery


// Retry with exponential backoff
async function fetchWithRetry(endpoint, maxAttempts = 3) {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await api.get(endpoint);
    } catch (error) {
      if (attempt === maxAttempts) throw error;
      
      if (error.status === 429) { // Rate limited
        const retryAfter = error.headers['retry-after'] || 1000;
        await new Promise(resolve => setTimeout(resolve, retryAfter));
      } else if (error.status >= 500) { // Server error
        await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
      } else {
        throw error; // Don't retry client errors
      }
    }
  }
}

// Circuit breaker pattern
class CircuitBreaker {
  constructor() {
    this.failures = 0;
    this.lastFailure = null;
    this.state = 'CLOSED';
  }

  async execute(requestFn) {
    if (this.state === 'OPEN') {
      if (Date.now() - this.lastFailure > 60000) {
        this.state = 'HALF_OPEN';
      } else {
        throw new Error('Circuit breaker open');
      }
    }

    try {
      const result = await requestFn();
      this.failures = 0;
      this.state = 'CLOSED';
      return result;
    } catch (error) {
      this.failures++;
      this.lastFailure = Date.now();
      if (this.failures >= 5) this.state = 'OPEN';
      throw error;
    }
  }
}
            

Complete CRUD Example


// Complete CRUD operations example
class UserService {
  constructor(api) {
    this.api = api;
  }

  // CREATE
  async createUser(userData) {
    try {
      const user = await this.api.post('/users', userData);
      console.log('User created:', user);
      return user;
    } catch (error) {
      console.error('Failed to create user:', error);
      throw error;
    }
  }

  // READ
  async getUser(userId) {
    try {
      const user = await this.api.get(`/users/${userId}`);
      return user;
    } catch (error) {
      if (error.status === 404) {
        console.log('User not found');
        return null;
      }
      throw error;
    }
  }

  // READ ALL with pagination
  async getUsers(page = 1, limit = 10) {
    const users = await this.api.get('/users', { page, limit });
    return users;
  }

  // UPDATE
  async updateUser(userId, updates) {
    const updatedUser = await this.api.patch(`/users/${userId}`, updates);
    console.log('User updated:', updatedUser);
    return updatedUser;
  }

  // DELETE
  async deleteUser(userId) {
    await this.api.delete(`/users/${userId}`);
    console.log('User deleted successfully');
  }

  // BATCH OPERATIONS
  async bulkUpdateUsers(userUpdates) {
    const results = await this.api.batch(
      userUpdates.map(update => ({
        endpoint: `/users/${update.id}`,
        options: {
          method: 'PATCH',
          body: update.data
        }
      }))
    );
    return results;
  }
}

// Usage
const userService = new UserService(api);

// Complete workflow
async function userManagementWorkflow() {
  // Create a user
  const newUser = await userService.createUser({
    name: 'Alice Johnson',
    email: 'alice@example.com',
    role: 'user'
  });

  // Get the user
  const user = await userService.getUser(newUser.id);

  // Update the user
  await userService.updateUser(user.id, {
    name: 'Alice Smith',
    role: 'admin'
  });

  // Get all users
  const users = await userService.getUsers(1, 20);

  // Bulk update
  await userService.bulkUpdateUsers([
    { id: 1, data: { status: 'active' } },
    { id: 2, data: { status: 'inactive' } }
  ]);

  // Delete user
  await userService.deleteUser(user.id);
}

// Run the workflow
userManagementWorkflow().catch(console.error);
        

🎉 Excellent! You've now mastered all HTTP request methods with Apisto. This foundation will serve you in building robust API integrations.

Ready to handle files?

Learn how to upload, download, and manipulate files with Apisto's powerful file handling capabilities.

Continue to File Handling →