├── .cargo └── config ├── .devcontainer └── devcontainer.json ├── .funcignore ├── .github └── workflows │ ├── deploy.yml │ └── main.yml ├── .gitignore ├── .vscode ├── extensions.json ├── settings.json └── tasks.json ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md ├── host.json ├── src └── main.rs └── token └── function.json /.cargo/config: -------------------------------------------------------------------------------- 1 | [target.x86_64-unknown-linux-musl] 2 | linker = "rust-lld" -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | // For format details, see https://aka.ms/devcontainer.json. For config options, see the 2 | // README at: https://github.com/devcontainers/templates/tree/main/src/rust 3 | { 4 | "name": "Rust", 5 | // Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile 6 | "image": "mcr.microsoft.com/devcontainers/rust:0-1-bullseye", 7 | "customizations": { 8 | "vscode": { 9 | "extensions": [ 10 | "GitHub.copilot", 11 | "ms-azuretools.vscode-azurefunctions", 12 | "ms-vscode.vscode-node-azure-pack" 13 | ] 14 | } 15 | }, 16 | "features": { 17 | "ghcr.io/jlaundry/devcontainer-features/azure-functions-core-tools:1": {} 18 | } 19 | 20 | // Use 'mounts' to make the cargo cache persistent in a Docker Volume. 21 | // "mounts": [ 22 | // { 23 | // "source": "devcontainer-cargo-cache-${devcontainerId}", 24 | // "target": "/usr/local/cargo", 25 | // "type": "volume" 26 | // } 27 | // ] 28 | 29 | // Features to add to the dev container. More info: https://containers.dev/features. 30 | // "features": {}, 31 | 32 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 33 | // "forwardPorts": [], 34 | 35 | // Use 'postCreateCommand' to run commands after the container is created. 36 | // "postCreateCommand": "rustc --version", 37 | 38 | // Configure tool-specific properties. 39 | // "customizations": {}, 40 | 41 | // Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. 42 | // "remoteUser": "root" 43 | } 44 | -------------------------------------------------------------------------------- /.funcignore: -------------------------------------------------------------------------------- 1 | .git* 2 | .vscode 3 | __azurite_db*__.json 4 | __blobstorage__ 5 | __queuestorage__ 6 | local.settings.json 7 | test 8 | # Prevent publishing the content of the target folder 9 | target -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Demo functions-actions 4 | 5 | on: 6 | workflow_dispatch: 7 | 8 | env: 9 | AZURE_FUNCTIONAPP_NAME: demo-rust-alfredo-2 # set this to your application's name, it has to be unique 10 | AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root 11 | 12 | jobs: 13 | build-and-deploy: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: 'Checkout GitHub action' 17 | uses: actions/checkout@v2 18 | 19 | - name: Install with RustUp 20 | shell: bash 21 | run: curl https://sh.rustup.rs -sSf | sh -s -- -y 22 | - name: Install musl 23 | run: sudo apt-get install -y --no-install-recommends musl-tools 24 | 25 | - name: Add Target 26 | shell: bash 27 | run: rustup target add x86_64-unknown-linux-musl 28 | 29 | - name: Build release 30 | shell: bash 31 | run: | 32 | cargo build --release --target=x86_64-unknown-linux-musl 33 | cp target/x86_64-unknown-linux-musl/release/handler . 34 | 35 | - name: Copy handler to parent directory 36 | shell: bash 37 | run: cp target/x86_64-unknown-linux-musl/release/handler . 38 | 39 | - name: Azure Login 40 | uses: azure/login@v1 41 | with: 42 | creds: ${{ secrets.AZURE_CREDENTIALS }} 43 | 44 | - name: 'Run Azure Functions action' 45 | uses: Azure/functions-action@v1 46 | with: 47 | app-name: ${{ env.AZURE_FUNCTIONAPP_NAME }} 48 | package: ${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }} 49 | respect-funcignore: true 50 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: Deploy Azure Function 4 | 5 | on: 6 | workflow_dispatch: 7 | 8 | env: 9 | AZURE_FUNCTIONAPP_NAME: demo-rust-alfredo # set this to your application's name, it has to be unique 10 | AZURE_GROUP_NAME: demo-function-rust 11 | AZURE_FUNCTIONAPP_PACKAGE_PATH: '.' # set this to the path to your web app project, defaults to the repository root 12 | 13 | jobs: 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout GitHub action' 18 | uses: actions/checkout@v2 19 | 20 | - name: Install with RustUp 21 | shell: bash 22 | run: curl https://sh.rustup.rs -sSf | sh -s -- -y 23 | 24 | - name: Install musl 25 | run: sudo apt-get install -y --no-install-recommends musl-tools 26 | 27 | - name: Add Linux MUSL Target 28 | shell: bash 29 | run: rustup target add x86_64-unknown-linux-musl 30 | 31 | - name: Build release 32 | shell: bash 33 | run: cargo build --release --target=x86_64-unknown-linux-musl 34 | 35 | - name: Copy handler to parent directory 36 | shell: bash 37 | run: cp target/x86_64-unknown-linux-musl/release/handler . 38 | 39 | # See https://github.com/Azure/azure-functions-core-tools#linux 40 | - name: Setup the repository 41 | shell: bash 42 | run: | 43 | curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg 44 | sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg 45 | sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list' 46 | 47 | - name: Install Azure Core Tools 48 | shell: bash 49 | run: | 50 | sudo apt-get update 51 | sudo apt-get install azure-functions-core-tools-4 52 | 53 | - name: Azure Login 54 | uses: azure/login@v1 55 | with: 56 | creds: ${{ secrets.AZURE_CREDENTIALS }} 57 | 58 | - name: Deploy to Azure Functions 59 | shell: bash 60 | run: func azure functionapp publish ${{ env.AZURE_FUNCTIONAPP_NAME }} --custom 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Rust 2 | debug/ 3 | target/ 4 | handler 5 | 6 | 7 | # Azure Functions artifacts 8 | bin 9 | obj 10 | appsettings.json 11 | local.settings.json 12 | 13 | # Azurite artifacts 14 | __blobstorage__ 15 | __queuestorage__ 16 | __azurite_db*__.json 17 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "ms-azuretools.vscode-azurefunctions" 4 | ] 5 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "azureFunctions.deploySubpath": ".", 3 | "azureFunctions.projectLanguage": "Custom", 4 | "azureFunctions.projectRuntime": "~4", 5 | "debug.internalConsoleOptions": "neverOpen", 6 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "type": "func", 6 | "label": "func: host start", 7 | "command": "host start", 8 | "problemMatcher": "$func-watch", 9 | "isBackground": true 10 | } 11 | ] 12 | } -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "actix-codec" 7 | version = "0.5.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe" 10 | dependencies = [ 11 | "bitflags", 12 | "bytes", 13 | "futures-core", 14 | "futures-sink", 15 | "log", 16 | "memchr", 17 | "pin-project-lite", 18 | "tokio", 19 | "tokio-util", 20 | ] 21 | 22 | [[package]] 23 | name = "actix-http" 24 | version = "3.3.0" 25 | source = "registry+https://github.com/rust-lang/crates.io-index" 26 | checksum = "0070905b2c4a98d184c4e81025253cb192aa8a73827553f38e9410801ceb35bb" 27 | dependencies = [ 28 | "actix-codec", 29 | "actix-rt", 30 | "actix-service", 31 | "actix-utils", 32 | "ahash", 33 | "base64", 34 | "bitflags", 35 | "brotli", 36 | "bytes", 37 | "bytestring", 38 | "derive_more", 39 | "encoding_rs", 40 | "flate2", 41 | "futures-core", 42 | "h2", 43 | "http", 44 | "httparse", 45 | "httpdate", 46 | "itoa", 47 | "language-tags", 48 | "local-channel", 49 | "mime", 50 | "percent-encoding", 51 | "pin-project-lite", 52 | "rand", 53 | "sha1", 54 | "smallvec", 55 | "tokio", 56 | "tokio-util", 57 | "tracing", 58 | "zstd", 59 | ] 60 | 61 | [[package]] 62 | name = "actix-macros" 63 | version = "0.2.3" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" 66 | dependencies = [ 67 | "quote", 68 | "syn", 69 | ] 70 | 71 | [[package]] 72 | name = "actix-router" 73 | version = "0.5.1" 74 | source = "registry+https://github.com/rust-lang/crates.io-index" 75 | checksum = "d66ff4d247d2b160861fa2866457e85706833527840e4133f8f49aa423a38799" 76 | dependencies = [ 77 | "bytestring", 78 | "http", 79 | "regex", 80 | "serde", 81 | "tracing", 82 | ] 83 | 84 | [[package]] 85 | name = "actix-rt" 86 | version = "2.8.0" 87 | source = "registry+https://github.com/rust-lang/crates.io-index" 88 | checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e" 89 | dependencies = [ 90 | "futures-core", 91 | "tokio", 92 | ] 93 | 94 | [[package]] 95 | name = "actix-server" 96 | version = "2.2.0" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327" 99 | dependencies = [ 100 | "actix-rt", 101 | "actix-service", 102 | "actix-utils", 103 | "futures-core", 104 | "futures-util", 105 | "mio", 106 | "num_cpus", 107 | "socket2", 108 | "tokio", 109 | "tracing", 110 | ] 111 | 112 | [[package]] 113 | name = "actix-service" 114 | version = "2.0.2" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" 117 | dependencies = [ 118 | "futures-core", 119 | "paste", 120 | "pin-project-lite", 121 | ] 122 | 123 | [[package]] 124 | name = "actix-utils" 125 | version = "3.0.1" 126 | source = "registry+https://github.com/rust-lang/crates.io-index" 127 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 128 | dependencies = [ 129 | "local-waker", 130 | "pin-project-lite", 131 | ] 132 | 133 | [[package]] 134 | name = "actix-web" 135 | version = "4.3.0" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "464e0fddc668ede5f26ec1f9557a8d44eda948732f40c6b0ad79126930eb775f" 138 | dependencies = [ 139 | "actix-codec", 140 | "actix-http", 141 | "actix-macros", 142 | "actix-router", 143 | "actix-rt", 144 | "actix-server", 145 | "actix-service", 146 | "actix-utils", 147 | "actix-web-codegen", 148 | "ahash", 149 | "bytes", 150 | "bytestring", 151 | "cfg-if", 152 | "cookie", 153 | "derive_more", 154 | "encoding_rs", 155 | "futures-core", 156 | "futures-util", 157 | "http", 158 | "itoa", 159 | "language-tags", 160 | "log", 161 | "mime", 162 | "once_cell", 163 | "pin-project-lite", 164 | "regex", 165 | "serde", 166 | "serde_json", 167 | "serde_urlencoded", 168 | "smallvec", 169 | "socket2", 170 | "time", 171 | "url", 172 | ] 173 | 174 | [[package]] 175 | name = "actix-web-codegen" 176 | version = "4.1.0" 177 | source = "registry+https://github.com/rust-lang/crates.io-index" 178 | checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" 179 | dependencies = [ 180 | "actix-router", 181 | "proc-macro2", 182 | "quote", 183 | "syn", 184 | ] 185 | 186 | [[package]] 187 | name = "adler" 188 | version = "1.0.2" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" 191 | 192 | [[package]] 193 | name = "ahash" 194 | version = "0.7.6" 195 | source = "registry+https://github.com/rust-lang/crates.io-index" 196 | checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 197 | dependencies = [ 198 | "getrandom", 199 | "once_cell", 200 | "version_check", 201 | ] 202 | 203 | [[package]] 204 | name = "aho-corasick" 205 | version = "0.7.20" 206 | source = "registry+https://github.com/rust-lang/crates.io-index" 207 | checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" 208 | dependencies = [ 209 | "memchr", 210 | ] 211 | 212 | [[package]] 213 | name = "alloc-no-stdlib" 214 | version = "2.0.4" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 217 | 218 | [[package]] 219 | name = "alloc-stdlib" 220 | version = "0.2.2" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 223 | dependencies = [ 224 | "alloc-no-stdlib", 225 | ] 226 | 227 | [[package]] 228 | name = "autocfg" 229 | version = "1.1.0" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 232 | 233 | [[package]] 234 | name = "base64" 235 | version = "0.21.0" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" 238 | 239 | [[package]] 240 | name = "bitflags" 241 | version = "1.3.2" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 244 | 245 | [[package]] 246 | name = "block-buffer" 247 | version = "0.10.3" 248 | source = "registry+https://github.com/rust-lang/crates.io-index" 249 | checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" 250 | dependencies = [ 251 | "generic-array", 252 | ] 253 | 254 | [[package]] 255 | name = "brotli" 256 | version = "3.3.4" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "a1a0b1dbcc8ae29329621f8d4f0d835787c1c38bb1401979b49d13b0b305ff68" 259 | dependencies = [ 260 | "alloc-no-stdlib", 261 | "alloc-stdlib", 262 | "brotli-decompressor", 263 | ] 264 | 265 | [[package]] 266 | name = "brotli-decompressor" 267 | version = "2.3.4" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744" 270 | dependencies = [ 271 | "alloc-no-stdlib", 272 | "alloc-stdlib", 273 | ] 274 | 275 | [[package]] 276 | name = "bytes" 277 | version = "1.4.0" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" 280 | 281 | [[package]] 282 | name = "bytestring" 283 | version = "1.2.0" 284 | source = "registry+https://github.com/rust-lang/crates.io-index" 285 | checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" 286 | dependencies = [ 287 | "bytes", 288 | ] 289 | 290 | [[package]] 291 | name = "cc" 292 | version = "1.0.79" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" 295 | dependencies = [ 296 | "jobserver", 297 | ] 298 | 299 | [[package]] 300 | name = "cfg-if" 301 | version = "1.0.0" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 304 | 305 | [[package]] 306 | name = "convert_case" 307 | version = "0.4.0" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 310 | 311 | [[package]] 312 | name = "cookie" 313 | version = "0.16.2" 314 | source = "registry+https://github.com/rust-lang/crates.io-index" 315 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" 316 | dependencies = [ 317 | "percent-encoding", 318 | "time", 319 | "version_check", 320 | ] 321 | 322 | [[package]] 323 | name = "cpufeatures" 324 | version = "0.2.5" 325 | source = "registry+https://github.com/rust-lang/crates.io-index" 326 | checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" 327 | dependencies = [ 328 | "libc", 329 | ] 330 | 331 | [[package]] 332 | name = "crc32fast" 333 | version = "1.3.2" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" 336 | dependencies = [ 337 | "cfg-if", 338 | ] 339 | 340 | [[package]] 341 | name = "crypto-common" 342 | version = "0.1.6" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 345 | dependencies = [ 346 | "generic-array", 347 | "typenum", 348 | ] 349 | 350 | [[package]] 351 | name = "derive_more" 352 | version = "0.99.17" 353 | source = "registry+https://github.com/rust-lang/crates.io-index" 354 | checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" 355 | dependencies = [ 356 | "convert_case", 357 | "proc-macro2", 358 | "quote", 359 | "rustc_version", 360 | "syn", 361 | ] 362 | 363 | [[package]] 364 | name = "digest" 365 | version = "0.10.6" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" 368 | dependencies = [ 369 | "block-buffer", 370 | "crypto-common", 371 | ] 372 | 373 | [[package]] 374 | name = "encoding_rs" 375 | version = "0.8.32" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" 378 | dependencies = [ 379 | "cfg-if", 380 | ] 381 | 382 | [[package]] 383 | name = "env_logger" 384 | version = "0.10.0" 385 | source = "registry+https://github.com/rust-lang/crates.io-index" 386 | checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" 387 | dependencies = [ 388 | "humantime", 389 | "is-terminal", 390 | "log", 391 | "regex", 392 | "termcolor", 393 | ] 394 | 395 | [[package]] 396 | name = "errno" 397 | version = "0.2.8" 398 | source = "registry+https://github.com/rust-lang/crates.io-index" 399 | checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" 400 | dependencies = [ 401 | "errno-dragonfly", 402 | "libc", 403 | "winapi", 404 | ] 405 | 406 | [[package]] 407 | name = "errno-dragonfly" 408 | version = "0.1.2" 409 | source = "registry+https://github.com/rust-lang/crates.io-index" 410 | checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" 411 | dependencies = [ 412 | "cc", 413 | "libc", 414 | ] 415 | 416 | [[package]] 417 | name = "flate2" 418 | version = "1.0.25" 419 | source = "registry+https://github.com/rust-lang/crates.io-index" 420 | checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" 421 | dependencies = [ 422 | "crc32fast", 423 | "miniz_oxide", 424 | ] 425 | 426 | [[package]] 427 | name = "fnv" 428 | version = "1.0.7" 429 | source = "registry+https://github.com/rust-lang/crates.io-index" 430 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 431 | 432 | [[package]] 433 | name = "form_urlencoded" 434 | version = "1.1.0" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" 437 | dependencies = [ 438 | "percent-encoding", 439 | ] 440 | 441 | [[package]] 442 | name = "futures-core" 443 | version = "0.3.26" 444 | source = "registry+https://github.com/rust-lang/crates.io-index" 445 | checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608" 446 | 447 | [[package]] 448 | name = "futures-sink" 449 | version = "0.3.26" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364" 452 | 453 | [[package]] 454 | name = "futures-task" 455 | version = "0.3.26" 456 | source = "registry+https://github.com/rust-lang/crates.io-index" 457 | checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366" 458 | 459 | [[package]] 460 | name = "futures-util" 461 | version = "0.3.26" 462 | source = "registry+https://github.com/rust-lang/crates.io-index" 463 | checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1" 464 | dependencies = [ 465 | "futures-core", 466 | "futures-task", 467 | "pin-project-lite", 468 | "pin-utils", 469 | ] 470 | 471 | [[package]] 472 | name = "generic-array" 473 | version = "0.14.6" 474 | source = "registry+https://github.com/rust-lang/crates.io-index" 475 | checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" 476 | dependencies = [ 477 | "typenum", 478 | "version_check", 479 | ] 480 | 481 | [[package]] 482 | name = "getrandom" 483 | version = "0.2.8" 484 | source = "registry+https://github.com/rust-lang/crates.io-index" 485 | checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" 486 | dependencies = [ 487 | "cfg-if", 488 | "libc", 489 | "wasi", 490 | ] 491 | 492 | [[package]] 493 | name = "h2" 494 | version = "0.3.15" 495 | source = "registry+https://github.com/rust-lang/crates.io-index" 496 | checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4" 497 | dependencies = [ 498 | "bytes", 499 | "fnv", 500 | "futures-core", 501 | "futures-sink", 502 | "futures-util", 503 | "http", 504 | "indexmap", 505 | "slab", 506 | "tokio", 507 | "tokio-util", 508 | "tracing", 509 | ] 510 | 511 | [[package]] 512 | name = "handler" 513 | version = "0.1.0" 514 | dependencies = [ 515 | "actix-web", 516 | "env_logger", 517 | "serde", 518 | "sha2", 519 | ] 520 | 521 | [[package]] 522 | name = "hashbrown" 523 | version = "0.12.3" 524 | source = "registry+https://github.com/rust-lang/crates.io-index" 525 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 526 | 527 | [[package]] 528 | name = "hermit-abi" 529 | version = "0.2.6" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" 532 | dependencies = [ 533 | "libc", 534 | ] 535 | 536 | [[package]] 537 | name = "hermit-abi" 538 | version = "0.3.1" 539 | source = "registry+https://github.com/rust-lang/crates.io-index" 540 | checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" 541 | 542 | [[package]] 543 | name = "http" 544 | version = "0.2.8" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" 547 | dependencies = [ 548 | "bytes", 549 | "fnv", 550 | "itoa", 551 | ] 552 | 553 | [[package]] 554 | name = "httparse" 555 | version = "1.8.0" 556 | source = "registry+https://github.com/rust-lang/crates.io-index" 557 | checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" 558 | 559 | [[package]] 560 | name = "httpdate" 561 | version = "1.0.2" 562 | source = "registry+https://github.com/rust-lang/crates.io-index" 563 | checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" 564 | 565 | [[package]] 566 | name = "humantime" 567 | version = "2.1.0" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" 570 | 571 | [[package]] 572 | name = "idna" 573 | version = "0.3.0" 574 | source = "registry+https://github.com/rust-lang/crates.io-index" 575 | checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" 576 | dependencies = [ 577 | "unicode-bidi", 578 | "unicode-normalization", 579 | ] 580 | 581 | [[package]] 582 | name = "indexmap" 583 | version = "1.9.2" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" 586 | dependencies = [ 587 | "autocfg", 588 | "hashbrown", 589 | ] 590 | 591 | [[package]] 592 | name = "io-lifetimes" 593 | version = "1.0.5" 594 | source = "registry+https://github.com/rust-lang/crates.io-index" 595 | checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3" 596 | dependencies = [ 597 | "libc", 598 | "windows-sys 0.45.0", 599 | ] 600 | 601 | [[package]] 602 | name = "is-terminal" 603 | version = "0.4.3" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "22e18b0a45d56fe973d6db23972bf5bc46f988a4a2385deac9cc29572f09daef" 606 | dependencies = [ 607 | "hermit-abi 0.3.1", 608 | "io-lifetimes", 609 | "rustix", 610 | "windows-sys 0.45.0", 611 | ] 612 | 613 | [[package]] 614 | name = "itoa" 615 | version = "1.0.5" 616 | source = "registry+https://github.com/rust-lang/crates.io-index" 617 | checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" 618 | 619 | [[package]] 620 | name = "jobserver" 621 | version = "0.1.25" 622 | source = "registry+https://github.com/rust-lang/crates.io-index" 623 | checksum = "068b1ee6743e4d11fb9c6a1e6064b3693a1b600e7f5f5988047d98b3dc9fb90b" 624 | dependencies = [ 625 | "libc", 626 | ] 627 | 628 | [[package]] 629 | name = "language-tags" 630 | version = "0.3.2" 631 | source = "registry+https://github.com/rust-lang/crates.io-index" 632 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 633 | 634 | [[package]] 635 | name = "libc" 636 | version = "0.2.139" 637 | source = "registry+https://github.com/rust-lang/crates.io-index" 638 | checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" 639 | 640 | [[package]] 641 | name = "linux-raw-sys" 642 | version = "0.1.4" 643 | source = "registry+https://github.com/rust-lang/crates.io-index" 644 | checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" 645 | 646 | [[package]] 647 | name = "local-channel" 648 | version = "0.1.3" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" 651 | dependencies = [ 652 | "futures-core", 653 | "futures-sink", 654 | "futures-util", 655 | "local-waker", 656 | ] 657 | 658 | [[package]] 659 | name = "local-waker" 660 | version = "0.1.3" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" 663 | 664 | [[package]] 665 | name = "lock_api" 666 | version = "0.4.9" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 669 | dependencies = [ 670 | "autocfg", 671 | "scopeguard", 672 | ] 673 | 674 | [[package]] 675 | name = "log" 676 | version = "0.4.17" 677 | source = "registry+https://github.com/rust-lang/crates.io-index" 678 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 679 | dependencies = [ 680 | "cfg-if", 681 | ] 682 | 683 | [[package]] 684 | name = "memchr" 685 | version = "2.5.0" 686 | source = "registry+https://github.com/rust-lang/crates.io-index" 687 | checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" 688 | 689 | [[package]] 690 | name = "mime" 691 | version = "0.3.16" 692 | source = "registry+https://github.com/rust-lang/crates.io-index" 693 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 694 | 695 | [[package]] 696 | name = "miniz_oxide" 697 | version = "0.6.2" 698 | source = "registry+https://github.com/rust-lang/crates.io-index" 699 | checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" 700 | dependencies = [ 701 | "adler", 702 | ] 703 | 704 | [[package]] 705 | name = "mio" 706 | version = "0.8.5" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de" 709 | dependencies = [ 710 | "libc", 711 | "log", 712 | "wasi", 713 | "windows-sys 0.42.0", 714 | ] 715 | 716 | [[package]] 717 | name = "num_cpus" 718 | version = "1.15.0" 719 | source = "registry+https://github.com/rust-lang/crates.io-index" 720 | checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" 721 | dependencies = [ 722 | "hermit-abi 0.2.6", 723 | "libc", 724 | ] 725 | 726 | [[package]] 727 | name = "once_cell" 728 | version = "1.17.0" 729 | source = "registry+https://github.com/rust-lang/crates.io-index" 730 | checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" 731 | 732 | [[package]] 733 | name = "parking_lot" 734 | version = "0.12.1" 735 | source = "registry+https://github.com/rust-lang/crates.io-index" 736 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 737 | dependencies = [ 738 | "lock_api", 739 | "parking_lot_core", 740 | ] 741 | 742 | [[package]] 743 | name = "parking_lot_core" 744 | version = "0.9.7" 745 | source = "registry+https://github.com/rust-lang/crates.io-index" 746 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 747 | dependencies = [ 748 | "cfg-if", 749 | "libc", 750 | "redox_syscall", 751 | "smallvec", 752 | "windows-sys 0.45.0", 753 | ] 754 | 755 | [[package]] 756 | name = "paste" 757 | version = "1.0.11" 758 | source = "registry+https://github.com/rust-lang/crates.io-index" 759 | checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" 760 | 761 | [[package]] 762 | name = "percent-encoding" 763 | version = "2.2.0" 764 | source = "registry+https://github.com/rust-lang/crates.io-index" 765 | checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" 766 | 767 | [[package]] 768 | name = "pin-project-lite" 769 | version = "0.2.9" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" 772 | 773 | [[package]] 774 | name = "pin-utils" 775 | version = "0.1.0" 776 | source = "registry+https://github.com/rust-lang/crates.io-index" 777 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 778 | 779 | [[package]] 780 | name = "pkg-config" 781 | version = "0.3.26" 782 | source = "registry+https://github.com/rust-lang/crates.io-index" 783 | checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" 784 | 785 | [[package]] 786 | name = "ppv-lite86" 787 | version = "0.2.17" 788 | source = "registry+https://github.com/rust-lang/crates.io-index" 789 | checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" 790 | 791 | [[package]] 792 | name = "proc-macro2" 793 | version = "1.0.51" 794 | source = "registry+https://github.com/rust-lang/crates.io-index" 795 | checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" 796 | dependencies = [ 797 | "unicode-ident", 798 | ] 799 | 800 | [[package]] 801 | name = "quote" 802 | version = "1.0.23" 803 | source = "registry+https://github.com/rust-lang/crates.io-index" 804 | checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" 805 | dependencies = [ 806 | "proc-macro2", 807 | ] 808 | 809 | [[package]] 810 | name = "rand" 811 | version = "0.8.5" 812 | source = "registry+https://github.com/rust-lang/crates.io-index" 813 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 814 | dependencies = [ 815 | "libc", 816 | "rand_chacha", 817 | "rand_core", 818 | ] 819 | 820 | [[package]] 821 | name = "rand_chacha" 822 | version = "0.3.1" 823 | source = "registry+https://github.com/rust-lang/crates.io-index" 824 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 825 | dependencies = [ 826 | "ppv-lite86", 827 | "rand_core", 828 | ] 829 | 830 | [[package]] 831 | name = "rand_core" 832 | version = "0.6.4" 833 | source = "registry+https://github.com/rust-lang/crates.io-index" 834 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 835 | dependencies = [ 836 | "getrandom", 837 | ] 838 | 839 | [[package]] 840 | name = "redox_syscall" 841 | version = "0.2.16" 842 | source = "registry+https://github.com/rust-lang/crates.io-index" 843 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 844 | dependencies = [ 845 | "bitflags", 846 | ] 847 | 848 | [[package]] 849 | name = "regex" 850 | version = "1.7.1" 851 | source = "registry+https://github.com/rust-lang/crates.io-index" 852 | checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733" 853 | dependencies = [ 854 | "aho-corasick", 855 | "memchr", 856 | "regex-syntax", 857 | ] 858 | 859 | [[package]] 860 | name = "regex-syntax" 861 | version = "0.6.28" 862 | source = "registry+https://github.com/rust-lang/crates.io-index" 863 | checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" 864 | 865 | [[package]] 866 | name = "rustc_version" 867 | version = "0.4.0" 868 | source = "registry+https://github.com/rust-lang/crates.io-index" 869 | checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" 870 | dependencies = [ 871 | "semver", 872 | ] 873 | 874 | [[package]] 875 | name = "rustix" 876 | version = "0.36.8" 877 | source = "registry+https://github.com/rust-lang/crates.io-index" 878 | checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644" 879 | dependencies = [ 880 | "bitflags", 881 | "errno", 882 | "io-lifetimes", 883 | "libc", 884 | "linux-raw-sys", 885 | "windows-sys 0.45.0", 886 | ] 887 | 888 | [[package]] 889 | name = "ryu" 890 | version = "1.0.12" 891 | source = "registry+https://github.com/rust-lang/crates.io-index" 892 | checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" 893 | 894 | [[package]] 895 | name = "scopeguard" 896 | version = "1.1.0" 897 | source = "registry+https://github.com/rust-lang/crates.io-index" 898 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 899 | 900 | [[package]] 901 | name = "semver" 902 | version = "1.0.16" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" 905 | 906 | [[package]] 907 | name = "serde" 908 | version = "1.0.152" 909 | source = "registry+https://github.com/rust-lang/crates.io-index" 910 | checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" 911 | dependencies = [ 912 | "serde_derive", 913 | ] 914 | 915 | [[package]] 916 | name = "serde_derive" 917 | version = "1.0.152" 918 | source = "registry+https://github.com/rust-lang/crates.io-index" 919 | checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" 920 | dependencies = [ 921 | "proc-macro2", 922 | "quote", 923 | "syn", 924 | ] 925 | 926 | [[package]] 927 | name = "serde_json" 928 | version = "1.0.93" 929 | source = "registry+https://github.com/rust-lang/crates.io-index" 930 | checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76" 931 | dependencies = [ 932 | "itoa", 933 | "ryu", 934 | "serde", 935 | ] 936 | 937 | [[package]] 938 | name = "serde_urlencoded" 939 | version = "0.7.1" 940 | source = "registry+https://github.com/rust-lang/crates.io-index" 941 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 942 | dependencies = [ 943 | "form_urlencoded", 944 | "itoa", 945 | "ryu", 946 | "serde", 947 | ] 948 | 949 | [[package]] 950 | name = "sha1" 951 | version = "0.10.5" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" 954 | dependencies = [ 955 | "cfg-if", 956 | "cpufeatures", 957 | "digest", 958 | ] 959 | 960 | [[package]] 961 | name = "sha2" 962 | version = "0.10.6" 963 | source = "registry+https://github.com/rust-lang/crates.io-index" 964 | checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" 965 | dependencies = [ 966 | "cfg-if", 967 | "cpufeatures", 968 | "digest", 969 | ] 970 | 971 | [[package]] 972 | name = "signal-hook-registry" 973 | version = "1.4.0" 974 | source = "registry+https://github.com/rust-lang/crates.io-index" 975 | checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0" 976 | dependencies = [ 977 | "libc", 978 | ] 979 | 980 | [[package]] 981 | name = "slab" 982 | version = "0.4.7" 983 | source = "registry+https://github.com/rust-lang/crates.io-index" 984 | checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" 985 | dependencies = [ 986 | "autocfg", 987 | ] 988 | 989 | [[package]] 990 | name = "smallvec" 991 | version = "1.10.0" 992 | source = "registry+https://github.com/rust-lang/crates.io-index" 993 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 994 | 995 | [[package]] 996 | name = "socket2" 997 | version = "0.4.7" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd" 1000 | dependencies = [ 1001 | "libc", 1002 | "winapi", 1003 | ] 1004 | 1005 | [[package]] 1006 | name = "syn" 1007 | version = "1.0.107" 1008 | source = "registry+https://github.com/rust-lang/crates.io-index" 1009 | checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" 1010 | dependencies = [ 1011 | "proc-macro2", 1012 | "quote", 1013 | "unicode-ident", 1014 | ] 1015 | 1016 | [[package]] 1017 | name = "termcolor" 1018 | version = "1.2.0" 1019 | source = "registry+https://github.com/rust-lang/crates.io-index" 1020 | checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" 1021 | dependencies = [ 1022 | "winapi-util", 1023 | ] 1024 | 1025 | [[package]] 1026 | name = "time" 1027 | version = "0.3.17" 1028 | source = "registry+https://github.com/rust-lang/crates.io-index" 1029 | checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" 1030 | dependencies = [ 1031 | "itoa", 1032 | "serde", 1033 | "time-core", 1034 | "time-macros", 1035 | ] 1036 | 1037 | [[package]] 1038 | name = "time-core" 1039 | version = "0.1.0" 1040 | source = "registry+https://github.com/rust-lang/crates.io-index" 1041 | checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" 1042 | 1043 | [[package]] 1044 | name = "time-macros" 1045 | version = "0.2.6" 1046 | source = "registry+https://github.com/rust-lang/crates.io-index" 1047 | checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" 1048 | dependencies = [ 1049 | "time-core", 1050 | ] 1051 | 1052 | [[package]] 1053 | name = "tinyvec" 1054 | version = "1.6.0" 1055 | source = "registry+https://github.com/rust-lang/crates.io-index" 1056 | checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" 1057 | dependencies = [ 1058 | "tinyvec_macros", 1059 | ] 1060 | 1061 | [[package]] 1062 | name = "tinyvec_macros" 1063 | version = "0.1.1" 1064 | source = "registry+https://github.com/rust-lang/crates.io-index" 1065 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 1066 | 1067 | [[package]] 1068 | name = "tokio" 1069 | version = "1.25.0" 1070 | source = "registry+https://github.com/rust-lang/crates.io-index" 1071 | checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af" 1072 | dependencies = [ 1073 | "autocfg", 1074 | "bytes", 1075 | "libc", 1076 | "memchr", 1077 | "mio", 1078 | "parking_lot", 1079 | "pin-project-lite", 1080 | "signal-hook-registry", 1081 | "socket2", 1082 | "windows-sys 0.42.0", 1083 | ] 1084 | 1085 | [[package]] 1086 | name = "tokio-util" 1087 | version = "0.7.6" 1088 | source = "registry+https://github.com/rust-lang/crates.io-index" 1089 | checksum = "bc6a3b08b64e6dfad376fa2432c7b1f01522e37a623c3050bc95db2d3ff21583" 1090 | dependencies = [ 1091 | "bytes", 1092 | "futures-core", 1093 | "futures-sink", 1094 | "pin-project-lite", 1095 | "tokio", 1096 | "tracing", 1097 | ] 1098 | 1099 | [[package]] 1100 | name = "tracing" 1101 | version = "0.1.37" 1102 | source = "registry+https://github.com/rust-lang/crates.io-index" 1103 | checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" 1104 | dependencies = [ 1105 | "cfg-if", 1106 | "log", 1107 | "pin-project-lite", 1108 | "tracing-core", 1109 | ] 1110 | 1111 | [[package]] 1112 | name = "tracing-core" 1113 | version = "0.1.30" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" 1116 | dependencies = [ 1117 | "once_cell", 1118 | ] 1119 | 1120 | [[package]] 1121 | name = "typenum" 1122 | version = "1.16.0" 1123 | source = "registry+https://github.com/rust-lang/crates.io-index" 1124 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 1125 | 1126 | [[package]] 1127 | name = "unicode-bidi" 1128 | version = "0.3.10" 1129 | source = "registry+https://github.com/rust-lang/crates.io-index" 1130 | checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58" 1131 | 1132 | [[package]] 1133 | name = "unicode-ident" 1134 | version = "1.0.6" 1135 | source = "registry+https://github.com/rust-lang/crates.io-index" 1136 | checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" 1137 | 1138 | [[package]] 1139 | name = "unicode-normalization" 1140 | version = "0.1.22" 1141 | source = "registry+https://github.com/rust-lang/crates.io-index" 1142 | checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" 1143 | dependencies = [ 1144 | "tinyvec", 1145 | ] 1146 | 1147 | [[package]] 1148 | name = "url" 1149 | version = "2.3.1" 1150 | source = "registry+https://github.com/rust-lang/crates.io-index" 1151 | checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" 1152 | dependencies = [ 1153 | "form_urlencoded", 1154 | "idna", 1155 | "percent-encoding", 1156 | ] 1157 | 1158 | [[package]] 1159 | name = "version_check" 1160 | version = "0.9.4" 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" 1162 | checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" 1163 | 1164 | [[package]] 1165 | name = "wasi" 1166 | version = "0.11.0+wasi-snapshot-preview1" 1167 | source = "registry+https://github.com/rust-lang/crates.io-index" 1168 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 1169 | 1170 | [[package]] 1171 | name = "winapi" 1172 | version = "0.3.9" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1175 | dependencies = [ 1176 | "winapi-i686-pc-windows-gnu", 1177 | "winapi-x86_64-pc-windows-gnu", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "winapi-i686-pc-windows-gnu" 1182 | version = "0.4.0" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1185 | 1186 | [[package]] 1187 | name = "winapi-util" 1188 | version = "0.1.5" 1189 | source = "registry+https://github.com/rust-lang/crates.io-index" 1190 | checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" 1191 | dependencies = [ 1192 | "winapi", 1193 | ] 1194 | 1195 | [[package]] 1196 | name = "winapi-x86_64-pc-windows-gnu" 1197 | version = "0.4.0" 1198 | source = "registry+https://github.com/rust-lang/crates.io-index" 1199 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1200 | 1201 | [[package]] 1202 | name = "windows-sys" 1203 | version = "0.42.0" 1204 | source = "registry+https://github.com/rust-lang/crates.io-index" 1205 | checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" 1206 | dependencies = [ 1207 | "windows_aarch64_gnullvm", 1208 | "windows_aarch64_msvc", 1209 | "windows_i686_gnu", 1210 | "windows_i686_msvc", 1211 | "windows_x86_64_gnu", 1212 | "windows_x86_64_gnullvm", 1213 | "windows_x86_64_msvc", 1214 | ] 1215 | 1216 | [[package]] 1217 | name = "windows-sys" 1218 | version = "0.45.0" 1219 | source = "registry+https://github.com/rust-lang/crates.io-index" 1220 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 1221 | dependencies = [ 1222 | "windows-targets", 1223 | ] 1224 | 1225 | [[package]] 1226 | name = "windows-targets" 1227 | version = "0.42.1" 1228 | source = "registry+https://github.com/rust-lang/crates.io-index" 1229 | checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7" 1230 | dependencies = [ 1231 | "windows_aarch64_gnullvm", 1232 | "windows_aarch64_msvc", 1233 | "windows_i686_gnu", 1234 | "windows_i686_msvc", 1235 | "windows_x86_64_gnu", 1236 | "windows_x86_64_gnullvm", 1237 | "windows_x86_64_msvc", 1238 | ] 1239 | 1240 | [[package]] 1241 | name = "windows_aarch64_gnullvm" 1242 | version = "0.42.1" 1243 | source = "registry+https://github.com/rust-lang/crates.io-index" 1244 | checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608" 1245 | 1246 | [[package]] 1247 | name = "windows_aarch64_msvc" 1248 | version = "0.42.1" 1249 | source = "registry+https://github.com/rust-lang/crates.io-index" 1250 | checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7" 1251 | 1252 | [[package]] 1253 | name = "windows_i686_gnu" 1254 | version = "0.42.1" 1255 | source = "registry+https://github.com/rust-lang/crates.io-index" 1256 | checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640" 1257 | 1258 | [[package]] 1259 | name = "windows_i686_msvc" 1260 | version = "0.42.1" 1261 | source = "registry+https://github.com/rust-lang/crates.io-index" 1262 | checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605" 1263 | 1264 | [[package]] 1265 | name = "windows_x86_64_gnu" 1266 | version = "0.42.1" 1267 | source = "registry+https://github.com/rust-lang/crates.io-index" 1268 | checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45" 1269 | 1270 | [[package]] 1271 | name = "windows_x86_64_gnullvm" 1272 | version = "0.42.1" 1273 | source = "registry+https://github.com/rust-lang/crates.io-index" 1274 | checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463" 1275 | 1276 | [[package]] 1277 | name = "windows_x86_64_msvc" 1278 | version = "0.42.1" 1279 | source = "registry+https://github.com/rust-lang/crates.io-index" 1280 | checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd" 1281 | 1282 | [[package]] 1283 | name = "zstd" 1284 | version = "0.12.3+zstd.1.5.2" 1285 | source = "registry+https://github.com/rust-lang/crates.io-index" 1286 | checksum = "76eea132fb024e0e13fd9c2f5d5d595d8a967aa72382ac2f9d39fcc95afd0806" 1287 | dependencies = [ 1288 | "zstd-safe", 1289 | ] 1290 | 1291 | [[package]] 1292 | name = "zstd-safe" 1293 | version = "6.0.4+zstd.1.5.4" 1294 | source = "registry+https://github.com/rust-lang/crates.io-index" 1295 | checksum = "7afb4b54b8910cf5447638cb54bf4e8a65cbedd783af98b98c62ffe91f185543" 1296 | dependencies = [ 1297 | "libc", 1298 | "zstd-sys", 1299 | ] 1300 | 1301 | [[package]] 1302 | name = "zstd-sys" 1303 | version = "2.0.7+zstd.1.5.4" 1304 | source = "registry+https://github.com/rust-lang/crates.io-index" 1305 | checksum = "94509c3ba2fe55294d752b79842c530ccfab760192521df74a081a78d2b3c7f5" 1306 | dependencies = [ 1307 | "cc", 1308 | "libc", 1309 | "pkg-config", 1310 | ] 1311 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "handler" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | actix-web = "4" 10 | env_logger = "0.10.0" 11 | serde = { version = "1.0", features = ["derive"] } 12 | sha2 = "0.10.6" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Alfredo Deza 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deploy Rust as an Azure Function 2 | Continuous deployment to Azure Functions using Rust and GitHub Actions. This repository contains a sample Rust application that can be deployed to Azure Functions using GitHub Actions. Although not a requirement it is easier to use [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-0000-alfredodeza) for development. 3 | 4 | This repository is part of a [Coursera MLOps course offered by Duke University](https://www.coursera.org/learn/mlops-aws-azure-duke) 5 | 6 | ## Prerequisites 7 | - [Azure account](https://azure.microsoft.com/free/?WT.mc_id=academic-0000-alfredodeza) 8 | - [Rust](https://www.rust-lang.org/tools/install) 9 | - [Azure Functions Core Tools](https://docs.microsoft.com/azure/azure-functions/functions-run-local?WT.mc_id=academic-0000-alfredodeza) 10 | - [Visual Studio Code](https://code.visualstudio.com/?WT.mc_id=academic-0000-alfredodeza) 11 | - [Azure Functions extension for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-azurefunctions&WT.mc_id=academic-0000-alfredodeza) 12 | 13 | This repository is also Codespaces ready, so you can use it directly from GitHub. The only requirement left would be to ensure you have an Azure account. 14 | 15 | Use the following [link](https://learn.microsoft.com/azure/azure-functions/create-first-function-vs-code-other?tabs=go%2Cmacos&WT.mc_id=academic-0000-alfredodeza) as a reference to the Azure documentation 16 | 17 | ## Running the application locally with Azure Functions Core Tools 18 | 1. Install the dependencies with `cargo build` 19 | 2. Start the Azure Functions Core Tools with `func start` (this feature is already installed with Codespaces) 20 | 3. Send a `curl` request to generate a JSON response 21 | 22 | ```bash 23 | curl --header "Content-Type: application/json" \ 24 | --request POST \ 25 | --data '{"text":"example string"}' \ 26 | http://localhost:7071/api/token 27 | ``` 28 | 29 | ## Creating the Azure Function in the Azure Portal 30 | Use a unique name for the function app. This name will be used in the GitHub Actions workflow to deploy the application to Azure Functions. The name must be unique across all Azure Functions. 31 | 32 | For the _Runtime stack_ select _Custom Handler_ and for the _version_ select _custom_ as well. 33 | 34 | Select _Linux_ as the _Operating System_ and any region like _East US_. 35 | 36 | Once the function app is created, click on _Get Publish Profile_ and add it as a secret to the GitHub repository. The name of the secret should be `AZURE_FUNCTIONAPP_PUBLISH_PROFILE` and the value should be the content of the downloaded file. 37 | 38 | ## Deploying with VSCode 39 | Although you can deploy directlty from VSCode, you might encounter the following error when you try to re-deploy using a different method: 40 | 41 | ``` 42 | Error: When request Azure resource at PublishContent, zipDepoy : WEBSITE_RUN_FROM_PACKAGE in your function app is set to an URL. Please remove WEBSITE_RUN_FROM_PACKAGE app setting from your function app. 43 | ``` 44 | 45 | This setting was created by the VSCode extension, so you must go to the portal, then to the function, next to Configuration, and then Application Settings, and delete `WEBSITE_RUN_FROM_PACKAGE` 46 | 47 | ## Deploying with GitHub Actions 48 | The workflow is defined in the `.github/workflows/main.yml` file. The workflow is set to be triggered manually via the `workflow_dispatch` setting. You can change this to trigger when a new commit is pushed to the `main` branch. The workflow will build the application and deploy it to Azure Functions. 49 | 50 | The only requirement is to add the `AZURE_CREDENTIALS` secret to the repository. The value of the secret should be the output of the following command: 51 | 52 | ```bash 53 | az ad sp create-for-rbac --name "rust-azure-function" --sdk-auth --role contributor --scopes /subscriptions//resourceGroups/ 54 | ``` 55 | 56 | The resulting output should look like: 57 | 58 | ``` 59 | { 60 | "clientId": "", 61 | "clientSecret": "", 62 | "subscriptionId": "", 63 | "tenantId": "", 64 | (...) 65 | } 66 | ``` 67 | 68 | Copy those contents into the actions secrets as `AZURE_CREDENTIALS`. This secret is used in the workflow to authenticate with Azure. 69 | 70 | ### Caveats 71 | Currently, Rust is not a _first class citizen_ in Azure Functions. This means that the deployment process is a bit more involved than other languages. If creating the function scaffolding in Visual Studio Code, you must select _"custom"_ for the runtime, whereas other languages have their own category. 72 | 73 | Deploying using the GitHub Actions for Functions _does not work_ at the moment. The workflow will succeed but the function will timeout when invoked with an HTTP 500. The GitHub workflow uses instead the Azure Core Tools to deploy the function with the `func` command. This is a workaround until the GitHub Actions for Functions [is fixed](https://github.com/Azure/functions-action/issues/169). 74 | -------------------------------------------------------------------------------- /host.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0", 3 | "logging": { 4 | "logLevel": { 5 | "default": "Trace" 6 | }, 7 | "applicationInsights": { 8 | "samplingSettings": { 9 | "isEnabled": true, 10 | "excludedTypes": "Request" 11 | } 12 | } 13 | }, 14 | "extensionBundle": { 15 | "id": "Microsoft.Azure.Functions.ExtensionBundle", 16 | "version": "[3.*, 4.0.0)" 17 | }, 18 | "customHandler": { 19 | "description": { 20 | "defaultExecutablePath": "./handler", 21 | "workingDirectory": "", 22 | "arguments": [] 23 | }, 24 | "enableForwardingHttpRequest": true 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder}; 2 | use serde::Deserialize; 3 | use std::env; 4 | 5 | //create a function that accepts a string as input and returns a sha256 hash of the string 6 | pub fn sha(text: &str) -> String { 7 | use sha2::{Digest, Sha256}; 8 | 9 | let mut hasher = Sha256::new(); 10 | hasher.update(text); 11 | let result = hasher.finalize(); 12 | format!("{:x}", result) 13 | } 14 | 15 | //create a struct that will be used to deserialize the JSON payload 16 | #[derive(Deserialize)] 17 | struct Text { 18 | text: String, 19 | } 20 | 21 | //create a struct to serialize the response using serde and hash as the key 22 | #[derive(serde::Serialize)] 23 | struct Hash { 24 | hash: String, 25 | } 26 | 27 | #[post("/api/token")] 28 | async fn tokenize(text: web::Json) -> impl Responder { 29 | //use the hash function to create a hash of the text and then return the hash 30 | //as JSON 31 | let hash = sha(&text.text); 32 | // return the hash as JSON using the Hash struct defined above 33 | HttpResponse::Ok().json(Hash { hash }) 34 | } 35 | 36 | #[actix_web::main] 37 | async fn main() -> std::io::Result<()> { 38 | env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); 39 | 40 | let port_key = "FUNCTIONS_CUSTOMHANDLER_PORT"; 41 | let port: u16 = match env::var(port_key) { 42 | Ok(val) => val.parse().expect("Custom Handler port is not a number!"), 43 | Err(_) => 3000, 44 | }; 45 | 46 | HttpServer::new(|| { 47 | App::new() 48 | .wrap(Logger::default()) 49 | .wrap(Logger::new("%a %{User-Agent}i")) 50 | .service(tokenize) 51 | }) 52 | .bind(("0.0.0.0", port))? 53 | .run() 54 | .await 55 | } 56 | -------------------------------------------------------------------------------- /token/function.json: -------------------------------------------------------------------------------- 1 | { 2 | "bindings": [ 3 | { 4 | "authLevel": "anonymous", 5 | "type": "httpTrigger", 6 | "direction": "in", 7 | "name": "req", 8 | "methods": [ 9 | "get", 10 | "post" 11 | ] 12 | }, 13 | { 14 | "type": "http", 15 | "direction": "out", 16 | "name": "res" 17 | } 18 | ] 19 | } --------------------------------------------------------------------------------