### Minimal Fiber Server Setup Source: https://github.com/w8fyz/fiber/blob/main/README.md A basic Fiber server setup with a simple 'Hello World' controller. Enable API documentation by setting the second argument to true. ```java public class Main { public static void main(String[] args) throws Exception { FiberServer server = new FiberServer(8080, true); // port, enable docs server.registerController(new HelloController()); server.start(); } } @Controller("/api") public class HelloController { @RequestMapping(value = "/hello", method = RequestMapping.Method.GET) public ResponseEntity> hello() { return ResponseEntity.ok(Map.of("message", "Hello, World!")); } } ``` -------------------------------- ### Full Fiber Server Setup in Java Source: https://github.com/w8fyz/fiber/blob/main/README.md This Java code demonstrates a complete Fiber server setup, including database configuration, authentication, session management, security settings, role registration, and controller registration. Ensure all necessary dependencies are included. ```java public class Main { public static void main(String[] args) throws Exception { // Database Architect architect = new Architect() .setDatabaseCredentials(new DatabaseCredentials( new PostgreSQLAuth("localhost", 5432, "mydb"), "postgres", "password", 16)); architect.start(); // Server FiberServer server = new FiberServer(8080, true); server.enableDevelopmentMode(); // Auth UserRepository userRepo = new UserRepository(); MyAuthService authService = new MyAuthService(userRepo); server.setAuthService(authService); server.getAuthResolver().registerAuthenticator(new CookieAuthenticator()); server.getAuthResolver().registerAuthenticator(new BearerAuthenticator()); // Sessions server.setSessionService(new SessionService(new GenericRepository<>(FiberSession.class))); // Security server.enableCSRFProtection(); server.setCorsService(new CorsService() .addAllowedOrigin("http://localhost:3000") .setAllowCredentials(true)); // Roles server.getRoleRegistry().registerRoleClasses(AdminRole.class, UserRole.class); // Controllers server.registerController(new AuthController()); server.registerController(new UserController()); server.registerController(new FileController()); server.start(); } } ``` -------------------------------- ### Session Setup Source: https://github.com/w8fyz/fiber/blob/main/README.md Configuration for enabling server-side sessions using a database repository. ```APIDOC ## Sessions Setup ### Description Fiber supports server-side sessions backed by a database (via Architect). Sessions are created automatically on login and validated on each authenticated request. ### Setup ```java GenericRepository sessionRepo = new GenericRepository<>(FiberSession.class); server.setSessionService(new SessionService(sessionRepo)); // or with custom TTL: new SessionService(sessionRepo, 30 * 24 * 60 * 60 * 1000L) // 30 days ``` Make sure `FiberSession` is registered as a Hibernate entity so the table is created. ``` -------------------------------- ### Fiber Controller and Routing Example Source: https://github.com/w8fyz/fiber/blob/main/README.md Demonstrates how to define controllers and routes using annotations like @Controller, @RequestMapping, and @RequireRole. ```java @Controller("/users") public class UserController { @RequestMapping(value = "/", method = RequestMapping.Method.GET, description = "List all users") public ResponseEntity list() { ... } @RequestMapping(value = "/{id}", method = RequestMapping.Method.GET) public ResponseEntity getById(@PathVariable("id") long id) { ... } @RequestMapping(value = "/", method = RequestMapping.Method.POST) public ResponseEntity create(@RequestBody User user) { ... } @RequestMapping(value = "/{id}", method = RequestMapping.Method.DELETE) @RequireRole("ADMIN") public ResponseEntity delete(@PathVariable("id") long id) { ... } } ``` -------------------------------- ### Enable Development Mode Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Relax CORS and cookie policies for local development. This should be called before `start()`. ```java server.enableDevelopmentMode(); ``` -------------------------------- ### Initialize Fiber Server Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Instantiate a Fiber server, optionally enabling API documentation. Call configuration methods before starting the server. ```java FiberServer server = new FiberServer(8080); FiberServer server = new FiberServer(8080, true); ``` -------------------------------- ### Fiber Authentication Service Setup Source: https://github.com/w8fyz/fiber/blob/main/README.md Steps to set up a custom authentication service and register authenticators like CookieAuthenticator and BearerAuthenticator. ```java // 1. Implement AuthenticationService public class MyAuthService extends AuthenticationService { public MyAuthService(GenericRepository userRepo) { super(userRepo, "/auth"); // refresh token cookie path } } // 2. Register on the server server.setAuthService(new MyAuthService(userRepository)); // 3. Register authenticators server.getAuthResolver().registerAuthenticator(new CookieAuthenticator()); server.getAuthResolver().registerAuthenticator(new BearerAuthenticator()); ``` -------------------------------- ### GET /data with Auth Schemes Source: https://github.com/w8fyz/fiber/blob/main/README.md Example endpoint demonstrating support for multiple authentication schemes (Cookie and Bearer). ```APIDOC ## GET /data ### Description Example endpoint demonstrating support for multiple authentication schemes (Cookie and Bearer). ### Method GET ### Endpoint /data ### Parameters #### Query Parameters - **@AuthType** (enum) - Specifies allowed authentication schemes: `COOKIE`, `BEARER`. ### Response #### Success Response (200) - **User** (object) - The authenticated user object. #### Response Example ```json { "id": 1, "email": "user@example.com", "role": "admin" } ``` ``` -------------------------------- ### Session Service Setup Source: https://github.com/w8fyz/fiber/blob/main/README.md Configure the server-side session management by creating a GenericRepository for FiberSession and setting it in the server. Supports custom TTL. ```java GenericRepository sessionRepo = new GenericRepository<>(FiberSession.class); server.setSessionService(new SessionService(sessionRepo)); // or with custom TTL: new SessionService(sessionRepo, 30 * 24 * 60 * 60 * 1000L) // 30 days ``` -------------------------------- ### Setup Session Tracking Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Configure server-side session tracking by providing a repository for FiberSession objects. A custom Time-To-Live (TTL) can be specified. ```java GenericRepository sessionRepo = new GenericRepository<>(FiberSession.class); server.setSessionService(new SessionService(sessionRepo)); // Custom TTL: new SessionService(sessionRepo, 30 * 24 * 3600 * 1000L) ``` -------------------------------- ### Initialize and Configure FiberServer Source: https://context7.com/w8fyz/fiber/llms.txt This snippet demonstrates how to initialize a FiberServer on a specific port, enable development mode, configure CORS, CSRF protection, file upload limits, and register controllers. It also shows how to start the server and access generated API documentation. ```java import sh.fyz.fiber.FiberServer; import sh.fyz.fiber.core.security.cors.CorsService; import java.util.Arrays; public class Main { public static void main(String[] args) throws Exception { // Create server on port 8080 with API documentation enabled FiberServer server = new FiberServer(8080, true); // Enable development mode (relaxes security for local testing) server.enableDevelopmentMode(); // Configure CORS server.setCorsService(new CorsService() .addAllowedOrigin("http://localhost:3000") .addAllowedOrigin("https://*.example.com") .setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")) .setAllowedHeaders(Arrays.asList("Content-Type", "Authorization", "X-CSRF-TOKEN")) .setAllowCredentials(true) .setMaxAge(3600)); // Enable CSRF protection server.enableCSRFProtection(); // Set custom server header server.setServerHeader("MyApp/1.0"); // Configure file upload limits server.setMaxFileSize(50_000_000) // 50MB max file .setMaxRequestSize(100_000_000) // 100MB max request .setFileSizeThreshold(1_000_000); // 1MB memory threshold // Register controllers server.registerController(new UserController()); server.registerController(new AuthController()); // Start the server server.start(); // Documentation available at: // UI: http://localhost:8080/docs/ui // JSON: http://localhost:8080/docs/api } } ``` -------------------------------- ### Setup SessionService in Fiber Source: https://context7.com/w8fyz/fiber/llms.txt Configure the SessionService by providing a repository for FiberSession objects. Optionally, set a custom TTL in milliseconds for session expiration. ```java import sh.fyz.fiber.core.session.SessionService; import sh.fyz.fiber.core.session.FiberSession; import sh.fyz.architect.repositories.GenericRepository; // Setup session service GenericRepository sessionRepo = new GenericRepository<>(FiberSession.class); server.setSessionService(new SessionService(sessionRepo)); // Or with custom TTL (30 days): // new SessionService(sessionRepo, 30 * 24 * 60 * 60 * 1000L) ``` -------------------------------- ### Fiber Parameter Injection Examples Source: https://github.com/w8fyz/fiber/blob/main/README.md Illustrates various ways to inject parameters into controller methods using annotations like @Param, @PathVariable, and @RequestBody. ```java @RequestMapping(value = "/search", method = RequestMapping.Method.GET) public ResponseEntity search( @NotBlank @Param("q") String query, @Param(value = "page", required = false) int page) { ... } ``` -------------------------------- ### Basic Rate Limiting Source: https://github.com/w8fyz/fiber/blob/main/README.md Implement basic rate limiting with a fixed window, specifying the number of attempts and the time unit. This example limits to 5 attempts per 15 minutes per IP. ```java // Basic — 5 attempts per 15 minutes, per IP @RateLimit(attempts = 5, timeout = 15, unit = TimeUnit.MINUTES) @RequestMapping(value = "/login", method = RequestMapping.Method.POST) public ResponseEntity login(...) { ... } ``` -------------------------------- ### AuthenticationService Implementation Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Example of extending the AuthenticationService for custom user authentication logic, including overriding findUserByIdentifier for efficient database lookups and managing user cache. ```APIDOC ## AuthenticationService ### Description Provides a base class for handling user authentication, including credential validation, token generation, and cookie management. It supports caching for efficient user retrieval. ### Key Methods - `getUserById(Object id)`: Loads user from repository (Caffeine-cached, 30s TTL). - `findUserByIdentifer(String identifier)`: Override this for efficient DB lookup. Default loads all users. - `findByIdentifier(String identifier)`: Protected fallback that loads all users (avoid in production). - `validateCredentials(UserAuth user, String password)`: Validates user credentials using BCrypt. - `doesIdentifiersAlreadyExists(UserAuth user)`: Checks for uniqueness of user identifiers. - `generateToken(UserAuth user, HttpServletRequest req)`: Generates a JWT access token. - `validateToken(String token, HttpServletRequest req)`: Validates a JWT token. - `setAuthCookies(UserAuth user, req, resp)`: Sets access and refresh token cookies, and creates a session if configured. - `clearAuthCookies(req, resp)`: Clears authentication cookies and invalidates the current session. - `evictUser(Object id)`: Invalidates a single user from the cache. - `evictAllUsers()`: Invalidates the entire user cache. ### User Cache The `getUserById()` method is backed by a Caffeine cache with a 30s TTL and a maximum of 10,000 entries. Cache hits are served from memory, while misses hit the database. **IMPORTANT**: When updating user data outside of the `AuthenticationService`, you must manually call `evictUser(id)` to ensure cache consistency. ### Example Implementation ```java public class MyAuthService extends AuthenticationService { public MyAuthService(GenericRepository repo) { super(repo, "/auth"); // refresh token cookie path } @Override public UserAuth findUserByIdentifer(String identifier) { return repo.query().where("email", identifier).findFirst(); } } ``` ``` -------------------------------- ### Custom AuditLogService Implementation Source: https://github.com/w8fyz/fiber/blob/main/README.md Provides an example of how to create a custom AuditLogService by extending the base AuditLogService class. This allows for custom handling of audit log events, such as printing details to the console or persisting them to a database. ```APIDOC ## Custom AuditLogService ### Description Implement a custom `AuditLogService` to define how audit logs are processed. This example prints log details and custom data to the console. ### Usage ```java public class MyAuditLogService extends AuditLogService { @Override public void onAuditLog(AuditLog log) { System.out.println("[" + log.getAction() + "] " + log.getMethod() + " " + log.getUri()); System.out.println(" IP: " + log.getIp()); System.out.println(" Status: " + log.getStatus()); if (log.getCustomData() != null) { log.getCustomData().forEach((k, v) -> System.out.println(" " + k + ": " + v)); } } } server.setAuditLogService(new MyAuditLogService()); ``` ### AuditLog Object Fields - **timestamp** (Date) - The timestamp of the log event. - **ip** (string) - The IP address of the client. - **userAgent** (string) - The user agent string. - **method** (string) - The HTTP method. - **uri** (string) - The request URI. - **action** (string) - The action performed. - **status** (integer) - The HTTP status code. - **queryParams** (Map) - Query parameters. - **pathVariables** (Map) - Path variables. - **requestBody** (object) - The request body. - **parameters** (Map) - Request parameters. - **response** (object) - The response body. - **customData** (Map) - Custom data attached via `AuditContext`. - **rawLog** (string) - The raw log entry. ``` -------------------------------- ### GET /me with Session Information Source: https://github.com/w8fyz/fiber/blob/main/README.md Retrieves the authenticated user and their session details, including options to invalidate other sessions. ```APIDOC ## GET /me (with Session) ### Description Retrieves the authenticated user and their session details, including options to invalidate other sessions. ### Method GET ### Endpoint /me ### Parameters - **@AuthenticatedUser User user** - The authenticated user object. - **@CurrentSession FiberSession session** - The current session object. ### Response #### Success Response (200) - **user** (object) - The authenticated user object. - **sessions** (array) - A list of the user's active sessions. #### Response Example ```json { "user": { "id": 1, "email": "user@example.com", "role": "user" }, "sessions": [ { "id": "session_id_1", "ipAddress": "192.168.1.1", "createdAt": 1678886400000 } ] } ``` ``` -------------------------------- ### GET /auth/me Source: https://github.com/w8fyz/fiber/blob/main/README.md Retrieves the currently authenticated user's information. ```APIDOC ## GET /auth/me ### Description Retrieves the currently authenticated user's information. ### Method GET ### Endpoint /auth/me ### Response #### Success Response (200) - **User** (object) - The authenticated user object. #### Response Example ```json { "id": 1, "email": "user@example.com", "role": "admin" } ``` ``` -------------------------------- ### File Upload Endpoint Source: https://github.com/w8fyz/fiber/blob/main/README.md An example endpoint for handling file uploads. It specifies constraints on file size and allowed MIME types. ```APIDOC ## POST /upload ### Description Handles file uploads with specified size and MIME type restrictions. Supports chunked uploads and automatically cleans up incomplete uploads. ### Method POST ### Endpoint /upload ### Parameters #### Query Parameters - **uploadId** (string) - Optional - Identifier for chunked uploads. - **chunkIndex** (integer) - Optional - The index of the current chunk. - **totalChunks** (integer) - Optional - The total number of chunks. #### Request Body - **file** (UploadedFile) - Required - The file to upload. Constraints: `maxSize = 5,242,880` bytes, `allowedMimeTypes = {"image/jpeg", "image/png"}`. ### Response #### Success Response (200) - **filename** (string) - The original filename of the uploaded file. #### Response Example ```json { "filename": "example.jpg" } ``` ``` -------------------------------- ### Sliding Window Rate Limiting Source: https://github.com/w8fyz/fiber/blob/main/README.md Configure rate limiting using a sliding window for more accurate request counting. This example allows 100 requests per hour. ```java // Sliding window — more accurate counting than fixed window @RateLimit(attempts = 100, timeout = 1, unit = TimeUnit.HOURS, slidingWindow = true) @RequestMapping(value = "/api/search", method = RequestMapping.Method.GET) public ResponseEntity search(...) { ... } ``` -------------------------------- ### Setup OAuth2 Client Service for Authorization Server Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Configure Fiber to act as an OAuth2 authorization server by setting up the `OAuth2ClientService` with a repository for managing OAuth2 clients. ```java GenericRepository clientRepo = new GenericRepository<>(OAuth2Client.class); server.setOauthClientService(new OAuth2ClientService(clientRepo)); ``` -------------------------------- ### Per-User Rate Limiting Source: https://github.com/w8fyz/fiber/blob/main/README.md Implement rate limiting keyed by authenticated user ID instead of IP address. Falls back to IP if the user is not authenticated. This example limits to 10 requests per minute. ```java // Per-user — keyed by authenticated userId instead of IP @RateLimit(attempts = 10, timeout = 1, unit = TimeUnit.MINUTES, perUser = true) @RequestMapping(value = "/api/export", method = RequestMapping.Method.GET) public ResponseEntity export(@AuthenticatedUser User user) { ... } ``` -------------------------------- ### Shared Bucket Rate Limiting Source: https://github.com/w8fyz/fiber/blob/main/README.md Group multiple endpoints under the same rate limit using a shared key. This example applies a limit of 50 requests per hour to both /api/posts and /api/comments. ```java // Shared bucket — group multiple endpoints under the same limit @RateLimit(attempts = 50, timeout = 1, unit = TimeUnit.HOURS, key = "api-write") @RequestMapping(value = "/api/posts", method = RequestMapping.Method.POST) public ResponseEntity createPost(...) { ... } ``` ```java @RateLimit(attempts = 50, timeout = 1, unit = TimeUnit.HOURS, key = "api-write") @RequestMapping(value = "/api/comments", method = RequestMapping.Method.POST) public ResponseEntity createComment(...) { ... } ``` -------------------------------- ### Class-Level Rate Limiting Source: https://github.com/w8fyz/fiber/blob/main/README.md Apply rate limiting to all endpoints within a controller by annotating the class. This example limits all endpoints in HeavyController to 20 requests per minute. ```java // Class-level — applies to all endpoints in the controller @Controller("/api/heavy") @RateLimit(attempts = 20, timeout = 1, unit = TimeUnit.MINUTES) public class HeavyController { ... } ``` -------------------------------- ### Setup OAuth2 Social Login with Token Persistence Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Configure Fiber's OAuth2 service to use a repository for persisting provider tokens, enabling repeat logins to skip direct provider calls. Access and refresh tokens are encrypted at rest. ```java GenericRepository tokenRepo = new GenericRepository<>(UserOAuth2Token.class); UserOAuth2TokenService tokenService = new UserOAuth2TokenService(tokenRepo); server.setUserOAuth2TokenService(tokenService); OAuth2AuthenticationService oauthService = new MyOAuth2Service(authService, userRepo, tokenService); oauthService.registerProvider(new DiscordOAuth2Provider<>("clientId", "secret")); server.setOAuthService(oauthService); ``` -------------------------------- ### Configure and Send Email with EmailService Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Set up the EmailService with SMTP details and credentials. Then, construct an Email object with recipients, subject, HTML content, and template information before sending it via the email service. The sendEmail method returns a CompletableFuture. ```java EmailService emailService = new EmailService( "smtp.example.com", "noreply@example.com", 465, "username", "password", true, true); server.setEmailService(emailService); Email email = new Email(); email.setTo("user@example.com"); email.setSubject("Welcome!"); email.setHtmlContent("

