From b73241cb2ba4a0430b4fe295320e0a584835fe3d Mon Sep 17 00:00:00 2001 From: Relism Date: Fri, 28 Feb 2025 16:24:15 +0000 Subject: [PATCH] deploy: 55cc97e4fc6d9aea9364f981f77007a9b5db7296 --- 404.html | 2 +- ...ler-default-implementations.md.ki9D2CCK.js | 117 ++++++++++++++++++ ...efault-implementations.md.ki9D2CCK.lean.js | 117 ++++++++++++++++++ ...e-concepts_request-response.md.BuTSfkDO.js | 67 ++++++++++ ...cepts_request-response.md.BuTSfkDO.lean.js | 67 ++++++++++ ...core-concepts_server-router.md.Dpvzqe12.js | 24 ++++ ...concepts_server-router.md.Dpvzqe12.lean.js | 24 ++++ flash/advanced/fullstack-development.html | 2 +- .../handler-default-implementations.html | 6 +- flash/core-concepts/handlers.html | 2 +- flash/core-concepts/request-handler.html | 2 +- flash/core-concepts/request-response.html | 10 +- flash/core-concepts/server-router.html | 6 +- flash/core-concepts/websockets.html | 2 +- flash/file-serving/dynamic-file-server.html | 2 +- flash/file-serving/static-file-server.html | 2 +- flash/index.html | 2 +- flash/introduction/installation.html | 2 +- hashmap.json | 2 +- index.html | 2 +- mobot/index.html | 2 +- serverlibraries/index.html | 2 +- 22 files changed, 440 insertions(+), 24 deletions(-) create mode 100644 assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.js create mode 100644 assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.lean.js create mode 100644 assets/flash_core-concepts_request-response.md.BuTSfkDO.js create mode 100644 assets/flash_core-concepts_request-response.md.BuTSfkDO.lean.js create mode 100644 assets/flash_core-concepts_server-router.md.Dpvzqe12.js create mode 100644 assets/flash_core-concepts_server-router.md.Dpvzqe12.lean.js diff --git a/404.html b/404.html index 544946b..5dadf5c 100644 --- a/404.html +++ b/404.html @@ -17,7 +17,7 @@
- + \ No newline at end of file diff --git a/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.js b/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.js new file mode 100644 index 0000000..98c956f --- /dev/null +++ b/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.js @@ -0,0 +1,117 @@ +import{_ as i,c as a,a0 as n,o as t}from"./chunks/framework.p2VkXzrt.js";const e="/assets/hdichain.FX-X2Mhu.png",o=JSON.parse('{"title":"⚡ Handler Default Implementations (HDI)","description":"","frontmatter":{"banner_title":"Flash - Handler Default Implementations","banner_description":"Leverage HDIs for cleaner and more maintainable route logic.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-advanced-handler-default-implementations.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-advanced-handler-default-implementations.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/advanced/handler-default-implementations.md","filePath":"flash/advanced/handler-default-implementations.md"}'),h={name:"flash/advanced/handler-default-implementations.md"};function l(p,s,k,r,d,E){return t(),a("div",null,s[0]||(s[0]=[n(`

⚡ Handler Default Implementations (HDI)

Handler Default Implementations (HDIs) provide an elegant way to standardize common behaviors across multiple request handlers. By defining base handlers that extend RequestHandler (or chaining multiple base handlers together), you can modularize logic for common tasks like authentication, user data retrieval, and rate limiting.

HDIs are designed using the Chain of Responsibility pattern, making it easy to handle requests with layered logic.

🔗 How It Works

Instead of repeating the same logic in each handler, create abstract handler classes that define common functionality. Your handler implementations then extend these base classes, inheriting the shared behavior while implementing the request-specific logic.

Semantics of an HDI

Creating an HDI is simple, but it's useful to follow some guidelines for clarity and maintainability:

  1. Base HDI Class:

    • Extends: The base HDI class should extend RequestHandler.
    • Constructor: The constructor must call the super constructor with Request and Response objects.
    • Override: Override the handle method to include common behavior. The handle method should return the response to the client and should call the Abstract Handler Method, which is implemented by the handler or next HDI in the chain.
      java
      @Override
      +public Object handle() {
      +    // Common logic here, then call the abstract method
      +    return handleCustom();
      +}
    • Abstract Handler Method: Define an abstract method that must be implemented by the handler to provide custom logic. It should look like this:
      java
      protected abstract Object handleCustom();
    • Protected Fields: If needed, declare protected fields in the base class to pass data between handlers in the chain.

      INFO

      Protected fields are accessible to the handler implementation inside the Abstract Handler Method. Example HDI :

      java
      public abstract class MyHDI extends RequestHandler {
      +    protected String data; 
      +    public BaseHandler(Request req, Response res) {
      +        super(req, res);
      +    }
      +    @Override
      +    public Object handle() {
      +        data = "Some data"; // Set the data
      +        return handleCustom();
      +    }
      +    protected abstract Object handleCustom();
      +}

      Example Handler Implementation :

      java
      public class MyHandler extends MyHDI {
      +    public MyHandler(Request req, Response res) {
      +        super(req, res);
      +    }
      +    @Override
      +    protected Object handleCustom() {
      +        // The data is accessible here
      +        System.out.println(data);
      +        return "Response";
      +    }
      +}
  2. Handler Implementation:

    • Extends: The handler should extend the HDI class (or be the final handler in the chain).
    • Constructor: The constructor should call the super constructor with Request and Response objects.
    • Implement: Implement the Abstract Handler Method from the HDI.
    • Response Logic: The response logic should be in the abstract method, and its return value is sent to the client.
      java
      @Override
      +protected Object handleCustom() {
      +      // Custom logic here
      +      return "Response";
      +}
    • Protected Fields: The handler implementation can access data from the HDI using the protected fields, inside the Abstract Handler Method.

🛠 Example: API Key Authentication

Now let's go over a simple example to demonstrate how HDIs work. Imagine you need to authenticate API requests by checking an API key. You can create an abstract APIKeyProtectedHandler that extends RequestHandler and handles the API key authentication:

java
public abstract class APIKeyProtectedHandler extends RequestHandler {
+    protected String apiKey;
+
+    public APIKeyProtectedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        apiKey = req.header("X-API-Key");
+
+        if (apiKey == null || !isValidApiKey(apiKey)) {
+            res.status(403);
+            res.type("application/json");
+            return "{\\"error\\":\\"Invalid API Key\\"}";
+        }
+
+        return handleAuthorized();
+    }
+
+    protected abstract Object handleAuthorized();
+
+    private boolean isValidApiKey(String key) {
+        // Implement key validation logic, e.g., checking against a database
+        return true;
+    }
+}

Now, your API handler implementation only need to extend APIKeyProtectedHandler, ensuring every request has a valid API key before executing its logic:

java
@RouteInfo(endpoint = "/data", method = HttpMethod.GET)
+public class GetDataHandler extends APIKeyProtectedHandler {
+    public GetDataHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleAuthorized() {
+        res.type("application/json");
+        return "{\\"data\\":\\"Your API response here\\"}";
+    }
+}

🏗️ Chaining HDIs for Modular Logic

HDI Chain

HDIs can be chained together to create multiple layers of logic. For example, if you need to authenticate a user and fetch their data from a database, you can create two HDIs:

java
public abstract class ProtectedHandler extends RequestHandler {
+    protected String authToken;
+
+    public ProtectedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        authToken = req.header("Authorization");
+        if (authToken == null || !isValidToken(authToken)) {
+            res.status(401);
+            res.type("application/json");
+            return "{\\"error\\":\\"Unauthorized\\"}";
+        }
+        return handleAuthenticated();
+    }
+
+    protected abstract Object handleAuthenticated();
+}
java
public abstract class AuthenticatedHandler extends ProtectedHandler {
+    protected User user;
+    private String authToken; // inherited from ProtectedHandler
+
+    public AuthenticatedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleAuthenticated() {
+        user = getUserFromDatabase(authToken);
+        if (user == null) {
+            res.status(403);
+            res.type("application/json");
+            return "{\\"error\\":\\"User not found\\"}";
+        }
+        return handleWithUser();
+    }
+
+    protected abstract Object handleWithUser();
+}
java
@RouteInfo(endpoint = "/profile", method = HttpMethod.GET)
+public class UserProfileHandler extends AuthenticatedHandler {
+    public UserProfileHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleWithUser() {
+        res.type("application/json");
+        return "{\\"username\\":\\"" + user.getUsername() + "\\"}";
+    }
+}
`,22)]))}const y=i(h,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.lean.js b/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.lean.js new file mode 100644 index 0000000..98c956f --- /dev/null +++ b/assets/flash_advanced_handler-default-implementations.md.ki9D2CCK.lean.js @@ -0,0 +1,117 @@ +import{_ as i,c as a,a0 as n,o as t}from"./chunks/framework.p2VkXzrt.js";const e="/assets/hdichain.FX-X2Mhu.png",o=JSON.parse('{"title":"⚡ Handler Default Implementations (HDI)","description":"","frontmatter":{"banner_title":"Flash - Handler Default Implementations","banner_description":"Leverage HDIs for cleaner and more maintainable route logic.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-advanced-handler-default-implementations.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-advanced-handler-default-implementations.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/advanced/handler-default-implementations.md","filePath":"flash/advanced/handler-default-implementations.md"}'),h={name:"flash/advanced/handler-default-implementations.md"};function l(p,s,k,r,d,E){return t(),a("div",null,s[0]||(s[0]=[n(`

⚡ Handler Default Implementations (HDI)

Handler Default Implementations (HDIs) provide an elegant way to standardize common behaviors across multiple request handlers. By defining base handlers that extend RequestHandler (or chaining multiple base handlers together), you can modularize logic for common tasks like authentication, user data retrieval, and rate limiting.

HDIs are designed using the Chain of Responsibility pattern, making it easy to handle requests with layered logic.

🔗 How It Works

Instead of repeating the same logic in each handler, create abstract handler classes that define common functionality. Your handler implementations then extend these base classes, inheriting the shared behavior while implementing the request-specific logic.

Semantics of an HDI

Creating an HDI is simple, but it's useful to follow some guidelines for clarity and maintainability:

  1. Base HDI Class:

    • Extends: The base HDI class should extend RequestHandler.
    • Constructor: The constructor must call the super constructor with Request and Response objects.
    • Override: Override the handle method to include common behavior. The handle method should return the response to the client and should call the Abstract Handler Method, which is implemented by the handler or next HDI in the chain.
      java
      @Override
      +public Object handle() {
      +    // Common logic here, then call the abstract method
      +    return handleCustom();
      +}
    • Abstract Handler Method: Define an abstract method that must be implemented by the handler to provide custom logic. It should look like this:
      java
      protected abstract Object handleCustom();
    • Protected Fields: If needed, declare protected fields in the base class to pass data between handlers in the chain.

      INFO

      Protected fields are accessible to the handler implementation inside the Abstract Handler Method. Example HDI :

      java
      public abstract class MyHDI extends RequestHandler {
      +    protected String data; 
      +    public BaseHandler(Request req, Response res) {
      +        super(req, res);
      +    }
      +    @Override
      +    public Object handle() {
      +        data = "Some data"; // Set the data
      +        return handleCustom();
      +    }
      +    protected abstract Object handleCustom();
      +}

      Example Handler Implementation :

      java
      public class MyHandler extends MyHDI {
      +    public MyHandler(Request req, Response res) {
      +        super(req, res);
      +    }
      +    @Override
      +    protected Object handleCustom() {
      +        // The data is accessible here
      +        System.out.println(data);
      +        return "Response";
      +    }
      +}
  2. Handler Implementation:

    • Extends: The handler should extend the HDI class (or be the final handler in the chain).
    • Constructor: The constructor should call the super constructor with Request and Response objects.
    • Implement: Implement the Abstract Handler Method from the HDI.
    • Response Logic: The response logic should be in the abstract method, and its return value is sent to the client.
      java
      @Override
      +protected Object handleCustom() {
      +      // Custom logic here
      +      return "Response";
      +}
    • Protected Fields: The handler implementation can access data from the HDI using the protected fields, inside the Abstract Handler Method.

🛠 Example: API Key Authentication

Now let's go over a simple example to demonstrate how HDIs work. Imagine you need to authenticate API requests by checking an API key. You can create an abstract APIKeyProtectedHandler that extends RequestHandler and handles the API key authentication:

java
public abstract class APIKeyProtectedHandler extends RequestHandler {
+    protected String apiKey;
+
+    public APIKeyProtectedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        apiKey = req.header("X-API-Key");
+
+        if (apiKey == null || !isValidApiKey(apiKey)) {
+            res.status(403);
+            res.type("application/json");
+            return "{\\"error\\":\\"Invalid API Key\\"}";
+        }
+
+        return handleAuthorized();
+    }
+
+    protected abstract Object handleAuthorized();
+
+    private boolean isValidApiKey(String key) {
+        // Implement key validation logic, e.g., checking against a database
+        return true;
+    }
+}

Now, your API handler implementation only need to extend APIKeyProtectedHandler, ensuring every request has a valid API key before executing its logic:

java
@RouteInfo(endpoint = "/data", method = HttpMethod.GET)
+public class GetDataHandler extends APIKeyProtectedHandler {
+    public GetDataHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleAuthorized() {
+        res.type("application/json");
+        return "{\\"data\\":\\"Your API response here\\"}";
+    }
+}

🏗️ Chaining HDIs for Modular Logic

HDI Chain

HDIs can be chained together to create multiple layers of logic. For example, if you need to authenticate a user and fetch their data from a database, you can create two HDIs:

java
public abstract class ProtectedHandler extends RequestHandler {
+    protected String authToken;
+
+    public ProtectedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        authToken = req.header("Authorization");
+        if (authToken == null || !isValidToken(authToken)) {
+            res.status(401);
+            res.type("application/json");
+            return "{\\"error\\":\\"Unauthorized\\"}";
+        }
+        return handleAuthenticated();
+    }
+
+    protected abstract Object handleAuthenticated();
+}
java
public abstract class AuthenticatedHandler extends ProtectedHandler {
+    protected User user;
+    private String authToken; // inherited from ProtectedHandler
+
+    public AuthenticatedHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleAuthenticated() {
+        user = getUserFromDatabase(authToken);
+        if (user == null) {
+            res.status(403);
+            res.type("application/json");
+            return "{\\"error\\":\\"User not found\\"}";
+        }
+        return handleWithUser();
+    }
+
+    protected abstract Object handleWithUser();
+}
java
@RouteInfo(endpoint = "/profile", method = HttpMethod.GET)
+public class UserProfileHandler extends AuthenticatedHandler {
+    public UserProfileHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    protected Object handleWithUser() {
+        res.type("application/json");
+        return "{\\"username\\":\\"" + user.getUsername() + "\\"}";
+    }
+}
`,22)]))}const y=i(h,[["render",l]]);export{o as __pageData,y as default}; diff --git a/assets/flash_core-concepts_request-response.md.BuTSfkDO.js b/assets/flash_core-concepts_request-response.md.BuTSfkDO.js new file mode 100644 index 0000000..c808483 --- /dev/null +++ b/assets/flash_core-concepts_request-response.md.BuTSfkDO.js @@ -0,0 +1,67 @@ +import{_ as i,c as e,a0 as a,o as t}from"./chunks/framework.p2VkXzrt.js";const c=JSON.parse('{"title":"📥 Request and Response","description":"","frontmatter":{"banner_title":"Flash - Request and Response","banner_description":"Unlock the power of the Request and Response objects in Flash.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-core-concepts-request-response.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-core-concepts-request-response.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/core-concepts/request-response.md","filePath":"flash/core-concepts/request-response.md"}'),n={name:"flash/core-concepts/request-response.md"};function h(l,s,p,d,k,r){return t(),e("div",null,s[0]||(s[0]=[a(`

📥 Request and Response

Generally speaking, in an HTTP request-response cycle, the client sends a request to the server, and the server generates a response based on the request. In this section, we illustrate the Request and Response objects in Flash, which are used to interact with the request data and generate responses. We will learn to read and interpret the request data, and model the correct response to send back to the client.

Request and Response Objects

The Request and Response objects are passed to the handler constructor and provide access to the request data and response methods. Under the hood, these objects are provided by the RouteController during the registration stage of the handler, and they are continously updated for each request on that specific handler's instance, but for now, you can consider them as magic.

These objects are a very powerful tool to interact with the lifecycle of the server's response, and they provide a wide range of methods that makes our lives as developers easier.

RequestHandler context

Inside a RequestHandler class, you can access the Request and Response objects inside the handle method by simply typing req and res, respectively. You can use the methods provided by these objects both outside of a handler, and inside of it, to interact with the request and response objects. Although, the advantages of being inside a handler are that Flash supports out-of-the-box methods that can significantly clean up your code and improve the overall readability of your handlers.

Specifically, the ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile objects are used to get the expected properties of the request, and they are used by Flash to validate the request data before the handle method is even executed.

The developer can then simply assume that all the expected parameters are present and valid, without having to write a single line of validation code: Flash will do it for you.

The three objects mentioned above are fairly similar in their usage, providing getter methods which safely return the data in the expected format and type, thanks to Flash's built-in validation and casting system.

NOTE

Flash will take care of informing the client of any missing or invalid parameters, parameters that are not in the expected format, or any other kind of error that might occur during the validation process.

REMEMBER

The ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile instances are ONLY supposed to be retrieved by calling the respective expectedRequestParameter(), expectedBodyField(), and expectedBodyFile() methods INSIDE of the super constructor of your handler class.

Example Usage

Click to expand

The ExpectedRequestParameter object is used to get the expected parameters of the request. You can use the getter methods to safely get the parameter value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the parameter to the expected type.

java
@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    // Store the expected parameter in a private field
+    private final ExpectedRequestParameter myExpectedReqParam;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected parameter "myParam", and optionally provide a description
+        myExpectedReqParam = expectedRequestParameter("myParam", "A description of the parameter");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Safely get the parameter value as a String
+        String myParamValue = myExpectedReqParam.getString();
+        
+        // Return the response to the client
+        return "Hello, " + myParamValue + "!";
+    }
+}

Visiting /hello?myParam=John from your browser, will return Hello, John!.

Click to expand

The ExpectedBodyField object is used to get the expected fields of the request body. You can use the getter methods to safely get the field value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the field to the expected type.

java
@RouteInfo(endpoint = "/helloBody", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    // Store the expected field in a private field
+    private final ExpectedBodyField myExpectedBodyField;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected field "myField", and optionally provide a description
+        myExpectedBodyField = expectedBodyField("myField", "A description of the field");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Safely get the field value as a String
+        String myFieldValue = myExpectedBodyField.getString();
+        
+        // Return the response to the client
+        return "Field value: " + myFieldValue;
+    }
+}

This time, since we are expecting a field in the request body, using our browser would not be enough to test the handler. Instead, you can use a tool like Postman to send a GET request to /helloBody with a multipart form data body containing a field named myField. You should receive a response like Field value: <value>.

Click to expand

The ExpectedBodyFile object is used to get the expected files of the request body. The methods provided by this object are slightly different from the other two, but still extremely powerful and simple to use.

java
@RouteInfo(endpoint = "/helloFile", method = HttpMethod.POST)
+public class MyHandler extends RequestHandler {
+    // Store the expected file in a private field
+    private final ExpectedBodyFile myExpectedBodyFile;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected file "myFile", and optionally provide a description
+        myExpectedBodyFile = expectedBodyFile("myFile", "A description of the file");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Write the file to filesystem and get the File object
+        File myFile = myExpectedBodyFile.createFile(Paths.get("path/to/save"));
+        
+        // Return the response to the client
+        return "File saved at: " + myFile.getAbsolutePath();
+    }
+}

This time, you will need to use a tool like Postman to send a POST request to /helloFile with a multipart form data body containing a file named myFile. You should receive a response like File saved at: <path> where <path> is the location where the server saved the file.

`,19)]))}const E=i(n,[["render",h]]);export{c as __pageData,E as default}; diff --git a/assets/flash_core-concepts_request-response.md.BuTSfkDO.lean.js b/assets/flash_core-concepts_request-response.md.BuTSfkDO.lean.js new file mode 100644 index 0000000..c808483 --- /dev/null +++ b/assets/flash_core-concepts_request-response.md.BuTSfkDO.lean.js @@ -0,0 +1,67 @@ +import{_ as i,c as e,a0 as a,o as t}from"./chunks/framework.p2VkXzrt.js";const c=JSON.parse('{"title":"📥 Request and Response","description":"","frontmatter":{"banner_title":"Flash - Request and Response","banner_description":"Unlock the power of the Request and Response objects in Flash.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-core-concepts-request-response.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-core-concepts-request-response.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/core-concepts/request-response.md","filePath":"flash/core-concepts/request-response.md"}'),n={name:"flash/core-concepts/request-response.md"};function h(l,s,p,d,k,r){return t(),e("div",null,s[0]||(s[0]=[a(`

📥 Request and Response

Generally speaking, in an HTTP request-response cycle, the client sends a request to the server, and the server generates a response based on the request. In this section, we illustrate the Request and Response objects in Flash, which are used to interact with the request data and generate responses. We will learn to read and interpret the request data, and model the correct response to send back to the client.

Request and Response Objects

The Request and Response objects are passed to the handler constructor and provide access to the request data and response methods. Under the hood, these objects are provided by the RouteController during the registration stage of the handler, and they are continously updated for each request on that specific handler's instance, but for now, you can consider them as magic.

These objects are a very powerful tool to interact with the lifecycle of the server's response, and they provide a wide range of methods that makes our lives as developers easier.

RequestHandler context

Inside a RequestHandler class, you can access the Request and Response objects inside the handle method by simply typing req and res, respectively. You can use the methods provided by these objects both outside of a handler, and inside of it, to interact with the request and response objects. Although, the advantages of being inside a handler are that Flash supports out-of-the-box methods that can significantly clean up your code and improve the overall readability of your handlers.

Specifically, the ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile objects are used to get the expected properties of the request, and they are used by Flash to validate the request data before the handle method is even executed.

The developer can then simply assume that all the expected parameters are present and valid, without having to write a single line of validation code: Flash will do it for you.

The three objects mentioned above are fairly similar in their usage, providing getter methods which safely return the data in the expected format and type, thanks to Flash's built-in validation and casting system.

NOTE

Flash will take care of informing the client of any missing or invalid parameters, parameters that are not in the expected format, or any other kind of error that might occur during the validation process.

REMEMBER

The ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile instances are ONLY supposed to be retrieved by calling the respective expectedRequestParameter(), expectedBodyField(), and expectedBodyFile() methods INSIDE of the super constructor of your handler class.

Example Usage

Click to expand

The ExpectedRequestParameter object is used to get the expected parameters of the request. You can use the getter methods to safely get the parameter value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the parameter to the expected type.

java
@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    // Store the expected parameter in a private field
+    private final ExpectedRequestParameter myExpectedReqParam;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected parameter "myParam", and optionally provide a description
+        myExpectedReqParam = expectedRequestParameter("myParam", "A description of the parameter");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Safely get the parameter value as a String
+        String myParamValue = myExpectedReqParam.getString();
+        
+        // Return the response to the client
+        return "Hello, " + myParamValue + "!";
+    }
+}

Visiting /hello?myParam=John from your browser, will return Hello, John!.

Click to expand

The ExpectedBodyField object is used to get the expected fields of the request body. You can use the getter methods to safely get the field value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the field to the expected type.

java
@RouteInfo(endpoint = "/helloBody", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    // Store the expected field in a private field
+    private final ExpectedBodyField myExpectedBodyField;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected field "myField", and optionally provide a description
+        myExpectedBodyField = expectedBodyField("myField", "A description of the field");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Safely get the field value as a String
+        String myFieldValue = myExpectedBodyField.getString();
+        
+        // Return the response to the client
+        return "Field value: " + myFieldValue;
+    }
+}

This time, since we are expecting a field in the request body, using our browser would not be enough to test the handler. Instead, you can use a tool like Postman to send a GET request to /helloBody with a multipart form data body containing a field named myField. You should receive a response like Field value: <value>.

Click to expand

The ExpectedBodyFile object is used to get the expected files of the request body. The methods provided by this object are slightly different from the other two, but still extremely powerful and simple to use.

java
@RouteInfo(endpoint = "/helloFile", method = HttpMethod.POST)
+public class MyHandler extends RequestHandler {
+    // Store the expected file in a private field
+    private final ExpectedBodyFile myExpectedBodyFile;
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+        // Get the expected file "myFile", and optionally provide a description
+        myExpectedBodyFile = expectedBodyFile("myFile", "A description of the file");
+    }
+
+    @Override
+    public Object handle() {
+        // OPTIONAL: specify the response status code and type
+        res.status(200);
+        res.type("text/plain");
+        
+        // Write the file to filesystem and get the File object
+        File myFile = myExpectedBodyFile.createFile(Paths.get("path/to/save"));
+        
+        // Return the response to the client
+        return "File saved at: " + myFile.getAbsolutePath();
+    }
+}

This time, you will need to use a tool like Postman to send a POST request to /helloFile with a multipart form data body containing a file named myFile. You should receive a response like File saved at: <path> where <path> is the location where the server saved the file.

`,19)]))}const E=i(n,[["render",h]]);export{c as __pageData,E as default}; diff --git a/assets/flash_core-concepts_server-router.md.Dpvzqe12.js b/assets/flash_core-concepts_server-router.md.Dpvzqe12.js new file mode 100644 index 0000000..9035104 --- /dev/null +++ b/assets/flash_core-concepts_server-router.md.Dpvzqe12.js @@ -0,0 +1,24 @@ +import{_ as i,c as a,a0 as e,o as n}from"./chunks/framework.p2VkXzrt.js";const c=JSON.parse('{"title":"🛣️ Server Router","description":"","frontmatter":{"banner_title":"Flash - Server Router","banner_description":"Learn how to use the FlashServer router to create and manage RouteHandlers.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-core-concepts-server-router.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-core-concepts-server-router.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/core-concepts/server-router.md","filePath":"flash/core-concepts/server-router.md"}'),t={name:"flash/core-concepts/server-router.md"};function h(l,s,r,p,k,o){return n(),a("div",null,s[0]||(s[0]=[e(`

🛣️ Server Router

In this section, we discuss how to use the FlashServer router to manage our RequestHandler instances. The router is used to define route endpoints and their corresponding handler, which are executed when a request is made to the server.

The FlashServer router is an instance of the RouteController class, each server instance has its own router instance. To access the router instance, you can call the route() method on the FlashServer instance.

Creating a Route

To create a route, you need to call the route() method on your server's instance (in this case for simplicity, on the InternalFlashServer) and specify the base path of the route, followed by your handler class,

java
// Example.java
+public class Example {
+    public static void main(String[] args) {
+        FlashServer server = new FlashServer(8080);
+        
+        server.route("/api")
+            .register(MyHandler.class);
+            
+        server.start();
+    }
+}
java
// MyHandler.java
+
+@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        String response = "Hello, world!";
+        return response;
+    }
+}

In the example above, we create an /api router and register the MyHandler class to handle requests on the /api/hello endpoint.

This is because the path property of the RouteInfo annotation is relative to the base path of the router, which in this case is /api.

Visiting /api/hello from your browser will result in the response Hello, world!.

`,10)]))}const E=i(t,[["render",h]]);export{c as __pageData,E as default}; diff --git a/assets/flash_core-concepts_server-router.md.Dpvzqe12.lean.js b/assets/flash_core-concepts_server-router.md.Dpvzqe12.lean.js new file mode 100644 index 0000000..9035104 --- /dev/null +++ b/assets/flash_core-concepts_server-router.md.Dpvzqe12.lean.js @@ -0,0 +1,24 @@ +import{_ as i,c as a,a0 as e,o as n}from"./chunks/framework.p2VkXzrt.js";const c=JSON.parse('{"title":"🛣️ Server Router","description":"","frontmatter":{"banner_title":"Flash - Server Router","banner_description":"Learn how to use the FlashServer router to create and manage RouteHandlers.","head":[["meta",{"name":"twitter:image","content":"/assets/banner-cards/flash-core-concepts-server-router.png"}],["meta",{"name":"twitter:image:src","content":"https://docs.pixel-services.com/assets/banner-cards/flash-core-concepts-server-router.png"}],["meta",{"name":"twitter:card","content":"summary_large_image"}],["meta",{"name":"twitter:image:height","content":"1280"}],["meta",{"name":"twitter:image:width","content":"669"}],["meta",{"name":"twitter:description","content":""}]]},"headers":[],"relativePath":"flash/core-concepts/server-router.md","filePath":"flash/core-concepts/server-router.md"}'),t={name:"flash/core-concepts/server-router.md"};function h(l,s,r,p,k,o){return n(),a("div",null,s[0]||(s[0]=[e(`

🛣️ Server Router

In this section, we discuss how to use the FlashServer router to manage our RequestHandler instances. The router is used to define route endpoints and their corresponding handler, which are executed when a request is made to the server.

The FlashServer router is an instance of the RouteController class, each server instance has its own router instance. To access the router instance, you can call the route() method on the FlashServer instance.

Creating a Route

To create a route, you need to call the route() method on your server's instance (in this case for simplicity, on the InternalFlashServer) and specify the base path of the route, followed by your handler class,

java
// Example.java
+public class Example {
+    public static void main(String[] args) {
+        FlashServer server = new FlashServer(8080);
+        
+        server.route("/api")
+            .register(MyHandler.class);
+            
+        server.start();
+    }
+}
java
// MyHandler.java
+
+@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
+public class MyHandler extends RequestHandler {
+    public MyHandler(Request req, Response res) {
+        super(req, res);
+    }
+
+    @Override
+    public Object handle() {
+        String response = "Hello, world!";
+        return response;
+    }
+}

In the example above, we create an /api router and register the MyHandler class to handle requests on the /api/hello endpoint.

This is because the path property of the RouteInfo annotation is relative to the base path of the router, which in this case is /api.

Visiting /api/hello from your browser will result in the response Hello, world!.

`,10)]))}const E=i(t,[["render",h]]);export{c as __pageData,E as default}; diff --git a/flash/advanced/fullstack-development.html b/flash/advanced/fullstack-development.html index fa6def8..4692323 100644 --- a/flash/advanced/fullstack-development.html +++ b/flash/advanced/fullstack-development.html @@ -54,7 +54,7 @@ server.start(); } }

