Boost Software Quality: Local Development with Azion CLI

Explore local development and testing of Edge Functions using Azion CLI. Boost software quality, optimize performance, and enhance security.

Gabriel França - Technical Writer
Boost Software Quality: Local Development with Azion CLI

Azion CLI is an efficient open-source tool for setting up local testing environments for edge functions. You can easily run your application locally by executing the azion dev command, kickstarting the local development process. This capability boosts software quality by testing and examining edge functions before integrating them into the live product, preventing errors and unexpected behaviors.

Key Benefits of Local Development with Azion CLI

  • Error prevention: test new features or modifications before they go live, reducing the risk of introducing bugs to the production system.
  • Improved debugging: debug code more effectively and quickly in a controlled environment as you can check logs in real time.
  • Performance optimization: test the application’s behavior under different loads or unique user scenarios.
  • Security enhancements: identify and rectify security vulnerabilities before the application goes live.
  • Cost-effective: prevent high resource-consuming post-production fixes, saving time and money by addressing potential problems before deployment.

Prerequisites for Using Azion CLI


Behind The Scenes: How Azion CLI local dev Works

Dataflow

  1. Through Azion CLI, the user runs the azion dev [flags] command.
  2. Azion CLI invokes Vulcan, which manages build and local development.
  3. Vulcan initializes a server and this server instantiates the runtime. This runtime supports a list of Web APIs and emulates the actual Azion Edge Runtime.

Responsibilities

Azion CLI: serves as the primary point of interaction between the user and the system. It manages the entire application deployment process, ensuring a smooth and efficient workflow.

Vulcan: the engine that drives project initialization, building, and adaptation. It intelligently tailors the project based on the selected template, ensuring that the application is optimally configured for its intended use. For local development, Vulcan:

  • Initiates a server.
  • Instantiates the Edge Runtime.
  • Handles changes in the source code, implementing hot reload.

The Science Behind Edge Functions

Azion Edge Functions are used to enhance edge applications or to boost security in an edge firewall. Both run on Azion Edge Runtime, reduce latency, and help to implement a distributed approach. OK, but what’s the difference between them?

The difference is how the functions are structured. Let’s dive deeper into that.

Edge Application Functions

First, edge functions for edge applications work based on a fetch event. They’re initialized with an addEventListener function, passing fetch as the event type, and an event. For example:

addEventListener('fetch',event=>{
event.respondWith(handleRequest(event.request));
});

Second, it’s necessary to define the behavior of the handleRequest function. This function has event.request as the signature. This data can be used later on to implement the necessary logic, such as:

  • Manipulate cookies.
  • Implement a behavior based on the HTTP request method (POST, GET, PUT, DELETE).
  • Access request metadata.

It’s mandatory to return a response object with fetch.

The handleRequest function can be defined as:

const html=`<!DOCTYPE html>
<body>
<h1>Hello World</h1>
<p>This markup was generated by Azion - Edge Functions.</p>
</body>`
async function handleRequest(request){
return new Response(html,{
headers:{
"content-type":"text/html;charset=UTF-8",
},
})
}

In this example, the response will be the HTML content, declared previously by the const html. The headers can be manipulated and, in the example, the content type is set.

Complete Example:

const html=`<!DOCTYPE html>
<body>
<h1>Hello World</h1>
<p>This markup was generated by Azion - Edge Functions.</p>
</body>`
async function handleRequest(request){
return new Response(html,{
headers:{
"content-type":"text/html;charset=UTF-8",
},
})
}
addEventListener('fetch',event=>{
event.respondWith(handleRequest(event.request));
});

Learn more about edge functions for edge applications.

Edge Firewall Functions

Edge functions for Edge Firewall operate based on a firewall event. They’re initialized using the addEventListener function, passing 'firewall' as the event type, and an event. For example:

addEventListener('firewall',event=>{
event.deny();
});

In this instance, the system sends a denial in response to the firewall event that has been triggered. There could be other event reactions like event.continue(), and event.drop() depending on the specific circumstances or logic desired.

It’s necessary to define the potential behaviors for different event reactions within the firewall event listener. The exact response depends on the condition met. For example:

  • Detect threat levels.
  • Block or rights list IP addresses.
  • Implement behaviors based on traffic patterns.

An example where the event.deny function is defined and used:

// Define a list of blocked IP addresses
const blockedIPs=["192.0.2.0","203.0.113.0","198.51.100.0"]
addEventListener('firewall',event=>{
let ip = event.request.clientIP;
if(blockedIPs.includes(ip)){
event.deny();
}else{
event.continue();
}
});

In this example, the firewall event listener checks the IP address that triggered the event against the list of blocked IPs. If the IP is on the list, the event is denied. If the IP isn’t on the list, the event will continue processing. It showcases how you might use event.deny(), event.continue(), and event.drop() in real application scenarios. You can also implement event.respondWith(<Response>).

Since it’s not possible to execute any other method after the execution of a finishing event, it’s recommended to use a return right after the event so it’s clear nothing more will be executed.

Learn more about edge functions for edge firewall.


Testing Edge Applications Functions

To kick off a local testing environment:

  1. Open the terminal, create a new directory, and access it.
  2. In the command line, initiate an application through azion init
  3. Name your application or accept the suggestion.
  4. Select JavaScript as the template.

You can start the application based on the template you want. For this example, JavaScript is used.

  1. Start the local development by answering yes to the interaction.
  2. Install the dependencies.
  3. After a build process, Azion will return the port to access the application.
  4. Send requests to the server and check the behavior.

Note: you can always terminate the terminal process and run azion dev to run the application locally. The changes applied to the function are rebuilt using hot reload.

The azion dev command starts up a local environment where you can test and monitor the functionality and efficiency of your edge function.

Azion edge functions run on Azion Edge Runtime and have compatibility with Web APIs and Azion APIs.

Testing Firewall Functions

If you’ve implemented firewall functions within your system, you’ll need to consider special testing conditions.

To do so, you must run the azion dev command with the flag --firewall. This informs the system you’re testing an edge firewall function.


Conclusion

Using local testing environments improves the product development process and software quality. Leveraging tools like Azion CLI makes it easier to build reliable, efficient, secure, and high-performing software solutions. By testing edge functions with the command azion dev, and optionally adding a --firewall flag when necessary, developers can navigate potential pitfalls before pushing their code into production.

Subscribe to our Newsletter