Hello {name}!

"); email.setTemplatePath("templates/welcome.html"); email.setTemplateVariables(Map.of("name", "John")); FiberServer.get().getEmailService().sendEmail(email); // returns CompletableFuture ``` -------------------------------- ### Configure and Send Simple Email Source: https://context7.com/w8fyz/fiber/llms.txt Initialize the EmailService with SMTP details and credentials. Create an Email object, set recipients, subject, and content (plain text and/or HTML). ```java import sh.fyz.fiber.core.email.EmailService; import sh.fyz.fiber.core.email.Email; import sh.fyz.fiber.core.email.EmailAttachment; // Configure email service EmailService emailService = new EmailService( "smtp.example.com", // SMTP host "noreply@example.com", // From address 465, // Port "apikey", // Username "password", // Password true, // Use SSL true // Use TLS ); server.setEmailService(emailService); // Send simple email Email email = new Email(); email.setTo("user@example.com"); email.setSubject("Welcome to our platform!"); email.setContent("Hello! Welcome to our platform."); email.setHtmlContent("

Welcome!

Thank you for joining us.

"); // Async send returns CompletableFuture FiberServer.get().getEmailService().sendEmail(email) .thenRun(() -> System.out.println("Email sent successfully")) .exceptionally(e -> { System.err.println("Failed to send email: " + e.getMessage()); return null; }); ``` -------------------------------- ### Basic Rate Limit Configuration Source: https://context7.com/w8fyz/fiber/llms.txt Applies a fixed window rate limit of 5 attempts per 15 minutes, tracked per IP address. Ensure imports for RateLimit and TimeUnit are present. ```java import sh.fyz.fiber.core.security.annotations.RateLimit; import java.util.concurrent.TimeUnit; @Controller("/api") public class RateLimitedController { // Basic rate limit: 5 attempts per 15 minutes, per IP @RateLimit(attempts = 5, timeout = 15, unit = TimeUnit.MINUTES) @RequestMapping(value = "/login", method = RequestMapping.Method.POST) public ResponseEntity login(@RequestBody LoginRequest body) { // ... } } ``` -------------------------------- ### Fiber ResponseEntity Usage Source: https://github.com/w8fyz/fiber/blob/main/README.md Examples of using ResponseEntity to control HTTP responses, including status codes, headers, and content types. ```java ResponseEntity.ok(body) // 200 ResponseEntity.created(body) // 201 ResponseEntity.badRequest(body) // 400 ResponseEntity.unauthorized(body) // 401 ResponseEntity.notFound() // 404 ResponseEntity.noContent() // 204 ResponseEntity.serverError(body) // 500 // Custom status, headers, content type ResponseEntity.ok(imageBytes) .contentType("image/png") .header("Cache-Control", "max-age=3600"); ``` -------------------------------- ### Configure Email Service Source: https://github.com/w8fyz/fiber/blob/main/README.md Set up the email service with SMTP details, sender address, and authentication credentials. An Email object can be constructed with recipients, subject, and content, then sent asynchronously. ```java server.setEmailService(new EmailService( "smtp.example.com", "noreply@example.com", 465, "apikey", "password", true, true )); Email email = new Email(); email.setTo("user@example.com"); email.setSubject("Welcome"); email.setContent("Welcome to our platform!"); email.setHtmlContent("