🚀 Package and Deploy your app!

With the frontend and backend code in place, you can now build the JAR file and deploy it to your server. The JAR file will contain both the frontend and backend code, making it easy to deploy and run your fullstack application.

All you've left to do is run the jarfile on any machine that has Java installed, and your fullstack application will be up and running!

- + \ No newline at end of file diff --git a/flash/advanced/handler-default-implementations.html b/flash/advanced/handler-default-implementations.html index 61a2ab4..8e9e20d 100644 --- a/flash/advanced/handler-default-implementations.html +++ b/flash/advanced/handler-default-implementations.html @@ -13,7 +13,7 @@ - + @@ -80,7 +80,7 @@ // Implement key validation logic, e.g., checking against a database return true; } -}

Now, your API handler implementation only need to extend APIKeyProtectedHandler, ensuring every request has a valid API key before executing its logic:

java
@RouteInfo(method = HttpMethod.GET, path = "/data")
+}

Now, your API handler implementation only need to extend APIKeyProtectedHandler, ensuring every request has a valid API key before executing its logic:

java
@RouteInfo(endpoint = "/data", method = HttpMethod.GET)
 public class GetDataHandler extends APIKeyProtectedHandler {
     public GetDataHandler(Request req, Response res) {
         super(req, res);
@@ -142,7 +142,7 @@
         return "{\"username\":\"" + user.getUsername() + "\"}";
     }
 }
