On this page:
budget/  c
tap/  c
exhaust/  c
gen:  source
source?
fetch
identify
source-variant?
subprogram-fetch
$fetch
make-source-key
current-string->source
18.1 Source and Fetch Settings
DENXI_  DOWNLOAD_  MAX_  REDIRECTS
DENXI_  FETCH_  TOTAL_  SIZE_  MB
DENXI_  FETCH_  BUFFER_  SIZE_  MB
DENXI_  FETCH_  PKGDEF_  SIZE_  MB
DENXI_  FETCH_  TIMEOUT_  MS
18.2 Defining Source Types
define-source
bind-recursive-fetch
lock-source
18.3 Source Types
exhausted-source
byte-source
first-available-source
text-source
lines-source
file-source
http-source
http-mirrors-source
$http-failure
18.4 Source Expressions
sources
coerce-source
from-file
18.5 Untrusted Source Expressions
$bad-source-eval
eval-untrusted-source-expression
8.12

18 Sources🔗ℹ

 (require denxi/source) package: denxi

A source is a value that implements gen:source. When used with fetch, a source produces an input port and an estimate of how many bytes that port can produce. Denxi uses sources to read data with safety limits. To tap a source means gaining a reference to the input port and estimate. To exhaust a source means gaining a reference to a contextual error value. We can also say a source is tapped or exhausted.

Note that these terms are linguistic conveniences. There is no value representing a tapped or exhausted state. The only difference is where control ends up in the program, and what references become available as a result of using fetch on a source.

A value representing an estimated number of bytes to allocate for a future task.

A contract for a procedure used to tap a source.

The procedure is given an input port, and an estimate of the maximum number of bytes the port can produce. This estimate could be +inf.0 to allow unlimited reading, provided the user allows this in their configuration.

A contract for a procedure used when a source is exhausted.

The sole argument to the procedure depends on the source type.

syntax

gen:source

value

source? : predicate/c

procedure

(fetch source tap exhaust)  any/c

  source : source?
  tap : tap/c
  exhaust : exhaust/c

procedure

