### Run Quick Start Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/README.md Command to run the quick start example. ```bash python3 main.py --data - < Response: name = request.body.get('name') if not name: return Response( code=400, errors=[APIError(code=400, message='name is required')] ) return Response( body={'message': f'Hello, {name}!'}, code=200 ) if __name__ == '__main__': func.run() ``` -------------------------------- ### HTTP Request Examples - GET Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md Example of a GET request using curl. ```bash curl -X POST http://localhost:8081/ \ -H "Content-Type: application/json" \ -d '{ "method": "GET", "url": "/users", "params": { "query": {"limit": ["10"]} } }' ``` -------------------------------- ### Configuration File Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example JSON structure for a configuration file. ```json { "api_key": "secret", "environment": "production", "database": { "host": "db.example.com", "port": 5432 } } ``` -------------------------------- ### API Keys and Credentials Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example demonstrating how to retrieve API keys and credentials from the configuration. ```json { "apis": { "external_service": { "key": "api-key-123", "secret": "api-secret-456", "base_url": "https://api.example.com" }, "payment_gateway": { "key": "pg-key-789", "endpoint": "https://payments.example.com" } } } ``` ```python from typing import Any from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='POST', path='/payment') def process_payment(request: Request, config: dict[str, Any] | None) -> Response: if not config: return Response(code=500, errors=[{'code': 500, 'message': 'config required'}]) pg_config = config['apis']['payment_gateway'] api_key = pg_config['key'] # Process payment using api_key return Response(body={'transaction_id': '123'}, code=200) ``` -------------------------------- ### Database Configuration Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example showing how to access database configuration details from the `config` object. ```json { "database": { "host": "db.example.com", "port": 5432, "username": "appuser", "password": "encrypted-password", "database": "myapp" } } ``` ```python from typing import Any from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='GET', path='/data') def get_data(request: Request, config: dict[str, Any] | None) -> Response: if not config or 'database' not in config: return Response( code=500, errors=[{'code': 500, 'message': 'database config missing'}] ) db_config = config['database'] # Connect to database using db_config return Response(body={'status': 'ok'}, code=200) ``` -------------------------------- ### Feature Flags Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example showing how to use feature flags defined in the configuration. ```json { "features": { "beta_api": true, "analytics": true, "debug_logging": false }, "environment": "production" } ``` ```python from logging import Logger from typing import Any from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='POST', path='/action') def perform_action( request: Request, config: dict[str, Any] | None, logger: Logger ) -> Response: debug = config and config.get('features', {}).get('debug_logging', False) if debug: logger.debug(f'Request body: {request.body}') if config and config.get('features', {}).get('beta_api'): # Use new API result = new_api_call(request.body) else: # Use stable API result = stable_api_call(request.body) return Response(body=result, code=200) ``` -------------------------------- ### Configuration Parameter Type Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example demonstrating how to handle the `config` parameter which can be a dictionary or None. ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler(request: Request, config: dict[str, Any] | None) -> Response: if config is None: # No configuration available api_key = 'default-key' else: # Configuration available api_key = config.get('api_key', 'default-key') return Response(body={'using_api_key': bool(api_key)}, code=200) ``` -------------------------------- ### CLIRunner Example - Simple GET Request Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md Example of a simple GET request using the CLIRunner. ```json { "method": "GET", "url": "/users" } ``` ```bash python3 main.py --data request.json ``` ```text Status code: 200 Response Header: Content-Length: 35 Response Header: Content-Type: application/json Response Payload: {"body": {"users": []}, "code": 200} ``` -------------------------------- ### GET Request Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/endpoints.md Example of a GET request with query parameters and an authorization header. ```json { "method": "GET", "url": "/users", "params": { "query": { "limit": ["10"], "offset": ["0"] }, "header": { "Authorization": ["Bearer token123"] } } } ``` -------------------------------- ### HTTP GET Handler Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md An example of how to implement an HTTP GET handler for a function. ```python from crowdstrike.foundry.function import ( APIError, Request, Response, Function, ) func = Function.instance() # An example GET handler @func.handler(method='GET', path='/my-resource') def on_get(request: Request) -> Response: # Fetch the requested resources resources = [] # ...snip... # Return the requested resources return Response( body={'resources': resources}, code=200, ) if __name__ == '__main__': func.run() ``` -------------------------------- ### Programmatic Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of initializing a function instance with programmatic configuration. ```python func = Function.instance(config={ 'api_key': 'my-key', 'environment': 'production' }) ``` -------------------------------- ### Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of accessing configuration parameters within a handler. ```python from typing import Any def handler(request: Request, config: dict[str, Any] | None) -> Response: if config is None: return Response( code=500, errors=[APIError(code=500, message='configuration required')] ) api_key = config.get('api_key') environment = config.get('environment', 'dev') return Response(body={'environment': environment}, code=200) ``` -------------------------------- ### Router Initialization Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Example of initializing the Router class. ```python from crowdstrike.foundry.function.router import Router config = {'api_key': 'secret'} router = Router(config) ``` -------------------------------- ### Example Configuration File (config.json) Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md An example JSON file structure for application configuration. ```json { "api_key": "sk-1234567890", "environment": "production", "database": { "host": "db.example.com", "port": 5432, "name": "myapp" }, "features": { "debug": false } } ``` -------------------------------- ### Route Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Example of creating a Route instance. ```python from crowdstrike.foundry.function.router import Route def my_handler(request): return Response(body={}, code=200) route = Route( func=my_handler, method='GET', path='/users' ) ``` -------------------------------- ### Provide Sensible Defaults Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md This example illustrates how to provide default values for configuration settings if they are not explicitly provided. ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler(request: Request, config: dict[str, Any] | None) -> Response: settings = config or {} timeout = settings.get('timeout_ms', 5000) max_retries = settings.get('max_retries', 3) cache_ttl = settings.get('cache_ttl_seconds', 300) return Response( body={'timeout': timeout, 'retries': max_retries, 'cache_ttl': cache_ttl}, code=200 ) ``` -------------------------------- ### Example GET request using curl Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md Example of how to test a GET request to the local function endpoint using curl. ```shell # Test GET /my-resource request curl --location 'http://localhost:8081' \ -H 'Content-Type: application/json' \ --data '{ "method": "GET", "url": "/my-resource" }' ``` -------------------------------- ### Programmatic Configuration Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Illustrates how to provide configuration directly when initializing a Function instance. ```python from crowdstrike.foundry.function import Function config = { 'db_host': 'db.production.com', 'api_key': 'prod-key', 'debug': False } func = Function.instance(config=config) ``` -------------------------------- ### Multiple Endpoints Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Provides a comprehensive example of defining multiple HTTP endpoints (GET, POST, DELETE, PUT) for different paths using the @func.handler decorator. ```python from crowdstrike.foundry.function import Function, Request, Response, APIError func = Function.instance() # GET /users — list all users @func.handler(method='GET', path='/users') def list_users(request: Request) -> Response: return Response(body={'users': []}, code=200) # POST /users — create user @func.handler(method='POST', path='/users') def create_user(request: Request) -> Response: return Response(body={'id': 1}, code=201) # GET /users/{id} and GET /items — different paths @func.handler(method='GET', path='/items') def list_items(request: Request) -> Response: return Response(body={'items': []}, code=200) # DELETE /users — delete operation @func.handler(method='DELETE', path='/users') def delete_user(request: Request) -> Response: return Response(code=200) # PUT /users — update operation @func.handler(method='PUT', path='/users') def update_user(request: Request) -> Response: return Response(body={'id': 1}, code=200) if __name__ == '__main__': func.run() ``` -------------------------------- ### File-Based Configuration Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Demonstrates loading configuration from a JSON file and using it in a handler. ```json { "db_host": "localhost", "db_port": 5432, "api_key": "secret" } ``` ```bash export CS_FN_CONFIG_PATH=./config.json python3 main.py ``` ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler(request: Request, config: dict[str, Any] | None) -> Response: db_host = config['db_host'] if config else 'localhost' return Response(body={'db_host': db_host}, code=200) ``` -------------------------------- ### Enable Logging Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of how to enable and use logging within a handler function to debug requests and processing. ```python from logging import Logger @func.handler(method='GET', path='/debug') def debug_handler(request: Request, config, logger: Logger) -> Response: logger.debug(f'Request: {request.method} {request.url}') logger.debug(f'Body: {request.body}') logger.info('Processing started') # ... return Response(body={}, code=200) ``` -------------------------------- ### Authentication Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of checking and validating an access token. ```python def handler(request: Request) -> Response: # Check access token if not request.access_token: return Response( code=401, errors=[APIError(code=401, message='authentication required')] ) # Validate token if not is_valid_token(request.access_token): return Response( code=401, errors=[APIError(code=401, message='invalid token')] ) return Response(body={}, code=200) ``` -------------------------------- ### Query Parameters Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of extracting and validating query parameters. ```python def handler(request: Request) -> Response: # Extract from query parameters user_id = request.params.query.get('id', [''])[0] limit = request.params.query.get('limit', ['10'])[0] if not user_id: return Response( code=400, errors=[APIError(code=400, message='id parameter required')] ) return Response(body={'id': user_id, 'limit': limit}, code=200) ``` -------------------------------- ### Router.register() Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Example of registering a route with the Router. ```python from crowdstrike.foundry.function.router import Router, Route from crowdstrike.foundry.function import Request, Response def get_user(request: Request) -> Response: return Response(body={'id': 1, 'name': 'John'}, code=200) router = Router(config=None) router.register(Route(func=get_user, method='GET', path='/user')) ``` -------------------------------- ### Programmatic Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of passing configuration directly when creating a Function instance. ```python from crowdstrike.foundry.function import Function custom_config = { 'api_key': 'my-key', 'environment': 'production', } func = Function.instance(config=custom_config) ``` -------------------------------- ### Minimal Function Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md A basic example of a Foundry Function with a single 'hello' endpoint. ```python from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='GET', path='/hello') def hello(request: Request) -> Response: return Response(body={'message': 'Hello, World!'}, code=200) if __name__ == '__main__': func.run() ``` -------------------------------- ### No Configuration Available Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Demonstrates the scenario where no configuration is available and `loader.load()` returns `None`. ```python import os from crowdstrike.foundry.function.config_loader_fs import FileSystemConfigLoader # Clear the environment variable if 'CS_FN_CONFIG_PATH' in os.environ: del os.environ['CS_FN_CONFIG_PATH'] loader = FileSystemConfigLoader() config = loader.load() print(config) # None ``` -------------------------------- ### Complete Example: Request and Response Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/request-response.md A comprehensive example demonstrating a POST request handler that creates a user, including validation, authorization, and returning a success response with headers. ```python from logging import Logger from typing import Any from crowdstrike.foundry.function import Function, Request, Response, APIError func = Function.instance() @func.handler(method='POST', path='/users') def create_user( request: Request, config: dict[str, Any] | None, logger: Logger ) -> Response: logger.info(f'Creating user, trace_id={request.trace_id}') # Validate request if 'name' not in request.body: return Response( code=400, errors=[APIError(code=400, message='name is required')] ) if 'email' not in request.body: return Response( code=400, errors=[APIError(code=400, message='email is required')] ) # Check authorization if not request.access_token: return Response( code=401, errors=[APIError(code=401, message='authentication required')] ) # Extract data name = request.body['name'] email = request.body['email'] # Create user (would normally save to database) new_user_id = 12345 # Return success response with headers return Response( body={ 'id': new_user_id, 'name': name, 'email': email, 'created_at': '2025-01-15T10:30:00Z' }, code=201, header={ 'X-Created-Resource-Id': [str(new_user_id)], 'Location': [f'/users/{new_user_id}'] } ) if __name__ == '__main__': func.run() ``` -------------------------------- ### HTTP Request Examples - POST Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md Example of a POST request with a body using curl. ```bash curl -X POST http://localhost:8081/ \ -H "Content-Type: application/json" \ -d '{ "method": "POST", "url": "/users", "body": { "name": "John", "email": "john@example.com" } }' ``` -------------------------------- ### JSON Configuration File Format Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of a valid JSON configuration file structure. ```json { "api_key": "secret-key-123", "environment": "production", "database_url": "postgresql://host/db", "features": { "debug": false, "cache_enabled": true }, "timeouts": { "api_call": 5000, "db_query": 3000 } } ``` -------------------------------- ### Function.run() Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/function.md An example demonstrating how to initialize a Function instance and run it. ```python from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='GET', path='/health') def health_check(request: Request) -> Response: return Response(body={'status': 'ok'}, code=200) if __name__ == '__main__': func.run() ``` -------------------------------- ### CLIRunner Example - POST Request with Headers Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md Example of a POST request with headers using the CLIRunner. ```json { "method": "POST", "url": "/users", "body": { "name": "John Doe", "email": "john@example.com" } } ``` ```bash python3 main.py --data request.json \ --header "Authorization: Bearer token123" ``` -------------------------------- ### CLIRunner Example - File Upload Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md Example of a file upload request using the CLIRunner. ```json { "method": "POST", "url": "/upload", "body": { "name": "John" } } ``` ```bash python3 main.py --data request.json \ -H "Content-Type: multipart/form-data" \ --file document.pdf ``` -------------------------------- ### Request Processing Pipeline Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/mapping.md An example demonstrating a request processing pipeline using Foundry functions. ```python from crowdstrike.foundry.function import Request from crowdstrike.foundry.function.mapping import dict_to_request, response_to_dict ``` -------------------------------- ### Success Response Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/types.md An example of how to construct a successful Response object. ```python from crowdstrike.foundry.function import Response return Response( body={ 'id': 123, 'name': 'John', 'created_at': '2025-01-01T00:00:00Z', }, code=200, ) ``` -------------------------------- ### Query Usage Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/request-response.md Illustrates how to retrieve and process query parameters in a request handler. ```python from crowdstrike.foundry.function import Request, Response def handler(request: Request) -> Response: # Query parameters are lists of strings user_id = request.params.query.get('id', [''])[0] # Multiple values for same parameter tag_list = request.params.query.get('tags', []) # Could be ['admin', 'user'] # Optional parameter with default limit = request.params.query.get('limit', ['10'])[0] offset = request.params.query.get('offset', ['0'])[0] return Response( body={ 'user_id': user_id, 'tags': tag_list, 'pagination': {'limit': limit, 'offset': offset} }, code=200 ) ``` -------------------------------- ### Custom Configuration Loader Implementation Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of implementing a custom configuration loader by extending ConfigLoaderBase. ```python from crowdstrike.foundry.function.config_loader import ConfigLoaderBase, ConfigLoader from crowdstrike.foundry.function import Function import json import requests class RemoteConfigLoader(ConfigLoaderBase): def __init__(self, config_url: str): super().__init__() self.config_url = config_url def load(self): response = requests.get(self.config_url) return response.json() # Use custom loader remote_loader = RemoteConfigLoader('https://api.example.com/config') config_loader = ConfigLoader(remote_loader) func = Function.instance(config_loader=config_loader) ``` -------------------------------- ### Custom Logger Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/runners.md An example of how to create and pass a custom logger to the Function instance. ```python from crowdstrike.foundry.function import Function from logging import Logger, StreamHandler, Formatter, getLogger # Create custom logger custom_logger = getLogger("my-logger") custom_logger.setLevel("INFO") handler = StreamHandler() formatter = Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') handler.setFormatter(formatter) custom_logger.addHandler(handler) func = Function.instance() @func.handler(method='GET', path='/test') def handler(request): return Response(body={}, code=200) if __name__ == '__main__': # Pass custom logger to runner func.run(logger=custom_logger) ``` -------------------------------- ### Example - Catching FDKException Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/types.md An example demonstrating how to catch FDKException within a handler function. ```python from crowdstrike.foundry.function import Function, Request, Response, FDKException func = Function.instance() @func.handler(method='GET', path='/data') def get_data(request: Request) -> Response: try: # This might raise FDKException if routing fails return Response(body={'data': []}, code=200) except FDKException as e: return Response( code=e.code, errors=[{'code': e.code, 'message': e.message}], ) ``` -------------------------------- ### Request Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/types.md Example of how to use the Request object within a handler function. ```python from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='POST', path='/items') def create_item(request: Request) -> Response: # Access request body item_data = request.body # Access query parameters include_details = request.params.query.get('details', ['false'])[0] # Access headers auth_header = request.params.header.get('authorization', [''])[0] # Access files (if multipart/form-data) if 'file' in request.files: file_content = request.files['file'] return Response( body={'id': 1, 'name': item_data.get('name')}, code=201, ) ``` -------------------------------- ### Install the SDK Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/README.md Install the crowdstrike-foundry-function package using pip. ```bash pip install crowdstrike-foundry-function ``` -------------------------------- ### Handler with File-Based Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of a handler method that accepts and uses configuration loaded from a JSON file. ```python from crowdstrike.foundry.function import Function, Request, Response from typing import Any func = Function.instance() @func.handler(method='POST', path='/process') def handler(request: Request, config: dict[str, Any] | None) -> Response: if config is None: return Response(body={'message': 'no config'}, code=200) api_key = config.get('api_key') environment = config.get('environment', 'dev') return Response( body={'environment': environment}, code=200, ) ``` -------------------------------- ### Response with Headers Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/types.md An example of constructing a Response object that includes custom HTTP headers. ```python from crowdstrike.foundry.function import Response return Response( body={'token': 'abc123'}, code=200, header={ 'X-Custom-Header': ['value1'], 'X-Request-Id': ['12345'], }, ) ``` -------------------------------- ### Accessing Configuration in Handler Methods Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example demonstrating how configuration is passed to handlers that declare the 'config' parameter. ```python from logging import Logger from typing import Any from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() ``` -------------------------------- ### Example Python Handler Implementation Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md A basic example of a POST handler for a Foundry Function, including request validation and response generation. ```python from crowdstrike.foundry.function import ( APIError, Request, Response, Function, ) func = Function.instance() # An example POST handler @func.handler(method='POST', path='/my-resource') def on_post(request: Request) -> Response: # Validate the request body if 'name' not in request.body: # This example expects 'name' field in the request body. # Return an error response (400 - Bad Request) if not provided by the caller return Response( code=400, errors=[APIError(code=400, message='name field is missing from request body')] ) # Process the request new_resource_id = 1 # ...snip... # Return a success response return Response( body={ 'result': f'Resource with name {request.body["name"]} is created.', 'id': new_resource_id }, code=200, ) if __name__ == '__main__': func.run() ``` -------------------------------- ### canonize_header Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/mapping.md Examples demonstrating the usage of canonize_header with different input cases and its application in processing raw headers. ```python from crowdstrike.foundry.function.mapping import canonize_header # Different cases print(canonize_header('authorization')) # 'Authorization' print(canonize_header('CONTENT-TYPE')) # 'Content-Type' print(canonize_header('x-Custom-Header')) # 'X-Custom-Header' print(canonize_header('accept-language')) # 'Accept-Language' # Usage in request processing raw_headers = { 'authorization': 'Bearer token', 'content-type': 'application/json', 'x-custom-id': '12345' } canonized_headers = { canonize_header(k): v for k, v in raw_headers.items() } # Result: { # 'Authorization': 'Bearer token', # 'Content-Type': 'application/json', # 'X-Custom-Id': '12345' # } ``` -------------------------------- ### Setting CS_FN_CONFIG_PATH Environment Variable Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Examples of setting the CS_FN_CONFIG_PATH environment variable for absolute and relative paths. ```bash # Absolute path export CS_FN_CONFIG_PATH=/etc/myapp/config.json python3 main.py # Relative path export CS_FN_CONFIG_PATH=./config.json python3 main.py # In production (Foundry platform sets this automatically) CS_FN_CONFIG_PATH=/path/to/encrypted/config.json python3 main.py ``` -------------------------------- ### APIError Usage Examples Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/request-response.md Examples demonstrating how to create and use APIError objects for different error scenarios. ```python from crowdstrike.foundry.function import APIError, Response # Missing required field error1 = APIError(code=400, message='name field is required') # Authentication failure error2 = APIError(code=401, message='Invalid API key') # Permission denied error3 = APIError(code=403, message='User does not have admin permissions') # Resource not found error4 = APIError(code=404, message='User with ID 999 not found') # Server error error5 = APIError(code=500, message='Database connection failed') # Return multiple errors return Response( code=400, errors=[error1, error2] ) ``` -------------------------------- ### Example POST request using curl Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md Example of how to test a POST request to the local function endpoint using curl. ```shell # Test POST /my-resource request curl --location 'http://localhost:8081' \ -H 'Content-Type: application/json' \ --data '{ "body": { "name": "bar" }, "method": "POST", "url": "/my-resource" }' ``` -------------------------------- ### Function.instance() Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/function.md Example of how to get the singleton instance of the Function class. ```python from crowdstrike.foundry.function import Function func = Function.instance() ``` -------------------------------- ### Validate Configuration on Startup Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md This example shows how to validate essential configuration keys ('api_key', 'database_url') when the function initializes and exit if they are missing. ```python from typing import Any from crowdstrike.foundry.function import Function, Request, Response def validate_config(config: dict[str, Any] | None) -> bool: if not config: return False required_keys = ['api_key', 'database_url'] return all(key in config for key in required_keys) func = Function.instance() # Validate configuration when function is initialized if not validate_config(func._config): print('ERROR: Required configuration is missing') exit(1) @func.handler(method='GET', path='/health') def health_check(request: Request) -> Response: return Response(body={'status': 'ok'}, code=200) ``` -------------------------------- ### FalconPy SDK usage example for Hosts API Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md Example demonstrating how to use the FalconPy SDK within a Foundry function to query host details, utilizing context authentication. ```python from falconpy import Hosts from crowdstrike.foundry.function import ( Function, Request, Response, APIError ) func = Function.instance() @func.handler(method='POST', path='/hosts-query') def on_hosts_query(request: Request) -> Response: # get the requested Host IDs from the request body host_ids = request.body.get("ids") if not host_ids: return Response( code=400, errors=[APIError(code=400, message='Required host ids are not provided')] ) # Initialize falconpy client for Hosts API # This example uses context authentication hosts_client = Hosts() # Call falconpy API to fetch the details of the requested hosts api_result = hosts_client.get_device_details_v1(ids=host_ids) if api_result['status_code'] != 200: # falconpy API returned an error response = Response( code=api_result['status_code'], errors=[ APIError(code=api_result['status_code'], message="falconpy API call failed") ] ) else: # falconpy API was successful, return the requested data response = Response( body={ 'hosts': api_result['body']['resources'] }, code=200 ) return response if __name__ == '__main__': func.run() ``` -------------------------------- ### HTTP PUT Handler Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/README.md An example of how to implement an HTTP PUT handler for a function, including error handling for missing parameters. ```python from crowdstrike.foundry.function import ( APIError, Request, Response, Function, ) func = Function.instance() # An example PUT handler @func.handler(method='PUT', path='/my-resource') def on_put(request: Request) -> Response: # Obtain the id of the resource to update from the request query parameters resource_id = request.params.query.get('id') if not resource_id: # This example expects 'id' field in the request query parameters. # Returns an error response (400 - Bad Request) if not provided by the caller return Response( code=400, errors=[APIError(code=400, message='id field is missing from request params')] ) # Get the update data provided in the request body and # Update the resource with the data provided data = request.body.get('data') # ...snip... # Return success with the updated resource info return Response( body={ 'result': f'Resource {resource_id} is updated successfully.', 'data': data }, code=200, ) if __name__ == '__main__': func.run() ``` -------------------------------- ### cloud() Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/function.md Example demonstrating how to use the cloud() function to get the current cloud identifier. ```python from crowdstrike.foundry.function import cloud current_cloud = cloud() # Returns: 'us1', 'eu1', 'auto', etc. ``` -------------------------------- ### Command-line example for loading configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Shows how to export the configuration file path as an environment variable before running a Python script. ```bash export CS_FN_CONFIG_PATH=/etc/myapp/config.json python3 main.py ``` -------------------------------- ### GET Endpoint - List Resources Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/endpoints.md Example of a GET endpoint handler to list resources with support for pagination via query parameters. ```python from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='GET', path='/users') def list_users(request: Request) -> Response: # Extract query parameters limit = int(request.params.query.get('limit', ['10'])[0]) offset = int(request.params.query.get('offset', ['0'])[0]) # Fetch users users = [ {'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}, ] return Response( body={'users': users[offset:offset+limit], 'total': len(users)}, code=200, ) # Request: # { # "method": "GET", # "url": "/users", # "params": { # "query": {"limit": ["20"], "offset": ["0"]} # } # } # Response: # { # "code": 200, # "body": { # "users": [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}], # "total": 2 # } # } ``` -------------------------------- ### Custom Loader Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Demonstrates creating a custom configuration loader to load settings from environment variables. ```python from crowdstrike.foundry.function import Function from crowdstrike.foundry.function.config_loader import ConfigLoader class EnvConfigLoader(ConfigLoaderBase): def load(self): import os return { 'api_key': os.getenv('API_KEY'), 'debug': os.getenv('DEBUG', 'false').lower() == 'true' } func = Function.instance( config_loader=ConfigLoader(EnvConfigLoader()) ) ``` -------------------------------- ### Use Configuration for Different Environments Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md This example shows how to use configuration values to adapt function behavior based on the environment (e.g., 'production' vs. 'dev'). ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler(request: Request, config: dict[str, Any] | None) -> Response: env = config.get('environment', 'dev') if config else 'dev' if env == 'production': # More strict validation, logging, etc. return Response(body={}, code=200) else: # Allow more permissive behavior in dev/test return Response(body={}, code=200) ``` -------------------------------- ### Example usage of FileSystemConfigLoader Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Demonstrates how to set the CS_FN_CONFIG_PATH environment variable and use FileSystemConfigLoader to load configuration. ```python from crowdstrike.foundry.function.config_loader_fs import FileSystemConfigLoader import os # Set configuration file path os.environ['CS_FN_CONFIG_PATH'] = './config.json' # Create and load loader = FileSystemConfigLoader() config = loader.load() # config = {'api_key': 'secret', ...} ``` -------------------------------- ### Document Expected Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md This example includes a docstring that outlines the expected structure and types of configuration parameters, along with a simple handler. ```python """ Expected configuration (config.json): { "api_key": "string - API key for external service", "environment": "string - 'dev', 'staging', or 'production'", "database": { "host": "string - database host", "port": "int - database port", "name": "string - database name" }, "logging": { "level": "string - log level", "format": "string - log format" } } """ from typing import Any from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='GET', path='/config-info') def config_info(request: Request, config: dict[str, Any] | None) -> Response: return Response( body={'has_config': config is not None}, code=200 ) ``` -------------------------------- ### Input Validation Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of validating required fields in the request body. ```python from crowdstrike.foundry.function import Request, Response, APIError def handler(request: Request) -> Response: # Validate required fields if 'email' not in request.body: return Response( code=400, errors=[APIError(code=400, message='email is required')] ) if 'name' not in request.body: return Response( code=400, errors=[APIError(code=400, message='name is required')] ) # Process valid request return Response(body={}, code=200) ``` -------------------------------- ### Logging Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of using a logger to record information and errors during request processing. ```python from logging import Logger from typing import Any def handler( request: Request, config: dict[str, Any] | None, logger: Logger ) -> Response: logger.info(f'Received {request.method} request to {request.url}') try: result = process_request(request) logger.info('Request processed successfully') return Response(body=result, code=200) except Exception as e: logger.error(f'Error processing request: {e}') return Response( code=500, errors=[APIError(code=500, message='internal error')] ) ``` -------------------------------- ### Handle Missing Configuration Gracefully Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md This example demonstrates how to check if the 'api_key' configuration is present and return an error if it's missing. ```python from typing import Any from crowdstrike.foundry.function import Request, Response, APIError def handler(request: Request, config: dict[str, Any] | None) -> Response: required_api_key = None if config and 'api_key' in config: required_api_key = config['api_key'] else: return Response( code=500, errors=[ APIError(code=500, message='Required configuration "api_key" not provided') ] ) return Response(body={'configured': True}, code=200) ``` -------------------------------- ### Request/Response Abstraction Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of a handler function using the Request and Response objects. ```python from crowdstrike.foundry.function import Request, Response def handler(request: Request) -> Response: # Request contains: body, params, headers, query, method, url, etc. name = request.body.get('name') # Response is serialized as JSON and returned return Response( body={'name': name}, code=200 ) ``` -------------------------------- ### Print to Console Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md A simple example of printing debug information to the console from a handler function. ```python @func.handler(method='GET', path='/test') def test_handler(request: Request) -> Response: print(f'Debug: {request.body}') return Response(body={}, code=200) ``` -------------------------------- ### Access Configuration in Handler Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of accessing configuration parameters within a handler, with a default value. ```python def handler(request: Request, config: dict[str, Any] | None) -> Response: if config is None: api_key = 'default' else: api_key = config.get('api_key', 'default') return Response(body={'has_key': bool(api_key)}, code=200) ``` -------------------------------- ### Handler with Configuration Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Demonstrates a handler that accepts a configuration dictionary. ```python from crowdstrike.foundry.function import Request, Response @func.handler(method='GET', path='/with-config') def handler_with_config(request: Request, config: dict[str, Any] | None) -> Response: if config is None: return Response(body={'status': 'no config'}, code=200) return Response( body={ 'api_key_set': 'api_key' in config, 'environment': config.get('environment', 'dev'), }, code=200, ) ``` -------------------------------- ### Router.__init__() Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Initialize the router with configuration. ```python def __init__(self, config): """Initialize the router. :param config: The config loaded from the configuration file, if provided. """ ``` -------------------------------- ### Integration with FalconPy Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example demonstrating how to integrate CrowdStrike FalconPy to access CrowdStrike APIs within a function. ```python from falconpy import Hosts from crowdstrike.foundry.function import Function, Request, Response func = Function.instance() @func.handler(method='POST', path='/get-hosts') def get_hosts(request: Request) -> Response: host_ids = request.body.get('ids', []) # Use FalconPy with context authentication hosts_client = Hosts() result = hosts_client.get_device_details_v1(ids=host_ids) if result['status_code'] != 200: return Response( code=result['status_code'], errors=[{'code': result['status_code'], 'message': 'API error'}] ) return Response(body={'hosts': result['body']['resources']}, code=200) ``` -------------------------------- ### Configuration Access Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/router.md Demonstrates how to access configuration parameters within a handler function, including handling cases where configuration might be None. ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler_with_config(request: Request, config: dict[str, Any] | None) -> Response: if config is None: api_key = 'default-key' else: api_key = config.get('api_key') return Response(body={'using_key': bool(api_key)}, code=200) ``` -------------------------------- ### HTTP Server Mode Request Format Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example JSON structure for requests in HTTP Server Mode. ```json { "method": "GET|POST|PUT|PATCH|DELETE", "url": "/endpoint-path", "body": {}, "params": { "query": {"param": ["value"]}, "header": {"Header": ["value"]} } } ``` -------------------------------- ### Multiple Errors Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example demonstrating how to return multiple errors in a single response when several validation checks fail. ```python def handler(request: Request) -> Response: errors = [] if 'name' not in request.body: errors.append(APIError(code=400, message='name is required')) if 'email' not in request.body: errors.append(APIError(code=400, message='email is required')) if errors: return Response(code=400, errors=errors) return Response(body={}, code=200) ``` -------------------------------- ### Return Errors in Response Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Example of returning a 400 Bad Request error when a required field is missing from the request body. ```python def handler(request: Request) -> Response: if 'required_field' not in request.body: return Response( code=400, errors=[ APIError(code=400, message='required_field is missing') ] ) return Response(body={}, code=200) ``` -------------------------------- ### Default Configuration Behavior Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Demonstrates how to create a Function instance without specifying a config_loader, relying on the default behavior. ```python from crowdstrike.foundry.function import Function # Uses default configuration loading func = Function.instance() # Equivalent to: # func = Function.instance( # config_loader=ConfigLoader(FileSystemConfigLoader()) # ) ``` -------------------------------- ### Using Configuration Type Hint in Handler Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/api-reference/config-loaders.md Example of how to correctly use the `ConfigType` hint and handle `None` values in a handler function. ```python from typing import Any from crowdstrike.foundry.function import Request, Response def handler(request: Request, config: dict[str, Any] | None) -> Response: if config is None: # No configuration available, use defaults value = get_default_value() else: # Configuration loaded value = config.get('setting_name', get_default_value()) return Response(body={'value': value}, code=200) ``` -------------------------------- ### RequestParams Example Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/types.md Example of how to access query parameters and headers using RequestParams. ```python from crowdstrike.foundry.function import Request, Response def handler(request: Request) -> Response: # Access query parameters user_ids = request.params.query.get('ids', []) # Returns: ['1', '2', '3'] if URL is ?ids=1&ids=2&ids=3 # Access headers auth = request.params.header.get('Authorization', [''])[0] content_type = request.params.header.get('Content-Type', [''])[0] return Response(body={}, code=200) ``` -------------------------------- ### Load Configuration from File Command Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/GUIDE.md Command to set the configuration path environment variable. ```bash export CS_FN_CONFIG_PATH=./config.json python3 main.py ``` -------------------------------- ### Setting PORT Environment Variable Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Examples of setting the PORT environment variable to configure the HTTP server port. ```bash # Default port (8081) python3 main.py # Custom port export PORT=9000 python3 main.py # One-liner PORT=3000 python3 main.py ``` -------------------------------- ### Local Testing with Environment Variables Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of setting various environment variables, including CS_FN_CONFIG_PATH, for local testing. ```bash export PORT=9000 export CS_CLOUD=us-1 export CS_FN_CONFIG_PATH=./test-config.json python3 main.py ``` -------------------------------- ### Local Testing with Configuration File Source: https://github.com/crowdstrike/foundry-fn-python/blob/main/_autodocs/configuration.md Example of setting the CS_FN_CONFIG_PATH environment variable to point to a local JSON configuration file for testing. ```bash export CS_FN_CONFIG_PATH=./config.json python3 main.py --data test_request.json ```