- + \ No newline at end of file diff --git a/flash/core-concepts/handlers.html b/flash/core-concepts/handlers.html index 27f2494..695d7b9 100644 --- a/flash/core-concepts/handlers.html +++ b/flash/core-concepts/handlers.html @@ -41,7 +41,7 @@ server.get("/hello", (req, res) -> { return "Hello, World!"; });

Both RequestHandler and SimpleHandler can specify the router behavior by the naming convention of the endpoint used to register the handler.

- + \ No newline at end of file diff --git a/flash/core-concepts/request-handler.html b/flash/core-concepts/request-handler.html index 32a934c..e0c3b1f 100644 --- a/flash/core-concepts/request-handler.html +++ b/flash/core-concepts/request-handler.html @@ -37,7 +37,7 @@ return response; } }

WARNING

Any logic that needs to be executed before the request handler is registered must be done within the constructor.

Request Handler methods

The RequestHandler class provides several methods that can be used to interact with the request and response objects easily and safely. Following are listed the methods available in the RequestHandler class, with a brief description of their purpose:

MethodParamsDescription
getRequestBody()noneReturns a JSONObject representation of the request body.
getSpecification()noneReturns an instance of HandlerSpecification containing all sorts of information about the handler.
expectedRequestParameter()String name, descriptionReturns an instance of ExpectedRequestParameter for the specified parameter name.
expectedBodyField()String name, descriptionReturns an instance of ExpectedBodyField for the specified field name.
expectedBodyFile()String name, descriptionReturns an instance of ExpectedBodyFile for the specified file name.