Welcome!

"); FiberServer.get().getEmailService().sendEmail(email); // async (CompletableFuture) ``` -------------------------------- ### Enable API Documentation Source: https://github.com/w8fyz/fiber/blob/main/README.md Enable API documentation by passing 'true' as the second argument to the FiberServer constructor. Access the UI at /docs/ui and raw JSON at /docs/api. Endpoint descriptions can be added using the @RequestMapping(description = "...") annotation. ```java FiberServer server = new FiberServer(8080, true); ``` -------------------------------- ### Create User Controller in Java Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Defines a UserController with endpoints for listing, retrieving by ID, and creating users. Uses annotations for request mapping and parameter binding. ```java @Controller("/api/users") public class UserController { @RequestMapping(value = "/", method = RequestMapping.Method.GET, description = "List users") public ResponseEntity list() { return ResponseEntity.ok(userRepository.all()); } @RequestMapping(value = "/{id}", method = RequestMapping.Method.GET) public ResponseEntity getById(@PathVariable("id") long id) { User user = userRepository.findById(id); return user != null ? ResponseEntity.ok(user) : ResponseEntity.notFound(); } @RequestMapping(value = "/", method = RequestMapping.Method.POST) public ResponseEntity create(@RequestBody User user) { userRepository.save(user); return ResponseEntity.created(user); } } ``` -------------------------------- ### Get Authenticated User Endpoint Source: https://context7.com/w8fyz/fiber/llms.txt Implement an endpoint to retrieve the currently authenticated user's details. The @AuthenticatedUser annotation injects the user object directly into the method parameter. ```java @RequestMapping(value = "/me", method = RequestMapping.Method.GET) public ResponseEntity me(@AuthenticatedUser User user) { return ResponseEntity.ok(user); } ``` -------------------------------- ### Custom Rate Limit Error Message Source: https://context7.com/w8fyz/fiber/llms.txt Defines a custom message for rate limit exceeded responses. This example sets a limit of 3 attempts within 5 minutes for password resets. ```java @RateLimit(attempts = 3, timeout = 5, unit = TimeUnit.MINUTES, message = "Too many password reset attempts. Please wait.") @RequestMapping(value = "/password-reset", method = RequestMapping.Method.POST) public ResponseEntity passwordReset(@RequestBody Map body) { // ... } ``` -------------------------------- ### Create Logging Middleware in Java Source: https://context7.com/w8fyz/fiber/llms.txt Implement the `Middleware` interface to create custom interceptors. Lower priority values run earlier. Return `true` to continue processing, `false` to abort. ```java import sh.fyz.fiber.middleware.Middleware; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; public class LoggingMiddleware implements Middleware { @Override public int priority() { return 10; // Lower = runs earlier } @Override public boolean handle(HttpServletRequest request, HttpServletResponse response) { long startTime = System.currentTimeMillis(); // Log request System.out.printf("[%s] %s %s%n", java.time.Instant.now(), request.getMethod(), request.getRequestURI()); // Store start time for response logging request.setAttribute("startTime", startTime); return true; // Continue processing (false = abort request) } } ``` -------------------------------- ### Define Custom Roles with Permissions Source: https://context7.com/w8fyz/fiber/llms.txt Extend the Role class to define custom roles and their associated permissions. Initialize permissions and parent roles within the respective methods. Register these roles at application startup. ```java import sh.fyz.fiber.core.authentication.entities.Role; import sh.fyz.fiber.annotations.security.RequireRole; import sh.fyz.fiber.annotations.security.Permission; // Define roles with permissions public class AdminRole extends Role { public AdminRole() { super("admin"); } @Override protected void initializePermissions() { addPermission("users.create"); addPermission("users.delete"); addPermission("users.edit"); addPermission("system.config"); } @Override protected void initializeParentRoles() { // Admin inherits all user permissions addParentRole(new UserRole()); } } public class UserRole extends Role { public UserRole() { super("user"); } @Override protected void initializePermissions() { addPermission("profile.read"); addPermission("profile.edit"); } @Override protected void initializeParentRoles() {} } ``` -------------------------------- ### ResponseEntity Status Codes and Fluent API Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Demonstrates various static methods for creating ResponseEntity objects with different HTTP status codes. Also shows the fluent API for setting content type and headers. ```java ResponseEntity.ok(body) // 200 ResponseEntity.created(body) // 201 ResponseEntity.noContent() // 204 ResponseEntity.badRequest(body) // 400 ResponseEntity.unauthorized(body) // 401 ResponseEntity.forbidden(body) // 403 ResponseEntity.notFound() // 404 ResponseEntity.gone(body) // 410 ResponseEntity.tooManyRequest(body) // 429 ResponseEntity.serverError(body) // 500 // Fluent API ResponseEntity.ok(bytes).contentType("image/png").header("X-Custom", "value"); ``` -------------------------------- ### Implement Custom Timing Middleware Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Create a custom middleware by extending the Middleware interface and implementing the handle method. The priority determines execution order, with lower numbers running earlier. Returning false from handle aborts the request. ```java public class TimingMiddleware implements Middleware { @Override public int priority() { return 5; } // lower = runs earlier @Override public boolean handle(HttpServletRequest req, HttpServletResponse resp) { req.setAttribute("startTime", System.currentTimeMillis()); return true; // false would abort the request } } server.addMiddleware(new TimingMiddleware()); ``` -------------------------------- ### Email Service Configuration Source: https://github.com/w8fyz/fiber/blob/main/README.md Demonstrates how to configure and use the email service in Fiber, including sending emails with HTML content and template support. ```APIDOC ## Email Service ### Description Configure and send emails using Fiber's email service. Supports basic email sending, HTML content, and template-based emails with variable substitution. ### Configuration ```java server.setEmailService(new EmailService( "smtp.example.com", "noreply@example.com", 465, "apikey", "password", true, true )); ``` ### Sending an Email ```java Email email = new Email(); email.setTo("user@example.com"); email.setSubject("Welcome"); email.setContent("Welcome to our platform!"); email.setHtmlContent("

