[![Rust](https://github.com/nginx/ngx-rust/actions/workflows/ci.yaml/badge.svg)](https://github.com/nginx/ngx-rust/actions/workflows/ci.yaml)
[![crates.io](https://img.shields.io/crates/v/ngx.svg)](https://crates.io/crates/ngx)
[![docs.rs](https://img.shields.io/docsrs/ngx?label=docs(ngx))](https://docs.rs/ngx)
[![docs.rs](https://img.shields.io/docsrs/nginx-sys?label=docs(nginx-sys))](https://docs.rs/nginx-sys)
[![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip)
[![Community Support](https://badgen.net/badge/support/community/cyan?icon=awesome)](https://github.com/nginx/ngx-rust/discussions)

<!-- cargo-sync-readme start -->

# Rust bindings for NGINX

The `ngx` crate provides a high-level Rust interface for the [NGINX] C APIs,
allowing creation of NGINX dynamic modules completely in Rust.

[NGINX]: https://nginx.org/

## Project status

This project is in active development. It is stable enough to be used in our
own products, but the APIs are not stabilized and breaking changes are expected.

## Build

NGINX modules can be built against a particular version of NGINX. The following
environment variables can be used to specify the NGINX build to use:

- `NGINX_BUILD_DIR` - absolute path to the NGINX build directory.
  Usually it's `objs` under the source directory, but can be changed with the
  `--builddir=` argument of the configure script.

- `NGINX_SOURCE_DIR` - absolute path to the NGINX source directory, configured
  with the [`configure`](https://nginx.org/en/docs/configure.html) command.

Only the `./configure` step of the NGINX build is mandatory because bindings
generator don't depend on any of the artifacts generated by `make`.

For example, this is how you would compile the [examples](#examples) using a
specific version of NGINX:

```sh
NGINX_BUILD_DIR=/path/to/nginx-1.28.0/objs cargo build --package=examples --examples
```

### Building with the NGINX build script

You can build your Rust-based module as a part of the NGINX build process by
providing a `config` script implementation and passing the `--add-module`/
`--add-dynamic-module` options to the configure script.

See the following example integration scripts: [`examples/config`] and
[`examples/config.make`].

[`examples/config`]: https://github.com/bavshin-f5/ngx-rust/blob/main/examples/config
[`examples/config.make`]: https://github.com/bavshin-f5/ngx-rust/blob/main/examples/config.make

### Building with vendored NGINX sources

It is possible to build module with a vendored copy of the NGINX sources
provided in the `nginx-src` crate by enabling feature `vendored`:

By default, this will use the latest stable release of NGINX and require
system-wide installation of build dependencies (OpenSSL, PCRE2, Zlib).

The behavior of vendored builds can be customized with environment variables,
as documented in the [nginx-src] crate README.

**NOTE**: We recommend to build the module binaries against the exact source and
configuration of the NGINX build that you are planning to use in production,
and that is unlikely to be possible with the vendored source.

`configure` arguments alter the APIs and the symbols visible to the Rust code,
and some OS distributions are known to ship nginx packages with API-breaking
patches applied.

[nginx-src]: https://docs.rs/nginx-src/

## Cargo features

- `alloc` - **Enabled** by default. This provides APIs that require allocations
  via the `alloc` crate.
- `async` - Enables a minimal async runtime built on top of the NGINX event loop.
- `serde` - Enables serialization support for some of the provided and
  re-exported types.
- `std` - **Enabled** by default. This provides APIs that require the standard
  library.
- `vendored`: Enables the build scripts to build a copy of nginx source and link
  against it. See the [nginx-src] crate documentation for additional details.

## Dependencies

The following dependencies are required to build a Rust NGINX module on Linux
or BSD platform:

- NGINX build dependencies: C compiler, make, OpenSSL, PCRE2, and Zlib.
- Rust toolchain (1.81.0 or later)
- [libclang] for rust-bindgen

The installation process and the package names are system-dependent. Please,
consult the documentation for your distribution.

Note that on some systems you will need `-devel` or `-dev` versions of the
packages.

For example, [Dockerfile] contains the installation commands for Debian Linux.

[Dockerfile]: https://github.com/nginx/ngx-rust/blob/main/Dockerfile
[libclang]: https://rust-lang.github.io/rust-bindgen/requirements.html

### macOS dependencies

In order to use the optional GNU make build process on macOS, you will need
to install additional tools. This can be done via [homebrew](https://brew.sh/)
with the following command:

```sh
brew install make openssl grep
```

Additionally, you may need to set up LLVM and clang. Typically, this is done
as follows:

```sh
# make sure xcode tools are installed
xcode-select --install
# instal llvm
brew install --with-toolchain llvm
```

<!-- cargo-sync-readme end -->

### Examples

Example modules are available in [examples] folder.
You can use `cargo build --package=examples --examples` to build these examples.
After compilation, the modules can be found in the path `target/debug/examples/`
(with the `.so` file extension for Linux or `.dylib` for macOS).
Add `--features=linux` to build Linux specific modules.

**NOTE**: adding the "linux" feature on macOS will cause a build failure.

For example (all examples plus linux specific):

```sh
cargo build --package=examples --examples --features=linux
```

[examples]: https://github.com/nginx/ngx-rust/tree/main/examples

### Docker

We provide a multistage [Dockerfile]:

```sh
# build all dynamic modules examples and specify NGINX version to use
docker buildx build --build-arg NGX_VERSION=1.29.1 -t ngx-rust .

# start NGINX using [curl](examples/curl.conf) module example:
docker run --rm -d  -p 8000:8000 ngx-rust nginx -c examples/curl.conf

# test it - you should see 403 Forbidden
curl http://127.0.0.1:8000 -v -H "user-agent: curl"

# test it - you should see 404 Not Found
curl http://127.0.0.1:8000 -v -H "user-agent: foo"
```

## Usage

A complete module example using the SDK can be found [here](examples/curl.rs).
You can build it with `cargo build --package=examples --example=curl` then set
up NGINX to use it, as shown below:

```nginx
daemon off;
error_log stderr debug;

load_module modules/libcurl.so;

events {
}

http {
    server {
        listen 8000;
        server_name localhost;

        access_log /dev/stdout;

        location / {
            root /srv/http;
            # ... Other config stuff ...

            curl on;
        }
    }
}
```

## Support

This SDK is currently unstable. Right now, our primary goal is collect feedback
and stabilize it before offering support.
Feel free to [contribute](CONTRIBUTING.md) by creating issues, PRs, or github
discussions.

Currently, the supported platforms are:

- Darwin (macOS)
- FreeBSD
- Linux

See the Rust toolchain [platform support] document for supported versions and
architectures.

[platform support]: https://doc.rust-lang.org/rustc/platform-support.html

### Tested OS and platforms

In addition, we verified that the modules based on this SDK can be built and
work on the following platforms.

- Illumos
- NetBSD 9-10
- OpenBSD 7
- Solaris 11.4
- Windows 10+/Windows Server 2022+

## Roadmap

If you have ideas for releases in the future, please suggest them in the github
discussions.

## Contributing

We welcome pull requests and issues!

Please refer to the [Contributing Guidelines](CONTRIBUTING.md) when doing a PR.

## Authors and acknowledgment

This project uses some great work from:

- [dcoles/nginx-rs](https://github.com/dcoles/nginx-rs),
- [arvancloud/nginx-rs](https://github.com/arvancloud/nginx-rs).

## Projects using the SDK

- [ngx-strict-sni](https://github.com/JyJyJcr/ngx-strict-sni) - Strict SNI validator for Nginx
- [nginx-acme](https://github.com/nginx/nginx-acme) - ACMEv2 client implementation

## License

All code in this repository is licensed under the
[Apache License, Version 2.0](./LICENSE).

&copy; [F5, Inc.](https://www.f5.com/)