(More on the ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile classes in the next section).

- + \ No newline at end of file diff --git a/flash/core-concepts/request-response.html b/flash/core-concepts/request-response.html index 6fb6bd9..1c7764f 100644 --- a/flash/core-concepts/request-response.html +++ b/flash/core-concepts/request-response.html @@ -13,7 +13,7 @@ - + @@ -25,7 +25,7 @@ -
Skip to content

📥 Request and Response

Generally speaking, in an HTTP request-response cycle, the client sends a request to the server, and the server generates a response based on the request. In this section, we illustrate the Request and Response objects in Flash, which are used to interact with the request data and generate responses. We will learn to read and interpret the request data, and model the correct response to send back to the client.

Request and Response Objects

The Request and Response objects are passed to the handler constructor and provide access to the request data and response methods. Under the hood, these objects are provided by the RouteController during the registration stage of the handler, and they are continously updated for each request on that specific handler's instance, but for now, you can consider them as magic.

These objects are a very powerful tool to interact with the lifecycle of the server's response, and they provide a wide range of methods that makes our lives as developers easier.

RequestHandler context

Inside a RequestHandler class, you can access the Request and Response objects inside the handle method by simply typing req and res, respectively. You can use the methods provided by these objects both outside of a handler, and inside of it, to interact with the request and response objects. Although, the advantages of being inside a handler are that Flash supports out-of-the-box methods that can significantly clean up your code and improve the overall readability of your handlers.