Welcome!

"); FiberServer.get().getEmailService().sendEmail(email); // async (CompletableFuture) ``` ### Template Support Supports template files with variable substitution (`{variable}`) and `@import` directives for partials. ``` -------------------------------- ### Register and Order Middleware in Java Source: https://context7.com/w8fyz/fiber/llms.txt Register custom middleware instances with the server. Middleware execution order is determined by their priority, with lower numbers running earlier. ```java // Register middleware server.addMiddleware(new ApiKeyMiddleware()); server.addMiddleware(new LoggingMiddleware()); // Middleware execution order (by priority): // 1. ApiKeyMiddleware (priority 5) // 2. LoggingMiddleware (priority 10) // 3. Built-in auth/CSRF middleware // 4. Endpoint handler ``` -------------------------------- ### API Documentation Generation Source: https://github.com/w8fyz/fiber/blob/main/README.md Details how to enable and access the auto-generated API documentation UI and raw JSON endpoint. ```APIDOC ## API Documentation Generation ### Description Enable automatic API documentation generation by passing `true` as the second argument to the `FiberServer` constructor. Access the UI and raw JSON endpoints. ### Enabling Documentation ```java FiberServer server = new FiberServer(8080, true); ``` ### Accessing Documentation - **UI**: `http://localhost:8080/docs/ui` - **Raw JSON**: `http://localhost:8080/docs/api` ### Adding Endpoint Descriptions Add descriptions to endpoints using the `@RequestMapping(description = "...")` annotation. ``` -------------------------------- ### Rate Limiting Annotations (Java) Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Configures rate limiting using annotations with different algorithms (fixed window, sliding window) and keying strategies (IP, user). State is managed in Caffeine caches. ```java // Basic — fixed window, IP-based @RateLimit(attempts = 10, timeout = 1, unit = TimeUnit.MINUTES) // Sliding window — more accurate for bursty traffic @RateLimit(attempts = 100, timeout = 1, unit = TimeUnit.HOURS, slidingWindow = true) // Per-user — falls back to IP if unauthenticated @RateLimit(attempts = 10, timeout = 5, unit = TimeUnit.MINUTES, perUser = true) // Shared bucket across endpoints @RateLimit(attempts = 50, timeout = 1, unit = TimeUnit.HOURS, key = "writes") // Class-level — applies to all methods in the controller @Controller("/api/heavy") @RateLimit(attempts = 20, timeout = 1, unit = TimeUnit.MINUTES) public class HeavyController { ... } ``` -------------------------------- ### POST /auth/login Source: https://github.com/w8fyz/fiber/blob/main/README.md Handles user login by validating credentials and setting authentication cookies. ```APIDOC ## POST /auth/login ### Description Handles user login by validating credentials and setting authentication cookies. ### Method POST ### Endpoint /auth/login ### Parameters #### Request Body - **identifier** (string) - Required - The user's email or username. - **password** (string) - Required - The user's password. ### Request Example ```json { "identifier": "user@example.com", "password": "your_password" } ``` ### Response #### Success Response (200) - **message** (string) - Indicates successful login. #### Response Example ```json { "message": "Logged in" } ``` #### Error Response (401) - **message** (string) - Indicates invalid credentials. #### Error Response Example ```json { "message": "Invalid credentials" } ``` ``` -------------------------------- ### Login Endpoint Source: https://github.com/w8fyz/fiber/blob/main/README.md Implement a POST endpoint for user login. It validates credentials against the AuthenticationService and sets authentication cookies upon success. Rate limiting is applied. ```java import io.fiber.core.auth.annotation.AuthenticatedUser; import io.fiber.core.auth.annotation.AuthScheme; import io.fiber.core.auth.annotation.AuthType; import io.fiber.core.auth.annotation.RateLimit; import io.fiber.core.auth.annotation.RequireRole; import io.fiber.core.controller.Controller; import io.fiber.core.controller.RequestMapping; import io.fiber.core.controller.ResponseEntity; import io.fiber.core.server.FiberServer; import io.fiber.core.session.FiberSession; import io.fiber.core.session.SessionService; import io.kokuwa.architect.core.auth.UserAuth; import io.kokuwa.architect.core.repository.GenericRepository; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; @Controller("/auth") public class AuthController { @RequestMapping(value = "/login", method = RequestMapping.Method.POST) @RateLimit(attempts = 5, timeout = 15, unit = TimeUnit.MINUTES) public ResponseEntity login(@RequestBody Map body, HttpServletRequest req, HttpServletResponse resp) { AuthenticationService auth = FiberServer.get().getAuthService(); UserAuth user = auth.findUserByIdentifer(body.get("identifier")); if (user == null || !auth.validateCredentials(user, body.get("password"))) { return ResponseEntity.unauthorized("Invalid credentials"); } auth.setAuthCookies(user, req, resp); // sets access_token + refresh_token cookies return ResponseEntity.ok(Map.of("message", "Logged in")); } @RequestMapping(value = "/logout", method = RequestMapping.Method.POST) public ResponseEntity logout(HttpServletRequest req, HttpServletResponse resp) { FiberServer.get().getAuthService().clearAuthCookies(req, resp); return ResponseEntity.ok("Logged out"); } @RequestMapping(value = "/me", method = RequestMapping.Method.GET) public ResponseEntity me(@AuthenticatedUser User user) { return ResponseEntity.ok(user); } } ``` -------------------------------- ### File Upload Manager Singleton Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Manages chunked file uploads, tracks progress, and handles automatic cleanup of incomplete uploads. Implemented as a Singleton. ```java public class FileUploadManager ``` -------------------------------- ### Login Endpoint Implementation Source: https://context7.com/w8fyz/fiber/llms.txt Implement the login endpoint to handle user credentials, validate them using the AuthenticationService, and set authentication cookies upon successful login. This endpoint is rate-limited. ```java // 4. Auth controller implementation @Controller("/auth") public class AuthController { @RequestMapping(value = "/login", method = RequestMapping.Method.POST) @RateLimit(attempts = 5, timeout = 15, unit = TimeUnit.MINUTES) public ResponseEntity login(@RequestBody Map body, HttpServletRequest req, HttpServletResponse resp) { AuthenticationService auth = FiberServer.get().getAuthService(); UserAuth user = auth.findUserByIdentifer(body.get("identifier")); if (user == null || !auth.validateCredentials(user, body.get("password"))) { return ResponseEntity.unauthorized("Invalid credentials"); } // Sets access_token + refresh_token cookies auth.setAuthCookies(user, req, resp); return ResponseEntity.ok(Map.of("message", "Logged in")); } @RequestMapping(value = "/logout", method = RequestMapping.Method.POST) public ResponseEntity logout(HttpServletRequest req, HttpServletResponse resp) { FiberServer.get().getAuthService().clearAuthCookies(req, resp); return ResponseEntity.ok("Logged out"); } @RequestMapping(value = "/refresh", method = RequestMapping.Method.POST) public ResponseEntity refresh(HttpServletRequest req, HttpServletResponse resp) { String refreshToken = getCookie(req, "refresh_token"); AuthenticationService auth = FiberServer.get().getAuthService(); UserAuth user = auth.refreshAuthCookies(refreshToken, req, resp); if (user == null) { auth.clearAuthCookies(req, resp); return ResponseEntity.unauthorized("Session expired"); } return ResponseEntity.ok(Map.of("message", "Token refreshed")); } @RequestMapping(value = "/me", method = RequestMapping.Method.GET) public ResponseEntity me(@AuthenticatedUser User user) { return ResponseEntity.ok(user); } } ``` -------------------------------- ### Implement Custom Authentication Service Source: https://context7.com/w8fyz/fiber/llms.txt Extend the AuthenticationService class to handle your specific user authentication logic. Override findUserByIdentifer for efficient database lookups. Ensure your User entity implements the UserAuth interface. ```java import sh.fyz.fiber.core.authentication.AuthenticationService; import sh.fyz.fiber.core.authentication.entities.UserAuth; import sh.fyz.architect.repositories.GenericRepository; // 1. Implement AuthenticationService for your User entity public class MyAuthService extends AuthenticationService { public MyAuthService(GenericRepository userRepo) { super(userRepo, "/auth"); // refresh token cookie path } // Override for efficient database lookup (default loads all users) @Override public UserAuth findUserByIdentifer(String identifier) { return userRepository.query() .where("email", identifier) .findFirst(); } } ``` -------------------------------- ### Send Email with Attachments Source: https://context7.com/w8fyz/fiber/llms.txt Create an Email object and use the addAttachment method with an EmailAttachment instance, specifying the file and its desired name in the email. ```java import sh.fyz.fiber.core.email.EmailService; import sh.fyz.fiber.core.email.Email; import sh.fyz.fiber.core.email.EmailAttachment; // Email with attachments Email invoiceEmail = new Email("customer@example.com", "Your Invoice"); invoiceEmail.setContent("Please find your invoice attached."); invoiceEmail.addAttachment(new EmailAttachment( new File("/invoices/INV-2024-001.pdf"), "invoice.pdf" )); emailService.sendEmail(invoiceEmail); ``` -------------------------------- ### RouterServlet for Route Handling Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md The main servlet for routing requests. Implements O(1) static route lookup and linear scan for dynamic routes. ```java public class RouterServlet extends HttpServlet ``` -------------------------------- ### Send Email with HTML Template and Variables Source: https://context7.com/w8fyz/fiber/llms.txt Set the email template path and provide dynamic data using addTemplateVariable. The template engine will render the HTML with these values. ```java import sh.fyz.fiber.core.email.EmailService; import sh.fyz.fiber.core.email.Email; import sh.fyz.fiber.core.email.EmailAttachment; // Email with template Email templateEmail = new Email(); templateEmail.setTo("user@example.com"); templateEmail.setSubject("Order Confirmation"); templateEmail.setTemplatePath("/templates/order-confirmation.html"); templateEmail.addTemplateVariable("customerName", "John Doe"); templateEmail.addTemplateVariable("orderNumber", "ORD-12345"); templateEmail.addTemplateVariable("total", "$99.99"); // Template file (/templates/order-confirmation.html): // // //