(identify source)  (or/c input-port? #f)

  source : source?
gen:source is a generic interface that requires an implementation of fetch and identify. source? returns #t for values that do so.

fetch attempts to tap source. If successful, fetch calls tap in tail position, passing the input port and the estimated maximum number of bytes that port is expected to produce. Otherwise, fetch calls exhaust in tail position using a source-dependent argument.

identify attempts to return an input port that produces bytes used to identify a source? value. The input port does not produce bytes for expected content, and cannot use any information outside of what’s available in the value itself. This allows other other systems to compute cache keys and avoid unnecessary calls to fetch. If identify returns #f for a source, then that source cannot be identified.

Returns #t if the sole argument is suitable for use in coerce-source.

procedure

(subprogram-fetch id source tap)  subprogram?

  id : any/c
  source : source?
  tap : tap/c

struct

(struct $fetch $message (id errors))

  id : any/c
  errors : (listof $message?)
Returns a subprogram that applies fetch to source and tap.

The computed value of the subprogram is FAILURE if the source is exhausted. Otherwise, the value is what’s returned from tap.

The log will gain a ($fetch id errors) message, where errors is empty if the fetch is successful.

procedure

(make-source-key src)  (or/c #f bytes?)

  src : source?
Returns bytes to uniquely identify src, or #f if the source is not meant to be identified.

This is a front-end to identify that will always produce a fixed-length byte string. Prefer using this over using identify directly.

A parameter that controls how coerce-source converts strings to source values.

The default value will infer if the string is suitable for use with file-source or http-source, in that order. If an error is raised, it will be returned within an exhausted-source.

18.1 Source and Fetch Settings🔗ℹ

CLI Flags: -o/--max-redirects/--DENXI_DOWNLOAD_MAX_REDIRECTS
The maximum number of HTTP redirects to follow when resolving a GET request.

setting

DENXI_FETCH_TOTAL_SIZE_MB : (or/c +inf.0 real?) = 100

CLI Flags: -m/--fetch-total-size/--DENXI_FETCH_TOTAL_SIZE_MB
The maximum total size of a single download allowed when fetching an input from a source, in mebibytes.

setting

DENXI_FETCH_BUFFER_SIZE_MB : (real-in 0.1 20) = 10

CLI Flags: -n/--fetch-buffer-size/--DENXI_FETCH_BUFFER_SIZE_MB
The maximum number of bytes to read at a time from a source, in mebibytes.

setting

DENXI_FETCH_PKGDEF_SIZE_MB : (real-in 0.1 20) = 0.1

CLI Flags: -p/--fetch-pkgdef-size/--DENXI_FETCH_PKGDEF_SIZE_MB
Like DENXI_FETCH_TOTAL_SIZE_MB, except the quota only applies to package definitions named in a user-defined transaction. This quote does not apply to package definitions listed as inputs in another package definition.

setting

DENXI_FETCH_TIMEOUT_MS : (or/c +inf.0 (real-in 100 10000))

 = 3000
CLI Flags: -d/--fetch-timeout/--DENXI_FETCH_TIMEOUT_MS
The maximum number of seconds to wait for the next available byte from a source.

18.2 Defining Source Types🔗ℹ

syntax

(define-source #:key compute-key
  (id [field field-contract] ...)
    body ...)
Defines a new source type.

On expansion, define-source defines a new structure type using (struct id (field ...)). The type is created with a guard that enforces per-field contracts. Instances implement gen:source.

define-source injects several bindings into the lexical context of body:

To understand how these injected bindings work together, let’s go through a few examples.

Use %tap to fulfil data with an input port and an estimated data length. In the simplest case, you can return constant data.

byte-source uses %tap like so:

(define-source #:key byte-source-data (byte-source [data bytes?])
  (%tap (open-input-bytes data)
        (bytes-length data)))

Notice that the data is used to both define a data field (where it appears by bytes?) and to reference the value contained in that field (within open-input-bytes and bytes-length).

Use %fail in tail position with error information to indicate a source was exhausted.

file-source uses %fail like so:

(define-source #:key file-source-path (file-source [path path-string?])
  (with-handlers ([exn:fail:filesystem? %fail])
    (%tap (open-input-file path)
          (+ (* 20 1024)
             (file-size path)))))

Note that %fail is an exhaust/c procedure, so it does not have to be given an exception as an argument.

%fetch is a recursive variant of fetch that uses %tap, but a possibly different exhaust/c procedure. This allows sources to control an entire fetch process and fall back to alternatives.

first-available-source uses a resursive fetch to iterate on available sources until it has none left to check.

(define-source #:key first-available-source-sources
               (first-available-source [available (listof source?)] [errors list?])
  (if (null? available)
      (%fail (reverse errors))
      (%fetch (car available)
              (λ (e)
                (%fetch (first-available-source (cdr available) (cons e errors))
                        %fail)))))

Finally, %src is just a reference to an instance of the structure containing each field.

compute-key is an expression that must resolve to a procedure, or #f. It is used to generate an implementation of identify, such that the procedure must produce a value that can be reasonably coerced to an input port for use with identify. Currently, the accepted values include input ports, paths, strings, byte strings, instances of url, sources, or lists of the aforementioned types.

procedure

(bind-recursive-fetch %tap %fail)

  (->* (source?) (exhaust/c) any/c)
  %tap : tap/c
  %fail : exhaust/c
Returns a fetch-like procedure that accepts only a source and an optional procedure to mark the source exhausted (defaults to %fail).

procedure

(lock-source variant [budget] exhaust)  
(or/c source-variant?
      bytes?)
  variant : source-variant?
  budget : (or/c +inf.0 exact-nonnegative-integer?) = 0
  exhaust : exhaust/c
Returns either variant, or the complete byte string produced from variant so long as its estimated size is not greater than budget.

lock-source works in the context of fetch, using the provided exhaust procedure.

18.3 Source Types🔗ℹ

struct

(struct exhausted-source (value))

  value : any/c
A source that is always exhausted, meaning that (fetch (exhausted-source v) void values) returns v.

struct

(struct byte-source (data))

  data : bytes?
A source that, when tapped, yields bytes directly from data.

struct

(struct first-available-source (sources errors))

  sources : (listof sources?)
  errors : list?
A source that, when tapped, yields bytes from the first tapped source.

If all sources for an instance are exhausted, then the instance is exhausted. As sources are visited, errors are functionally accumulated in errors.

The value produced for an exhausted first-available-source is the longest possible list bound to errors.

struct

(struct text-source (data)
    #:extra-constructor-name make-text-source)
  data : string?
A source that, when tapped, produces bytes from the given string.

struct

(struct lines-source (suffix lines)
    #:extra-constructor-name make-lines-source)
  suffix : (or/c #f char? string?)
  lines : (listof string?)
A source that, when tapped, produces bytes from (join-lines #:suffix suffix #:trailing? #f lines).

(define src
  (lines-source "\r\n"
                '("#lang racket/base"
                  "(provide a)"
                  "(define a 1)")))
 
; "#lang racket/base (provide a) (define a 1) "
(fetch src consume void)

struct

(struct file-source (path)
    #:extra-constructor-name make-file-source)
  path : path-string?
A source that, when tapped, yields bytes from the file located at path.

If the source is exhausted, it yields a relevant exn:fail:filesystem exception.

struct

(struct http-source (request-url)
    #:extra-constructor-name make-http-source)
  request-url : (or/c url? url-string?)
A source that, when tapped, yields bytes from an HTTP response body. The response comes from a GET request to request-url, and the body is only used for a 2xx response. A non-2xx status will exhaust the source with an $http-failure message.

If request-url has the "file" scheme, then http-source behaves like file-source. In this case, only the URL path is used from request-url.

If the source is exhausted, it yields a relevant exception.

The behavior of the source is impacted by DENXI_DOWNLOAD_MAX_REDIRECTS.

struct

(struct http-mirrors-source (request-urls)
    #:extra-constructor-name make-http-mirrors-source)
  request-urls : (listof (or/c url-string? url?))
Like http-source, but tries each of the given URLs using first-available-source.

struct

(struct $http-failure $message (request-url
    status-line
    headers
    capped-body))
  request-url : string?
  status-line : string?
  headers : (listof (cons/c string? string?))
  capped-body : bytes?
Represents a server response when an http-source is exhausted. The field values match their names. cappped-body in special in that it holds no more than 512 bytes of the response body.

18.4 Source Expressions🔗ℹ

The following procedures are useful for declaring sources in a package input.

procedure

(sources variant ...)  source?

  variant : (or/c string? source?)
Like first-available-source, but each string argument is coerced to a source using coerce-source.

procedure

(coerce-source variant)  source?

  variant : source-variant?
Returns a source depending on the type of variant.

syntax

(from-file relative-path-expr)

Expands to a complete path. relative-path-expr is a relative path made complete with regards to the source directory in which this expression appears.

Due to this behavior, from-file will return different results when the containing source file changes location on disk.

18.5 Untrusted Source Expressions🔗ℹ

struct

(struct $bad-source-eval $message (reason datum))

  reason : (or/c 'security 'invariant)
  datum : any/c

procedure

(eval-untrusted-source-expression datum [ns])  subprogram?

  datum : any/c
  ns : namespace? = (current-namespace)
eval-untrusted-source-expression returns a subprogram which evaluates (eval datum ns) in the context of a security guard. The security guard blocks all file operations (except 'exists), and all network operations.

If the evaluation produces a source, then the result of the subprogram is that source, and no other messages will appear in the subprogram log.

If the evaluation does not produce a source, then the result is FAILURE and the subprogram log gains a ($bad-source-eval 'invariant datum).

If the evaluation is blocked by the security guard, then the result is FAILURE and the subprogram log gains a ($bad-source-eval 'security datum).