Specifically, the ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile objects are used to get the expected properties of the request, and they are used by Flash to validate the request data before the handle method is even executed.

The developer can then simply assume that all the expected parameters are present and valid, without having to write a single line of validation code: Flash will do it for you.

The three objects mentioned above are fairly similar in their usage, providing getter methods which safely return the data in the expected format and type, thanks to Flash's built-in validation and casting system.

NOTE

Flash will take care of informing the client of any missing or invalid parameters, parameters that are not in the expected format, or any other kind of error that might occur during the validation process.

REMEMBER

The ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile instances are ONLY supposed to be retrieved by calling the respective expectedRequestParameter(), expectedBodyField(), and expectedBodyFile() methods INSIDE of the super constructor of your handler class.

Example Usage

  • ExpectedRequestParameter
Click to expand

The ExpectedRequestParameter object is used to get the expected parameters of the request. You can use the getter methods to safely get the parameter value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the parameter to the expected type.

java
@RouteInfo(method = HttpMethod.GET, path = "/hello")
+    
Skip to content

📥 Request and Response

Generally speaking, in an HTTP request-response cycle, the client sends a request to the server, and the server generates a response based on the request. In this section, we illustrate the Request and Response objects in Flash, which are used to interact with the request data and generate responses. We will learn to read and interpret the request data, and model the correct response to send back to the client.

