diff --git a/.github/workflows/python-ci.yml b/.github/workflows/python-ci.yml index e2cf6dd..c4aae64 100644 --- a/.github/workflows/python-ci.yml +++ b/.github/workflows/python-ci.yml @@ -8,7 +8,7 @@ on: workflow_dispatch: # Allows manual triggering from GitHub Actions UI env: - VICEROY_TAG: v0.16.3 + VICEROY_TAG: v0.16.4 jobs: build: diff --git a/Makefile b/Makefile index 8d66c81..d4db6d3 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,7 @@ EXAMPLES := bottle-app flask-app backend-requests game-of-life EXAMPLE ?= bottle-app WASM_FILE := $(BUILD_DIR)/$(EXAMPLE).composed.wasm -TARGET_WORLD := fastly:compute/service +TARGET_WORLD := fastly:compute/service@0.1.0 VICEROY ?= viceroy diff --git a/crates/fastly-compute-py/src/lib.rs b/crates/fastly-compute-py/src/lib.rs index c5f87bc..f490a6b 100644 --- a/crates/fastly-compute-py/src/lib.rs +++ b/crates/fastly-compute-py/src/lib.rs @@ -141,7 +141,7 @@ pub fn build(output: PathBuf, entry_name: String) -> Result<()> { futures::executor::block_on(async { componentize_py::componentize( &[merged_wit_path.as_path()], - Some("fastly:compute/service"), + Some("fastly:compute/service@0.1.0"), &[], false, Some("wit_world"), diff --git a/wit/deps/fastly-adapter/adapter.wit b/wit/deps/fastly-adapter/adapter.wit deleted file mode 100644 index 68c49b7..0000000 --- a/wit/deps/fastly-adapter/adapter.wit +++ /dev/null @@ -1,345 +0,0 @@ -/// Interfaces available to the component adapter, which are not otherwise -/// part of the Fastly Compute platform. -package fastly:adapter; - -interface adapter-abi { - init: func(); -} - -/// Adapter functions formerly of `fastly:compute/http-req`. -/// -/// These functions depend on the host maintaining an implicit downstream -/// request. They were replaced by functions in the `http-downstream` interface -/// which do the same thing but take an explicit `request` handle. -interface adapter-http-req { - use fastly:compute/types@0.0.0-prerelease.0.{error, ip-address}; - use fastly:compute/http-req@0.0.0-prerelease.0.{ - client-cert-verify-result, request, body, response-with-body, error-with-detail, - pending-response - }; - - downstream-client-ip-addr: func() -> option; - downstream-server-ip-addr: func() -> option; - downstream-client-h2-fingerprint: func(max-len: u64) -> result; - downstream-client-request-id: func(max-len: u64) -> result; - downstream-client-oh-fingerprint: func(max-len: u64) -> result; - downstream-client-ddos-detected: func() -> result; - downstream-tls-cipher-openssl-name: func(max-len: u64) -> result>, error>; - downstream-tls-protocol: func(max-len: u64) -> result>, error>; - downstream-tls-client-hello: func(max-len: u64) -> result>, error>; - downstream-tls-client-cert-verify-result: func() -> result, error>; - downstream-tls-ja3-md5: func() -> result>, error>; - downstream-tls-ja4: func(max-len: u64) -> result, error>; - downstream-compliance-region: func(max-len: u64) -> result, error>; - - /// Deprecated, because it doesn't return `none` on an empty certificate. - downstream-tls-raw-client-certificate-deprecated: func(max-len: u64) -> result>, error>; - - get-original-header-names: func( - max-len: u64, - cursor: u32, - ) -> result>, error>; - - original-header-count: func() -> result; - - fastly-key-is-valid: func() -> result; - - /// Deprecated; this version doesn't take a `request`, and takes `backend` - /// as a string. - redirect-to-websocket-proxy-norequest: func(backend: string) -> result<_, error>; - - /// Deprecated; this version doesn't take a `request`, and takes `backend` - /// as a string. - redirect-to-grip-proxy-norequest: func(backend: string) -> result<_, error>; - - /// Deprecated; this version takes `backend` as a string. - redirect-to-websocket-proxy: func( - request: borrow, - backend: string, - ) -> result<_, error>; - - /// Deprecated; this version takes `backend` as a string. - redirect-to-grip-proxy: func( - request: borrow, - backend: string, - ) -> result<_, error>; - - /// Deprecated; this function takes `backend` as a string. - send: func( - request: request, - body: body, - backend: string, - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - send-uncached: func( - request: request, - body: body, - backend: string, - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - send-async: func( - request: request, - body: body, - backend: string - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - send-async-uncached: func( - request: request, - body: body, - backend: string, - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - send-async-streaming: func( - request: request, - body: borrow, - backend: string, - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - send-async-uncached-streaming: func( - request: request, - body: borrow, - backend: string, - ) -> result; - - /// Deprecated; this function takes `backend` as a string. - upgrade-websocket: func(backend: string) -> result<_, error>; - - /// Deprecated; this function depends on per-service authority. - on-behalf-of-deprecated: func( - request: borrow, - service: string, - ) -> result<_, error>; -} - -/// Deprecated; these functions take `backend` as a string. -interface adapter-backend { - use fastly:compute/backend@0.0.0-prerelease.0.{ - backend-health, error, timeout-ms, tls-version, timeout-secs, probe-count, - dynamic-backend-options, - }; - - register-dynamic-backend: func( - prefix: string, - target: string, - options: dynamic-backend-options, - ) -> result<_, error>; - - exists: func(backend: string) -> result; - is-healthy: func(backend: string) -> result; - is-dynamic: func(backend: string) -> result; - get-host: func(backend: string, max-len: u64) -> result; - get-override-host: func( - backend: string, - max-len: u64, - ) -> result>, error>; - get-port: func(backend: string) -> result; - get-connect-timeout-ms: func(backend: string) -> result; - get-first-byte-timeout-ms: func(backend: string) -> result; - get-between-bytes-timeout-ms: func(backend: string) -> result; - is-tls: func(backend: string) -> result; - get-tls-min-version: func(backend: string) -> result, error>; - get-tls-max-version: func(backend: string) -> result, error>; - get-http-keepalive-time: func( - backend: string, - ) -> result; - get-tcp-keepalive-enable: func( - backend: string, - ) -> result; - get-tcp-keepalive-interval: func( - backend: string, - ) -> result; - get-tcp-keepalive-probes: func( - backend: string, - ) -> result; - get-tcp-keepalive-time: func( - backend: string, - ) -> result; -} - -/// Deprecated functions formerly of `fastly:compute/image-optimizer`. -interface adapter-image-optimizer { - use fastly:compute/image-optimizer@0.0.0-prerelease.0.{ - body, request, image-optimizer-transform-options, response-with-body, error - }; - - /// Deprecated; this function takes the backend as a `string`. - transform-image-optimizer-request: func( - origin-image-request: borrow, - origin-image-request-body: option, - origin-image-request-backend: string, - io-transform-options: image-optimizer-transform-options, - ) -> result; -} - -interface adapter-http-downstream { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - use fastly:compute/http-req@0.0.0-prerelease.0.{request}; - - /// Deprecated, because it doesn't return `none` on an empty certificate. - downstream-tls-raw-client-certificate-deprecated: func( - ds-request: borrow, - max-len: u64 - ) -> result>, error>; -} - -/// Deprecated functions formerly of `fastly:compute/http-cache`. -interface adapter-http-cache { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - use fastly:compute/http-req@0.0.0-prerelease.0.{request}; - use fastly:compute/http-cache@0.0.0-prerelease.0.{entry}; - - /// Deprecated; use `transaction-lookup` instead. - lookup: func( - req-handle: borrow, - options: lookup-options, - ) -> result; - - /// Deprecated; this function takes the backend in `lookup-options` as - /// a `string`. - transaction-lookup: func( - req-handle: borrow, - options: lookup-options, - ) -> result; - - record lookup-options { - override-key: option>, - backend-name: option, - extra: option>, - } - resource extra-lookup-options {} -} - -/// Adapter Core Cache functions. -interface adapter-cache { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - use fastly:compute/cache@0.0.0-prerelease.0.{ - extra-lookup-options, extra-write-options, extra-replace-options - }; - - /// Deprecated; this function depends on per-service authority. - set-lookup-service-id-deprecated: func( - options: borrow, - service-id: string - ) -> result<_, error>; - - /// Deprecated; this function depends on per-service authority. - set-write-service-id-deprecated: func( - options: borrow, - service-id: string - ) -> result<_, error>; - - /// Deprecated; this function depends on per-service authority. - set-replace-service-id-deprecated: func( - options: borrow, - service-id: string - ) -> result<_, error>; -} - -/// User-agent string parsing (deprecated). -interface adapter-uap { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - - resource user-agent { - family: func(max-len: u64) -> result; - major: func(max-len: u64) -> result; - minor: func(max-len: u64) -> result; - patch: func(max-len: u64) -> result; - } - - /// Parses a user agent string. - parse: func(user-agent: list) -> result; -} - -/// Deprecated functions formerly of `fastly:compute/erl`. -interface adapter-erl { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - - check-rate: func( - rate-counter: string, - entry: string, - delta: u32, - window: u32, - limit: u32, - penalty-box: string, - ttl: u32, - ) -> result; - - ratecounter-increment: func( - rate-counter: string, - entry: string, - delta: u32, - ) -> result<_, error>; - - ratecounter-lookup-rate: func( - rate-counter: string, - entry: string, - window: u32, - ) -> result; - - ratecounter-lookup-count: func( - rate-counter: string, - entry: string, - duration: u32, - ) -> result; - - penaltybox-add: func( - penalty-box: string, - entry: string, - ttl: u32, - ) -> result<_, error>; - - penaltybox-has: func( - penalty-box: string, - entry: string, - ) -> result; -} - -/// Deprecated functions formerly of `fastly:compute/shielding`. -interface adapter-shielding { - use fastly:compute/types@0.0.0-prerelease.0.{error}; - use fastly:compute/shielding@0.0.0-prerelease.0.{shield-backend-options}; - - /// Deprecated; this function returns the backend as a `string`. - backend-for-shield: func( - name: string, - options: option>, - max-len: u64, - ) -> result; -} - -/// A world that just imports all the adapter-only APIs, split out from the main -/// world below so that we can refer to it in tests. -world adapter-imports { - import adapter-abi; - import adapter-http-req; - import adapter-http-downstream; - import adapter-http-cache; - import adapter-backend; - import adapter-cache; - import adapter-erl; - import adapter-image-optimizer; - import adapter-shielding; - import adapter-uap; -} - -/// The `fastly:compute/service` world plus the adapter-only interfaces. -world adapter-service { - // Make this world a superset of the `service` world. - include fastly:compute/service@0.0.0-prerelease.0; - - // And, add all the adapter-only interfaces. - include adapter-imports; -} - -/// Like `adapter-service`, but only includes the imports, and not the -/// exports (`http-incoming.handle`), so that it can be used by library components -/// that don't have their own `main` function. -world adapter-service-imports { - include fastly:compute/service-imports@0.0.0-prerelease.0; - include adapter-imports; -} diff --git a/wit/deps/fastly/compute.wit b/wit/deps/fastly/compute.wit index 4b46743..c8a79b4 100644 --- a/wit/deps/fastly/compute.wit +++ b/wit/deps/fastly/compute.wit @@ -6,7 +6,7 @@ /// /// [Wit]: https://component-model.bytecodealliance.org/design/wit.html /// [Fastly Compute platform]: https://www.fastly.com/documentation/guides/compute/ -package fastly:compute@0.0.0-prerelease.0; +package fastly:compute@0.1.0; /// Types used by many interfaces in this package. interface types { @@ -132,12 +132,45 @@ interface http-types { /// HTTP [content encoding] flags /// + /// The names of these flags correspond to + /// [IANA HTTP Content Coding Registry] names. + /// + /// Not all of these content encoding flags are supported in all APIs that + /// use this `content-encodings` type. See the documentation for individual + /// functions for details. + /// /// [content encoding]: https://www.rfc-editor.org/rfc/rfc9110.html#field.content-encoding + /// [IANA HTTP Content Coding Registry]: https://www.iana.org/assignments/http-parameters/http-parameters.xhtml#content-coding flags content-encodings { /// [Gzip coding] /// /// [Gzip coding]: https://www.rfc-editor.org/rfc/rfc9110.html#gzip.coding - gzip + gzip, + + /// [Brotli coding] + /// + /// [Brotli coding]: https://www.rfc-editor.org/rfc/rfc7932.html + br, + + /// [Zstandard coding] + /// + /// [Zstandard coding]: https://www.rfc-editor.org/rfc/rfc8878.html + zstd, + + /// [Dictionary-Compressed Brotli] + /// + /// [Dictionary-Compressed Brotli]: https://www.rfc-editor.org/rfc/rfc9842.html#name-dictionary-compressed-brotl + dcb, + + /// [Dictionary-Compressed Zstandard] + /// + /// [Dictionary-Compressed Zstandard]: https://www.rfc-editor.org/rfc/rfc9842.html#name-dictionary-compressed-zstan + dcz, + + /// [AES-GCM encryption with a 128-bit content encryption key] + /// + /// [AES-GCM encryption with a 128-bit content encryption key]: https://www.rfc-editor.org/rfc/rfc8188.html + aes128gcm, } /// Determines how the framing headers (`Content-Length`/`Transfer-Encoding`) are set for a @@ -168,17 +201,19 @@ interface http-types { /// [Transport Layer Security] (TLS) version /// + /// This corresponds to the `ProtocolVersion` type in the RFC, which gives + /// the following values the following meanings: + /// + /// | Value | Meaning | Notes | + /// | ------ | ------- | ----- | + /// | 0x0300 | SSL 3.0 | Not supported in this API | + /// | 0x0301 | TLS 1.0 | | + /// | 0x0302 | TLS 1.1 | Not explicitly defined in the RFC | + /// | 0x0303 | TLS 1.2 | | + /// | 0x0304 | TLS 1.3 | | + /// /// [Transport Layer Security]: https://www.rfc-editor.org/rfc/rfc8446.html - enum tls-version { - /// TLS 1.0 - tls1, - /// TLS 1.1 - tls11, - /// TLS 1.2 - tls12, - /// TLS 1.3 - tls13 - } + type tls-version = u16; /// HTTP [status codes]. /// @@ -523,7 +558,7 @@ interface http-downstream { /// HTTP requests. interface http-req { use types.{error, ip-address}; - use http-types.{http-version, content-encodings, framing-headers-mode, tls-version}; + use http-types.{http-version, content-encodings, framing-headers-mode}; use http-resp.{response}; use http-body.{body}; use http-resp.{response-with-body}; @@ -634,6 +669,9 @@ interface http-req { /// If the response to this request is encoded by one of the encodings set by this method, the /// response will be presented to the Compute program in decompressed form with the /// `Content-Encoding` and `Content-Length` headers removed. + /// + /// Not all of the flags defined in `content-encodings` are supported. Currently the only + /// supported flag is `content-encodings.gzip`. set-auto-decompress-response: func( encodings: content-encodings, ) -> result<_, error>; @@ -876,6 +914,10 @@ interface http-req { /// The system encountered a TLS error when communicating with the backend, either during /// the handshake or afterwards. tls-protocol-error, + /// The system received an HTTP/2 error frame and code from the backend. + h2-error(h2-error-detail), + /// Additional error details may be added in the future via this resource type. + extra(extra-send-error-detail), } /// Variant fields for `send-error.dns-error`. @@ -889,6 +931,15 @@ interface http-req { id: option, } + /// Variant fields for `send-error.h2-error`. + record h2-error-detail { + frame-type: u8, + error-code: u32, + } + + /// Extensibility for `send-error-detail` + resource extra-send-error-detail {} + /// An `error` code, optionally with extra request error information. record error-with-detail { detail: option, @@ -1321,7 +1372,7 @@ interface kv-store { use async-io.{pollable as pending-list}; /// A value indicating the status of a KV store operation. - enum kv-error { + variant kv-error { /// KV store cannot or will not process the request due to something that is perceived to be a /// client error. /// @@ -1348,8 +1399,13 @@ interface kv-store { /// /// This means that some unexpected error occurred. generic-error, + /// Additional error information may be added in the future via this resource type. + extra(extra-kv-error), } + /// Extensibility for `kv-error` + resource extra-kv-error {} + /// Wait on the async lookup of a value in the KV Store. /// /// Returns `ok(some(v))` with the value `v` that was found, `ok(none)` if no value was @@ -2051,6 +2107,11 @@ interface cache { options: write-options, ) -> result<_, error>; + /// Get the state of a cache lookup, waiting for the lookup to complete if necessary. + /// + /// Note that FOUND == USABLE, and means "usable" (fresh or stale-while-revalidate). + /// Some SDKs were released that checked only FOUND to infer "usable"; + /// we preserve the equivalence for backwards compatibility. get-state: func() -> result; /// Gets the user metadata of the found object, returning `ok(none)` if no object @@ -2142,6 +2203,10 @@ interface cache { /// Gets the lookup state of the existing object during replace, returning /// `ok(none)` if there was no object. + /// + /// Note that FOUND == USABLE, and means "usable" (fresh or stale-while-revalidate). + /// Some SDKs were released that checked only FOUND to infer "usable"; + /// we preserve the equivalence for backwards compatibility. get-state: func() -> result, error>; /// Gets the user metadata of the existing object during replace, returning @@ -2235,6 +2300,7 @@ interface cache { stale, /// this client is requested to insert or revalidate an object must-insert-or-update, + usable-if-error, } /// Performs a non-request-collapsing cache insertion (or update). @@ -2592,6 +2658,8 @@ interface http-cache { /// If this field is not set, the default value is zero. stale-while-revalidate-ns: option, + stale-if-error-ns: option, + /// A list of surrogate keys that may be used to purge this response. /// /// The format is a string containing [valid surrogate keys] separated by spaces. diff --git a/wrap_app_in_wasiless.wac b/wrap_app_in_wasiless.wac index 883c8b4..98bfb07 100644 --- a/wrap_app_in_wasiless.wac +++ b/wrap_app_in_wasiless.wac @@ -1,4 +1,4 @@ -package fastly:python-wasiless; // TODO: Append "targets fastly:compute/service" as an additional check. +package fastly:python-wasiless; // TODO: Append "targets fastly:compute/service@0.1.0" as an additional check. // Instantiate wasiless to satisfy irrelevant WASI interfaces: let wasiless = new fastly:wasiless { ... }; @@ -6,4 +6,4 @@ let wasiless = new fastly:wasiless { ... }; let app = new app:component { ...wasiless, ... }; // Export only the HTTP handler, not the extraneous `exports` bundle: -export app["fastly:compute/http-incoming@0.0.0-prerelease.0"]; +export app["fastly:compute/http-incoming@0.1.0"];