Thank you, {customerName}!

//

Your order {orderNumber} totaling {total} has been confirmed.

// // emailService.sendEmail(templateEmail); ``` -------------------------------- ### Register and Handle Challenges Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Register a challenge with a callback that defines success and failure responses. The system exposes a single verification endpoint for clients to POST their responses to. The challenge ID is part of the URL. ```java Challenge registered = server.registerChallenge(challenge, new ChallengeCallback() { @Override public ResponseEntity onSuccess(Challenge c, HttpServletRequest req, HttpServletResponse resp) { return ResponseEntity.ok(Map.of("verified", true)); } @Override public ResponseEntity onFailure(Challenge c, String reason, HttpServletRequest req, HttpServletResponse resp) { return ResponseEntity.badRequest(Map.of("error", reason)); } }); ``` -------------------------------- ### Implement Custom Middleware Source: https://github.com/w8fyz/fiber/blob/main/README.md Create custom middleware by implementing the Middleware interface and overriding the handle method. Middleware can intercept requests and responses, with execution order determined by priority. Return true to continue processing, false to abort. ```java public class LoggingMiddleware implements Middleware { @Override public int priority() { return 10; } @Override public boolean handle(HttpServletRequest req, HttpServletResponse resp) { System.out.println(req.getMethod() + " " + req.getRequestURI()); return true; // continue processing (false = abort) } } server.addMiddleware(new LoggingMiddleware()); ``` -------------------------------- ### Define User and Admin Roles Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Define custom roles by extending the base Role class and implementing `initializePermissions` and `initializeParentRoles`. UserRole inherits permissions from Role, while AdminRole inherits from UserRole. ```java public class UserRole extends Role { public UserRole() { super("user"); } @Override public void initializePermissions() { addPermission("profile.view"); addPermission("profile.edit"); } @Override public void initializeParentRoles() {} } public class AdminRole extends Role { public AdminRole() { super("admin"); } @Override public void initializePermissions() { addPermission("users.manage"); } @Override public void initializeParentRoles() { addParentRole(new UserRole()); // inherits all "user" permissions } } ``` -------------------------------- ### Set Password Policy Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Configure password strength requirements at startup using UserFieldUtil.setPasswordPolicy. This validation runs automatically when setPassword() is called. ```java UserFieldUtil.setPasswordPolicy(12, true, true); // min 12 chars, require uppercase, require digit ``` -------------------------------- ### UploadedFile Wrapper Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md A wrapper class for uploaded files, providing methods to move the file, clean it up, and access its input stream. ```java public class UploadedFile ``` -------------------------------- ### Register Custom Audit Service in Java Source: https://context7.com/w8fyz/fiber/llms.txt Set the custom `AuditLogService` implementation on the server to enable your customized audit logging. ```java // Register custom audit service server.setAuditLogService(new MyAuditLogService(auditRepo)); ``` -------------------------------- ### Register Roles and Protect Endpoints Source: https://context7.com/w8fyz/fiber/llms.txt Register your custom role classes with the server's role registry at startup. Use the @RequireRole annotation on controllers or individual methods to enforce access control. Specific permissions can be checked using the @Permission annotation. ```java // Register roles at startup server.getRoleRegistry().registerRoleClasses(AdminRole.class, UserRole.class); // Protect endpoints with @RequireRole @Controller("/admin") @RequireRole("admin") // All endpoints in this controller require admin role public class AdminController { @RequestMapping(value = "/stats", method = RequestMapping.Method.GET) public ResponseEntity getStats() { return ResponseEntity.ok(statsService.getSystemStats()); } @RequestMapping(value = "/users/{id}", method = RequestMapping.Method.DELETE) @Permission("users.delete") // Also check specific permission public ResponseEntity deleteUser(@PathVariable("id") long id) { userRepository.delete(id); return ResponseEntity.ok("User deleted"); } } // Mixed access control @Controller("/api") public class ApiController { @RequestMapping(value = "/public", method = RequestMapping.Method.GET) public ResponseEntity publicEndpoint() { return ResponseEntity.ok("Anyone can access this"); } @RequestMapping(value = "/protected", method = RequestMapping.Method.GET) @RequireRole({"user", "admin"}) // Either role can access public ResponseEntity protectedEndpoint(@AuthenticatedUser User user) { return ResponseEntity.ok("Hello " + user.getEmail()); } } ``` -------------------------------- ### Password Policy Configuration Source: https://github.com/w8fyz/fiber/blob/main/FIBER-SKILL.md Information on configuring password strength requirements for user authentication. ```APIDOC ### Password Policy Password strength requirements can be configured at application startup. #### Configuration Example ```java UserFieldUtil.setPasswordPolicy(12, true, true); // min 12 chars, require uppercase, require digit ``` #### Default Policy - Minimum 8 characters. - No uppercase or digit requirement. Password validation automatically runs when the `setPassword()` method is called. ``` -------------------------------- ### Implement Custom AuditLogService in Java Source: https://context7.com/w8fyz/fiber/llms.txt Extend `AuditLogService` to customize audit logging behavior. The `onAuditLog` method receives all captured log data, allowing persistence to databases or sending to logging systems. ```java import sh.fyz.fiber.core.security.logging.AuditLogService; import sh.fyz.fiber.core.security.logging.AuditContext; import java.util.Map; // Custom AuditLogService implementation public class MyAuditLogService extends AuditLogService { private final AuditRepository auditRepo; public MyAuditLogService(AuditRepository auditRepo) { this.auditRepo = auditRepo; } @Override public void onAuditLog(sh.fyz.fiber.core.security.logging.AuditLog log) { // Log to console System.out.printf("[AUDIT] %s | %s %s | IP: %s | Status: %d%n", log.getAction(), log.getMethod(), log.getUri(), log.getIp(), log.getStatus()); // Access all log data long timestamp = log.getTimestamp(); String userAgent = log.getUserAgent(); Map queryParams = log.getQueryParams(); Map pathVariables = log.getPathVariables(); Object requestBody = log.getRequestBody(); Map customData = log.getCustomData(); // Persist to database, send to ELK, etc. AuditEntry entry = new AuditEntry(); entry.setAction(log.getAction()); entry.setTimestamp(timestamp); entry.setIpAddress(log.getIp()); entry.setPayload(JsonUtil.toJson(customData)); auditRepo.save(entry); } } ```