Request and Response Objects

The Request and Response objects are passed to the handler constructor and provide access to the request data and response methods. Under the hood, these objects are provided by the RouteController during the registration stage of the handler, and they are continously updated for each request on that specific handler's instance, but for now, you can consider them as magic.

These objects are a very powerful tool to interact with the lifecycle of the server's response, and they provide a wide range of methods that makes our lives as developers easier.

RequestHandler context

Inside a RequestHandler class, you can access the Request and Response objects inside the handle method by simply typing req and res, respectively. You can use the methods provided by these objects both outside of a handler, and inside of it, to interact with the request and response objects. Although, the advantages of being inside a handler are that Flash supports out-of-the-box methods that can significantly clean up your code and improve the overall readability of your handlers.

Specifically, the ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile objects are used to get the expected properties of the request, and they are used by Flash to validate the request data before the handle method is even executed.

The developer can then simply assume that all the expected parameters are present and valid, without having to write a single line of validation code: Flash will do it for you.

The three objects mentioned above are fairly similar in their usage, providing getter methods which safely return the data in the expected format and type, thanks to Flash's built-in validation and casting system.

NOTE

Flash will take care of informing the client of any missing or invalid parameters, parameters that are not in the expected format, or any other kind of error that might occur during the validation process.

REMEMBER

