# HTTP Adapter Guide ## Overview The HTTP Adapter in the Baba Yaga REPL demonstrates how to implement a real-world adapter that makes actual HTTP requests. This guide shows how the adapter works, how to use it, and how to implement your own adapters following the same pattern. ## How the HTTP Adapter Works ### 1. Adapter Registration The HTTP adapter is registered in the REPL's adapter registry: ```javascript network: { name: 'Network Adapter', description: 'Handles HTTP requests with real network calls', process: async (command) => { // Adapter logic here } } ``` ### 2. Command Processing The adapter processes commands emitted by scripts: ```javascript if (command.type === 'emit' && command.value.action === 'http_request') { // Process HTTP request } ``` ### 3. HTTP Request Execution The adapter makes actual HTTP requests using Node.js `fetch`: ```javascript const response = await fetch(url, options); const responseText = await response.text(); let responseData = JSON.parse(responseText); ``` ### 4. Response Handling The adapter displays results and handles errors: ```javascript console.log(`✅ ${method} ${url} - Status: ${response.status}`); console.log(`Response Data:`, JSON.stringify(responseData, null, 2)); ``` ## Usage Examples ### Basic GET Request ```javascript // Script ..emit { action: "http_request", method: "GET", url: "https://jsonplaceholder.typicode.com/posts/1" }; ``` ### POST Request with JSON Body ```javascript // Script post_data : { title: "Test Post", body: "This is a test", userId: 1 }; ..emit { action: "http_request", method: "POST", url: "https://jsonplaceholder.typicode.com/posts", headers: { "Content-Type": "application/json" }, body: post_data }; ``` ### Request with Custom Headers ```javascript // Script ..emit { action: "http_request", method: "GET", url: "https://api.example.com/data", headers: { "Authorization": "Bearer YOUR_TOKEN", "Accept": "application/json" }, timeout: 10000 }; ``` ## Adapter Implementation Pattern ### 1. Adapter Structure ```javascript const myAdapter = { name: 'My Adapter', description: 'Handles specific functionality', process: async (command) => { // Adapter logic } }; ``` ### 2. Command Pattern ```javascript // Script emits commands ..emit { action: "my_action", // ... action-specific data }; // Adapter processes commands if (command.type === 'emit' && command.value.action === 'my_action') { // Process the action } ``` ### 3. Error Handling ```javascript try { // Perform action const result = await performAction(command.value); console.log(`✅ Success: ${result}`); } catch (error) { console.log(`❌ Error: ${error.message}`); } ``` ### 4. Response Processing ```javascript // Parse and display responses let responseData; try { responseData = JSON.parse(responseText); } catch { responseData = responseText; } console.log(`Response:`, responseData); ``` ## Supported HTTP Features ### HTTP Methods - **GET**: Fetch data from server - **POST**: Create new resources - **PUT**: Update existing resources - **PATCH**: Partial updates - **DELETE**: Remove resources ### Request Options - **url**: Target endpoint - **method**: HTTP method (default: GET) - **headers**: Request headers - **body**: Request body (for POST/PUT/PATCH) - **timeout**: Request timeout in milliseconds (default: 5000) ### Response Handling - **Status codes**: Displayed in console - **Headers**: Shown for debugging - **Body**: Parsed as JSON or displayed as text - **Errors**: Graceful error handling with helpful messages ## Built-in Examples ### 1. HTTP GET Example ```bash :example http-get ``` Makes a GET request to JSONPlaceholder API to fetch a sample post. ### 2. HTTP POST Example ```bash :example http-post ``` Creates a new post via JSONPlaceholder API with JSON body. ### 3. Weather API Example ```bash :example http-weather ``` Demonstrates integration with OpenWeatherMap API (requires API key). ### 4. Pokémon API Example ```bash :example network ``` Fetches Pokémon data from PokéAPI. ## Creating Your Own Adapter ### Step 1: Define Adapter Structure ```javascript const myCustomAdapter = { name: 'Custom Adapter', description: 'Handles custom functionality', process: async (command) => { // Your adapter logic } }; ``` ### Step 2: Implement Command Processing ```javascript process: async (command) => { if (command.type === 'emit' && command.value.action === 'my_custom_action') { const { param1, param2 } = command.value; try { // Perform your custom action const result = await performCustomAction(param1, param2); // Display results console.log(`[Custom Adapter] ✅ Success: ${result}`); } catch (error) { console.log(`[Custom Adapter] ❌ Error: ${error.message}`); } } } ``` ### Step 3: Register with REPL ```javascript // In REPL constructor this.adapters = { // ... existing adapters custom: myCustomAdapter }; ``` ### Step 4: Use in Scripts ```javascript // Script ..emit { action: "my_custom_action", param1: "value1", param2: "value2" }; ``` ## Adapter Best Practices ### 1. Clear Naming - Use descriptive adapter names - Provide clear descriptions - Use consistent naming conventions ### 2. Error Handling - Always wrap operations in try-catch - Provide helpful error messages - Handle different error types appropriately ### 3. Logging - Use colored console output for clarity - Include adapter name in logs - Show success/failure status ### 4. Response Processing - Handle different response formats - Parse JSON when appropriate - Display results in readable format ### 5. Configuration - Support timeout configuration - Allow custom headers - Provide sensible defaults ## Integration Patterns ### 1. State-Driven Requests ```javascript // Script uses current state to determine request state : ..listen; pokemon_name : when state is { pokemon: name } then name _ then "ditto"; ..emit { action: "http_request", method: "GET", url: "https://pokeapi.co/api/v2/pokemon/" + pokemon_name }; ``` ### 2. Conditional Requests ```javascript // Script makes conditional requests state : ..listen; when state.action is "fetch_user" then ..emit { action: "http_request", method: "GET", url: "https://api.example.com/users/" + state.userId } "create_user" then ..emit { action: "http_request", method: "POST", url: "https://api.example.com/users", body: state.userData }; ``` ### 3. Batch Requests ```javascript // Script makes multiple requests ..emit { action: "http_request", method: "GET", url: "https://api.example.com/users" }; ..emit { action: "http_request", method: "GET", url: "https://api.example.com/posts" }; ``` ## Troubleshooting ### Common Issues 1. **Node.js Version**: `fetch` requires Node.js 18+ or a polyfill 2. **Network Errors**: Check internet connection and URL validity 3. **API Keys**: Some APIs require authentication 4. **CORS**: Browser-based requests may have CORS restrictions 5. **Rate Limiting**: APIs may limit request frequency ### Debug Tips 1. **Check Adapters**: Use `:adapters` to see available adapters 2. **Test URLs**: Verify URLs work in browser/curl first 3. **Check Headers**: Ensure required headers are included 4. **Monitor Logs**: Watch console output for detailed information 5. **Use Examples**: Start with built-in examples as templates ## Advanced Features ### Custom Headers ```javascript ..emit { action: "http_request", method: "GET", url: "https://api.example.com/data", headers: { "Authorization": "Bearer YOUR_TOKEN", "X-Custom-Header": "custom-value" } }; ``` ### Request Timeout ```javascript ..emit { action: "http_request", method: "GET", url: "https://api.example.com/data", timeout: 10000 // 10 seconds }; ``` ### JSON Body ```javascript ..emit { action: "http_request", method: "POST", url: "https://api.example.com/data", body: { key: "value", nested: { data: "example" } } }; ``` ## Conclusion The HTTP Adapter demonstrates how to build real-world adapters that integrate external services with the Baba Yaga scripting language. By following the patterns shown in this guide, you can create adapters for: - Database operations - File system access - Message queues - WebSocket connections - Email services - Payment processing - And much more The key is maintaining the functional, side-effect-free nature of scripts while providing powerful integration capabilities through well-designed adapters.