HTTP Uploader

Streams a matched resource’s content directly to an HTTP endpoint (typically a PUT upload) and rewrites the resource to a Wget/v1 access pointing at the uploaded location. The source may be any access type (wget, OCI, S3, GitHub, …) — its content is fetched through the access-type-specific downloader; only the target is always an HTTP endpoint. The source content is piped straight into the request body, so it is never buffered in memory or on disk. The digest is computed during the stream, or — when the source resource already carries one — verified as the bytes pass through.

The upload request and the published access are kept separate. method, header, body and noRedirect describe the upload request only. The published Wget/v1 access — the download access recorded on the transferred resource — carries just the resolved url and mediaType, never the write verb, body or request headers. This ensures a later ocm download issues a plain read (GET) and cannot re-send the write request that would overwrite the uploaded object.

The OCM Kubernetes controller ignores HTTP uploader entries because they send content to configured URLs from the controller pod.

Schema

Fields

targetURL and mediaType also become the published Wget/v1 download access; method, header, body and noRedirect apply to the upload request only:

FieldTypeApplies toDescription
matchCEL expression—A CEL boolean expression selecting the resources this uploader handles. Required: the HTTP uploader has no default match.
targetURLCEL expressionrequest + published (url)The upload URL; also the published download URL. See CEL Expressions.
methodstringrequest (verb)HTTP method for the upload request. Defaults to PUT. Not on the published access.
headermap[string][]stringrequestHTTP headers sent with the upload request. May be CEL-templated. Request only.
noRedirectboolrequestDisable following HTTP redirects on the upload. Not on the published access.
mediaTypestringrequest + published (mediaType)Media type recorded on the resource. Defaults to the source’s.

Routing Resources to Different Targets

Because a rule can match on any resource property, several resources of the same access type can be routed to different targets. List the specific rules first; a broader rule acts as a catch-all:

configurations:
  # Docs go to the docs bucket.
  - type: http.uploader.transfer.config.ocm.software/v1alpha1
    match: resource.access.isType("Wget/v1") && resource.name == "docs"
    targetURL: '${"https://docs.example.com" + url(resource.access.url).path}'
  # Everything else Wget goes to the generic bucket.
  - type: http.uploader.transfer.config.ocm.software/v1alpha1
    match: resource.access.isType("Wget/v1")
    targetURL: '${"https://blobs.example.com/" + resource.name + "/" + resource.version}'

Templating Headers

header values are templated with the same ${…} CEL expressions. This is how you forward a checksum the source already advertised on the upload request. Header expressions read resource.digest, which is only present when the source resource carries a digest (e.g. pinned from the source via the checksum-http configuration), so scope the rule with match so every matched resource has one. A value without ${…} is sent as a literal.

resource.digest.value is the hex digest and resource.digest.hashAlgorithm is the OCM algorithm name (e.g. SHA-256). Two inbuilt CEL functions build a standard Content-Digest / Repr-Digest field (RFC 9530):

  • contentDigestAlgorithm(<name>) maps the OCM algorithm name to the RFC 9530 key, lower-cased and canonicalized (SHA-256 → sha-256, SHA-512 → sha-512, MD5 → md5, and SHA-1 → the registered key sha). Matching is case- and separator-insensitive; an unknown algorithm fails the transfer.
  • RFC 9530 carries the digest value as base64, while resource.digest.value is hex, so convert it with base64.encode(hex.decode(resource.digest.value)). The base64.encode/base64.decode functions come from the CEL encoders extension; hex.encode/hex.decode are inbuilt companions.
  - type: http.uploader.transfer.config.ocm.software/v1alpha1
    match: resource.access.isType("Wget/v1")
    targetURL: '${"https://mytarget.example.com/uploads" + url(resource.access.url).path}'
    method: PUT
    header:
      # RFC 9530 Content-Digest: sha-256=:<base64>:
      Content-Digest: ['${contentDigestAlgorithm(resource.digest.hashAlgorithm) + "=:" + base64.encode(hex.decode(resource.digest.value)) + ":"}']
      # A simple non-standard checksum header carrying the raw hex value.
      X-Checksum-Sha256: ['${resource.digest.value}']
      # A static literal header is sent verbatim (no ${...}).
      X-Uploaded-By: ['ocm-transfer']

To upload into JFrog Artifactory or Sonatype Nexus repositories, use the vendor uploaders artifactory.uploader.transfer.config.ocm.software/v1alpha1 or nexus.uploader.transfer.config.ocm.software/v1alpha1 instead.

Credentials

The uploader resolves credentials for the target URL independently from the source resource, using the target host’s consumer identity (the same Wget identity used for downloads). Configure target-side credentials the same way you would for any HTTP endpoint; see Credential Types.