The ExpectedRequestParameter, ExpectedBodyField, and ExpectedBodyFile instances are ONLY supposed to be retrieved by calling the respective expectedRequestParameter(), expectedBodyField(), and expectedBodyFile() methods INSIDE of the super constructor of your handler class.

Example Usage

  • ExpectedRequestParameter
Click to expand

The ExpectedRequestParameter object is used to get the expected parameters of the request. You can use the getter methods to safely get the parameter value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the parameter to the expected type.

java
@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
 public class MyHandler extends RequestHandler {
     // Store the expected parameter in a private field
     private final ExpectedRequestParameter myExpectedReqParam;
@@ -47,7 +47,7 @@
         // Return the response to the client
         return "Hello, " + myParamValue + "!";
     }
-}

Visiting /hello?myParam=John from your browser, will return Hello, John!.

  • ExpectedBodyField
Click to expand

The ExpectedBodyField object is used to get the expected fields of the request body. You can use the getter methods to safely get the field value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the field to the expected type.

java
@RouteInfo(method = HttpMethod.GET, path = "/helloBody")
+}

Visiting /hello?myParam=John from your browser, will return Hello, John!.

  • ExpectedBodyField
Click to expand

The ExpectedBodyField object is used to get the expected fields of the request body. You can use the getter methods to safely get the field value, such as getString, getInt, getDouble, and getBoolean methods to safely cast the field to the expected type.

java
@RouteInfo(endpoint = "/helloBody", method = HttpMethod.GET)
 public class MyHandler extends RequestHandler {
     // Store the expected field in a private field
     private final ExpectedBodyField myExpectedBodyField;
@@ -69,7 +69,7 @@
         // Return the response to the client
         return "Field value: " + myFieldValue;
     }
-}

This time, since we are expecting a field in the request body, using our browser would not be enough to test the handler. Instead, you can use a tool like Postman to send a GET request to /helloBody with a multipart form data body containing a field named myField. You should receive a response like Field value: <value>.

  • ExpectedBodyFile
Click to expand

The ExpectedBodyFile object is used to get the expected files of the request body. The methods provided by this object are slightly different from the other two, but still extremely powerful and simple to use.

  • createFile(Path/String) accepts either a Path or a String as input. It writes the file's contents to the specified location on the filesystem and returns a File object for further interaction.
  • getFileName() simply returns the name of the file specified by the client.
  • getInputStream() returns an InputStream object containing the file's contents.
java
@RouteInfo(method = HttpMethod.POST, path = "/helloFile")
+}

This time, since we are expecting a field in the request body, using our browser would not be enough to test the handler. Instead, you can use a tool like Postman to send a GET request to /helloBody with a multipart form data body containing a field named myField. You should receive a response like Field value: <value>.

  • ExpectedBodyFile
Click to expand

The ExpectedBodyFile object is used to get the expected files of the request body. The methods provided by this object are slightly different from the other two, but still extremely powerful and simple to use.

  • createFile(Path/String) accepts either a Path or a String as input. It writes the file's contents to the specified location on the filesystem and returns a File object for further interaction.
  • getFileName() simply returns the name of the file specified by the client.
  • getInputStream() returns an InputStream object containing the file's contents.
java
@RouteInfo(endpoint = "/helloFile", method = HttpMethod.POST)
 public class MyHandler extends RequestHandler {
     // Store the expected file in a private field
     private final ExpectedBodyFile myExpectedBodyFile;
@@ -92,7 +92,7 @@
         return "File saved at: " + myFile.getAbsolutePath();
     }
 }

This time, you will need to use a tool like Postman to send a POST request to /helloFile with a multipart form data body containing a file named myFile. You should receive a response like File saved at: <path> where <path> is the location where the server saved the file.

- + \ No newline at end of file diff --git a/flash/core-concepts/server-router.html b/flash/core-concepts/server-router.html index 999ee7a..0f6b597 100644 --- a/flash/core-concepts/server-router.html +++ b/flash/core-concepts/server-router.html @@ -13,7 +13,7 @@ - + @@ -37,7 +37,7 @@ } }
java
// MyHandler.java
 
