Git Product home page Git Product logo

zigly's Introduction

Zigly

The easiest way to write Fastly Compute services in Zig.

What is Compute@Edge?

Compute@Edge is Fastly's service to run custom code directly on CDN nodes.

The service runs anything that can be compiled to WebAssembly, and exports a convenient set of functions to interact with the platform.

What is Zigly?

Zigly is a library that makes it easy to write Compute@Edge modules in Zig.

Beyond the functions exported by the Fastly platform, Zigly will eventually include additional utility functions (cookie manipulation, JWT tokens, tracing...) to make application development as simple as possible.

Zigly is written for Zig 0.11.x.

Usage

Adding Zigly as a dependency

Add the following to your build.zig.zon file:

.{
    .name = "project",
    .version = "0.0.1",
    .dependencies = .{
        .zigly = .{
            .url = "https://github.com/jedisct1/zigly/archive/refs/tags/0.1.3.tar.gz",
            .hash = "122025e93467c3e3855b323fcf6cbd5f569603f17eb72cd626354a7ed11609e900ab",
        },
    },
}

And the following to your build.zig file:

    const zigly = b.dependency("zigly", .{
        .target = target,
        .optimize = optimize,
    });
    exe.addModule("zigly", zigly.module("zigly"));
    exe.linkLibrary(zigly.artifact("zigly"));

The zigly structure can be imported in your application with:

const zigly = @import("zigly");

A minimal WebAssembly program

const std = @import("std");

pub fn main() !void
    std.debug.print("Hello from WebAssembly and Zig!\n", .{});
}

The program can be compiled with (replace example.zig with the source file name):

zig build-exe -target wasm32-wasi example.zig

Happy with the result? Add -Doptimize=ReleaseSmall or -Doptimize=ReleaseFast to get very small or very fast module:

zig build-exe -target wasm32-wasi -Doptimize=ReleaseSmall example.zig

The example above should not compile to more than 411 bytes.

If you are using a build file instead, define the target as wasm32-wasi in the build.zig file:

const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" });

...and build with zig build -Doptimize=ReleaseSmall or -Doptimize=ReleaseFast to get optimized modules.

Testing Compute@Edge modules

The easiest way to test the resulting modules is to use Viceroy, a reimplementation of the Fastly API that runs locally.

Using Zigly

Hello world!

var downstream = try zigly.downstream();
var response = downstream.response;
try response.body.writeAll("Hello world!");
try response.finish();

downstream() returns a type representing the initial connection, from a client to the proxy.

That type includes response, that can be used to send a response, as well as request, that can be used to inspect the incoming request.

Every function call may fail with an error from the FastlyError set.

Slightly more complicated example:

var downstream = try zigly.downstream();
var response = downstream.response;

response.setStatus(201);
response.headers.set("X-Example", "Header");

try response.body.writeAll("Partial");
try response.flush();
try response.body.writeAll("Response");
try response.finish();

var logger = Logger.open("logging_endpoint");
logger.write("Operation sucessful!");

Note that calling finish() is always required in order to actually send a response to the client.

But realistically, most responses will either be simple redirects:

var downstream = try zigly.downstream();
try downstream.redirect(302, "https://www.perdu.com");

or responding directly from the cache, proxying to the origin if the cached entry is nonexistent or expired:

var downstream = try zigly.downstream();
try downstream.proxy("google", "www.google.com");

Inspecting incoming requests

Applications can read the body of an incoming requests as well as other informations such as the headers:

const request = downstream.request;
const user_agent = try request.headers.get(allocator, "user-agent");
if (request.isPost()) {
    // method is POST, read the body until the end, up to 1000000 bytes
    const body = try request.body.readAll(allocator, 1000000);
}

As usual in Zig, memory allocations are never hidden, and applications can choose the allocator they want to use for individual function calls.

Making HTTP queries

Making HTTP queries is easy:

var query = try zigly.Request.new("GET", "https://example.com");
var response = try query.send("backend");
const body = try response.body.readAll(allocator, 0);

Arbitrary headers can be added the the outgoing query:

try query.headers.set("X-Custom-Header", "Custom value");

Body content can also be pushed, even as chunks:

try query.body.write("X");
try query.body.write("Y");
try query.body.close();

And the resulting response contains headers and body properties, that can be inspected the same way as a downstream query.

Cache override

Caching can be disabled or configured on a per-query basis with setCachingPolicy():

try query.setCachingPolicy(.{ .serve_stale = 600, .pci = true });

Attributes include:

  • no_cache
  • ttl
  • serve_stale
  • pci
  • surrogate_key

Pipes

With pipe(), the response sent to a client can be a direct copy of another response. The application will then act as a proxy, optionally also copying the original status and headers.

var query = try zigly.Request.new("GET", "https://google.com");
var upstream_response = try query.send("google");
var downstream = try zigly.downstream();
try downstream.response.pipe(&upstream_response, true, true);

Proxying

Proxying is even easier to use than pipes when a query should be sent unmodified (with the exception of the Host header) to the origin:

var downstream = try zigly.downstream();
try downstream.proxy("google", "www.google.com");

The second parameter is optional. If null, the original Host header will not be modified.

Redirects

Redirecting the client to another address can be done with a single function call on the downstream object:

var downstream = try zigly.downstream();
try downstream.redirect(302, "https://www.perdu.com");

Response decompression

By default, responses are left as-is. Which means that if compression (Content-Encoding) was accepted by the client, the response can be compressed.

Calling setAutoDecompressResponse(true) on a Request object configures the Compute@Edge runtime to decompress gzip-encoded responses before streaming them to the application.

Dictionaries

const dict = try zigly.Dictionary.open("name");
const value = try dict.get(allocator, "key");

Logging

const logger = try zigly.Logger.open("endpoint);
try logger.write("Log entry");

Deployment to Fastly's platform

The fastly command-line tool only supports compilation of Rust and AssemblyScript at the moment. However, it can still be used to upload pre-compiled code written in other languages, including Zig.

  1. Create a new project:
fastly compute init

For the language, select Other (pre-compiled WASM binary).

  1. Add a build script:

Add the following lines to the fastly.toml file:

[scripts]
build = "zig build -Doptimize=ReleaseSmall -Dtarget=wasm32-wasi && mkdir -p bin && fastly compute pack --wasm-binary zig-out/bin/*"
  1. Package the Compute@Edge module, passing in your compiled WebAssembly module.
fastly compute pack --path zig-out/bin/main.wasm
  1. Test locally
fastly compute serve --skip-build --file zig-out/bin/main.wasm
  1. Deploy!
fastly compute deploy

In order to deploy new versions, repeat steps 3 and 5.

zigly's People

Contributors

jedisct1 avatar angaz avatar kailan avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.