2023-09-21 17:45:06 +00:00
|
|
|
"Univeral Lambda" for Zig
|
|
|
|
=========================
|
|
|
|
|
|
|
|
This a Zig 0.11 project intended to be used as a package to turn a zig program
|
|
|
|
into a function that can be run as:
|
|
|
|
|
|
|
|
* A command line executable
|
|
|
|
* A standalone web server
|
|
|
|
* An AWS Lambda function
|
|
|
|
* A shared library in [flexilib](https://git.lerch.org/lobo/FlexiLib)
|
2023-10-21 06:06:13 +00:00
|
|
|
* Cloudflare
|
2023-09-21 17:45:06 +00:00
|
|
|
* etc
|
|
|
|
|
|
|
|
Usage - Development
|
|
|
|
-------------------
|
|
|
|
|
|
|
|
From an empty directory, with Zig 0.11 installed:
|
|
|
|
|
|
|
|
`zig init-exe`
|
|
|
|
|
|
|
|
|
|
|
|
Create a `build.zig.zon` with the following contents:
|
|
|
|
|
|
|
|
```
|
|
|
|
.{
|
|
|
|
.name = "univeral-zig-example",
|
|
|
|
.version = "0.0.1",
|
|
|
|
|
|
|
|
.dependencies = .{
|
|
|
|
.universal_lambda_build = .{
|
2023-10-21 06:06:13 +00:00
|
|
|
.url = "https://git.lerch.org/lobo/universal-lambda-zig/archive/70b0fda03b9c54a6eda8d61cb8ab8b9d9f29b2ef.tar.gz",
|
|
|
|
.hash = "122004f2a4ad253be9b8d7989ca6508af1483d8a593ca7fee93627444b2b37d170d2",
|
2023-10-05 23:23:44 +00:00
|
|
|
},
|
|
|
|
.flexilib = .{
|
|
|
|
.url = "https://git.lerch.org/lobo/flexilib/archive/c44ad2ba84df735421bef23a2ad612968fb50f06.tar.gz",
|
|
|
|
.hash = "122051fdfeefdd75653d3dd678c8aa297150c2893f5fad0728e0d953481383690dbc",
|
2023-09-21 17:45:06 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
Due to limitations in the build apis related to relative file paths, the
|
2023-10-05 23:23:44 +00:00
|
|
|
dependency name currently must be "universal_lambda_build". Also, note that
|
|
|
|
the flexilib dependency is required at all times. This requirement may go away
|
|
|
|
with zig 0.12 (see [#17135](https://github.com/ziglang/zig/issues/17135))
|
|
|
|
and/or changes to this library.
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
**Build.zig:**
|
|
|
|
|
|
|
|
* Add an import at the top:
|
|
|
|
|
|
|
|
```zig
|
|
|
|
const configureUniversalLambdaBuild = @import("universal_lambda_build").configureBuild;
|
|
|
|
```
|
|
|
|
|
|
|
|
* Set the return of the build function to return `!void` rather than `void`
|
|
|
|
* Add a line to the build script, after any modules are used, but otherwise just
|
|
|
|
after adding the exe is fine:
|
|
|
|
|
|
|
|
```zig
|
|
|
|
try configureUniversalLambdaBuild(b, exe);
|
|
|
|
```
|
|
|
|
|
|
|
|
This will provide most of the magic functionality of the package, including
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
several new build steps to manage the system, and a new import to be used. For
|
|
|
|
testing, it is also advisable to add the modules to your tests by adding a line
|
|
|
|
like so:
|
|
|
|
|
|
|
|
```zig
|
|
|
|
_ = try universal_lambda.addModules(b, main_tests);
|
|
|
|
```
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
**main.zig**
|
|
|
|
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
The build changes above will add several modules:
|
|
|
|
|
|
|
|
* universal_lambda_handler: Main import, used to register your handler
|
|
|
|
* universal_lambda_interface: Contains the context type used in the handler function
|
|
|
|
* flexilib-interface: Used as a dependency of the handler. Not normally needed
|
|
|
|
|
|
|
|
Add imports for the handler registration and interface:
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
```zig
|
|
|
|
const universal_lambda = @import("universal_lambda_handler");
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
const universal_lambda_interface = @import("universal_lambda_interface");
|
2023-09-21 17:45:06 +00:00
|
|
|
```
|
|
|
|
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
Add a handler to be executed. The handler must follow this signature:
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
```zig
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
pub fn handler(allocator: std.mem.Allocator, event_data: []const u8, context: universal_lambda_interface.Context) ![]const u8
|
2023-09-21 17:45:06 +00:00
|
|
|
```
|
|
|
|
|
2023-10-23 19:55:28 +00:00
|
|
|
Your main function should return `!u8`. Let the package know about your handler in your main function, like so:
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
```zig
|
2023-10-23 19:55:28 +00:00
|
|
|
return try universal_lambda.run(null, handler);
|
2023-09-21 17:45:06 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
The first parameter above is an allocator. If you have a specific handler you
|
|
|
|
would like to use, you may specify it. Otherwise, an appropriate allocator
|
|
|
|
will be created and used. Currently this is an ArenaAllocator wrapped around
|
|
|
|
an appropriate base allocator, so your handler does not require deallocation.
|
|
|
|
|
|
|
|
A fully working example of usage is at https://git.lerch.org/lobo/universal-lambda-example/.
|
|
|
|
|
|
|
|
Usage - Building
|
|
|
|
----------------
|
|
|
|
|
|
|
|
The build configuration will add the following build steps when building with
|
|
|
|
Linux:
|
|
|
|
|
|
|
|
```
|
|
|
|
awslambda_package Package the function
|
|
|
|
awslambda_deploy Deploy the function
|
|
|
|
awslambda_iam Create/Get IAM role for function
|
|
|
|
awslambda_run Run the app in AWS lambda
|
2023-10-21 06:06:13 +00:00
|
|
|
cloudflare Deploy as Cloudflare worker (must be compiled with -Dtarget=wasm32-wasi)
|
2023-09-21 17:45:06 +00:00
|
|
|
flexilib Create a flexilib dynamic library
|
2023-10-21 06:06:13 +00:00
|
|
|
standalone_server Run the function in its own web server
|
2023-09-21 17:45:06 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
AWS Lambda is not currently available if building with other operating systems,
|
|
|
|
as that set of build steps utilize system commands using the AWS CLI. This is
|
2023-10-21 06:06:13 +00:00
|
|
|
likely to change in the future to enable other operating systems. All other
|
|
|
|
build steps are available for all targets.
|
|
|
|
|
|
|
|
Note that AWS Lambda will require that credentials are established using the
|
|
|
|
same methods as checked by the AWS CLI and the AWS CLI is installed.
|
|
|
|
|
|
|
|
If using Cloudflare deployment, either CLOUDFLARE_API_TOKEN or
|
|
|
|
CLOUDFLARE_EMAIL/CLOUDFLARE_API_KEY environment variables must be set for
|
|
|
|
successful deployment.
|
2023-09-21 17:45:06 +00:00
|
|
|
|
|
|
|
To run as an executable, a simple `zig build` will build, or `zig build run`
|
|
|
|
will run as expected. `zig build standalone_server run` will also build/run
|
|
|
|
as a standalone web server.
|
|
|
|
|
|
|
|
Limitations
|
|
|
|
-----------
|
|
|
|
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
Limitations include standalone web server port customization and linux/aws cli requirements for Linux.
|
2023-09-21 17:45:06 +00:00
|
|
|
|
rework context
This commit is a significant refactor that fixes a number of things.
1. Replaces the optional helpers import (which was always weird) with a
mandatory interface import on behalf of the application. This is
actually a good thing as it enables all things below.
2. Removes the severely awkward union that was the lambda context. Now,
no matter how your handler runs, a single object with everything you
need is fully populated and (nearly always) works as you would
expect. There is a slight exception to this with AWS Lambda that is
related to the service itself. It is also possible that not
everything is passed in correctly for Cloudflare, which, if true,
will be addressed later.
3. Allows writes to the context object. These will be added to the
output, but is implementation dependent, and I'm not 100% sure I've
got it right yet, but the infrastructure is there.
4. Allows proper tests throughout this project.
5. Allows proper tests in the application too.
6. Removes the need for the handler to be public under flexlib. Flexilib
handler registration now works just like everything else. Note,
however, that flexilib is unique in that your handler registration
function will return before the program ends. If this is important
for resource cleanup, @import("build_options").build_type is your
friend.
7. Request method can now be passed into console applications using -m
or --method
2023-10-25 06:45:08 +00:00
|
|
|
Also, within the context, AWS Lambda is unable to provide proper method, target,
|
|
|
|
and headers for the request. This may be important for routing purposes. Suggestion
|
|
|
|
here is to use API Gateway and pass these parameters through the event_data content.
|