-@RouteInfo(method = HttpMethod.GET, path = "/hello")
+@RouteInfo(endpoint = "/hello", method = HttpMethod.GET)
 public class MyHandler extends RequestHandler {
     public MyHandler(Request req, Response res) {
         super(req, res);
@@ -49,7 +49,7 @@
         return response;
     }
 }

In the example above, we create an /api router and register the MyHandler class to handle requests on the /api/hello endpoint.

This is because the path property of the RouteInfo annotation is relative to the base path of the router, which in this case is /api.

Visiting /api/hello from your browser will result in the response Hello, world!.

- + \ No newline at end of file diff --git a/flash/core-concepts/websockets.html b/flash/core-concepts/websockets.html index 65d83c1..63542ea 100644 --- a/flash/core-concepts/websockets.html +++ b/flash/core-concepts/websockets.html @@ -58,7 +58,7 @@ server.start(); } }

Interacting with Websockets sessions

The WebSocketSession object provides methods to interact with the Websocket session, such as sending messages, closing the connection, and getting the remote address and session ID.

MethodParamsDescription
getChannel()noneReturns an instance of AsynchronousSocketChannel useful for retrieving info about the client .
getRequestInfo()noneReturns an instance of RequestInfo containing all sorts of information about the request (headers, method, path etc.) .
getPath()noneReturns the path to the websocket endpoint as a String.
getId()noneReturns the id of the websocket session as a String, useful if you want to keep track of the connected clients in a custom manager.
getBuffer()noneReturns the ByteBuffer for that session.
sendMessage()String messageSends the message to the client as a String. it's up to the developer to stringify and de-stringify any data you want to send back and forth
close()noneCloses the websocket session.

NOTE

WebsocketHandler includes a setId(String id) method for overriding the default session ID. Unless you have a specific reason to change it, it's best to leave it as is.

Similarly, the setBuffer(ByteBuffer buffer) method allows you to override the default buffer. If you're unsure about this, it's recommended to keep the default setting.

- + \ No newline at end of file diff --git a/flash/file-serving/dynamic-file-server.html b/flash/file-serving/dynamic-file-server.html index 5fb7aab..e7d5156 100644 --- a/flash/file-serving/dynamic-file-server.html +++ b/flash/file-serving/dynamic-file-server.html @@ -53,7 +53,7 @@ )); } } - + \ No newline at end of file diff --git a/flash/file-serving/static-file-server.html b/flash/file-serving/static-file-server.html index b5a145b..e125bfc 100644 --- a/flash/file-serving/static-file-server.html +++ b/flash/file-serving/static-file-server.html @@ -53,7 +53,7 @@ )); } } - + \ No newline at end of file diff --git a/flash/index.html b/flash/index.html index 65571a9..1e1b29c 100644 --- a/flash/index.html +++ b/flash/index.html @@ -26,7 +26,7 @@
Skip to content

⚡ Flash

Flash is a simple, modern and fast expressive web framework written in Java. The project is maintained by Pixel Services and the open-source community.

Our Team

Say hello to the Pixel Services team !

Relism

Relism

Developer

Sieadev

Sieadev

Developer

- + \ No newline at end of file diff --git a/flash/introduction/installation.html b/flash/introduction/installation.html index e7aa12c..b07ffa6 100644 --- a/flash/introduction/installation.html +++ b/flash/introduction/installation.html @@ -44,7 +44,7 @@ }
  • And the dependency :

    groovy
    dependencies {
         implementation 'com.pixelservices:flash:{{ latestVersion }}'
     }
  • ⚡ Latest version:
    - + \ No newline at end of file diff --git a/hashmap.json b/hashmap.json index 13bb0ae..63e487a 100644 --- a/hashmap.json +++ b/hashmap.json @@ -1 +1 @@ -{"flash_advanced_fullstack-development.md":"DFJ2Nfm_","flash_advanced_handler-default-implementations.md":"Bai_t_s4","flash_core-concepts_handlers.md":"B1156l1I","flash_core-concepts_request-handler.md":"fjZWLpOw","flash_core-concepts_request-response.md":"3C-3EYgj","flash_core-concepts_server-router.md":"BtmNSZRo","flash_core-concepts_websockets.md":"ByGVX96c","flash_file-serving_dynamic-file-server.md":"DY_r4ecH","flash_file-serving_static-file-server.md":"BvN0FZB2","flash_index.md":"E5zPbZtg","flash_introduction_installation.md":"BEOKwAAp","index.md":"CgmTRI0Q","mobot_index.md":"Be0Zoetq","serverlibraries_index.md":"CeIqSPIs"} +{"flash_advanced_fullstack-development.md":"DFJ2Nfm_","flash_advanced_handler-default-implementations.md":"ki9D2CCK","flash_core-concepts_handlers.md":"B1156l1I","flash_core-concepts_request-handler.md":"fjZWLpOw","flash_core-concepts_request-response.md":"BuTSfkDO","flash_core-concepts_server-router.md":"Dpvzqe12","flash_core-concepts_websockets.md":"ByGVX96c","flash_file-serving_dynamic-file-server.md":"DY_r4ecH","flash_file-serving_static-file-server.md":"BvN0FZB2","flash_index.md":"E5zPbZtg","flash_introduction_installation.md":"BEOKwAAp","index.md":"CgmTRI0Q","mobot_index.md":"Be0Zoetq","serverlibraries_index.md":"CeIqSPIs"} diff --git a/index.html b/index.html index 4684307..141cad9 100644 --- a/index.html +++ b/index.html @@ -26,7 +26,7 @@
    - + \ No newline at end of file diff --git a/mobot/index.html b/mobot/index.html index 4a287cb..19ac67e 100644 --- a/mobot/index.html +++ b/mobot/index.html @@ -26,7 +26,7 @@
    Skip to content
    - + \ No newline at end of file diff --git a/serverlibraries/index.html b/serverlibraries/index.html index 5dd19e8..c9958d2 100644 --- a/serverlibraries/index.html +++ b/serverlibraries/index.html @@ -26,7 +26,7 @@
    Skip to content
    - + \ No newline at end of file