---
# System prepended metadata

title: Fetch API

---

# Fetch API

Baseline: GET of a data: URI produces a result.

This allows for functional testing and interaction with `await`.

```typescript=
let { UrlRequest } = import("TBD");

doAsync { () extends GeneratorFn;;
  let request = new UrlRequest("data:type/text;Hello, World!");
  request.method = "GET"; // default
  // Could add headers which would be ignored with data:
  let response = request.fetch();
  do { await(response.bodyText) } orelse do { ... };      
}
```

```typescript=
export class UrlRequest {
  // consider making this a setter so that you can't do: req.method = "NO_METHOD_BY_THIS_NAME_MAKES_ANY_SENSE!!!";
  // TODO: make an enum
  // (sealed class of request subtypes? and factory method? this does somewhat defeat builder)
  public var method: String;
  public constructor(url: String);
  public addHeader(name: String, value: String);
  public fetch(): UrlResponse;
  // TODO: extend to allow adding POST parameters and bodies
}

export class UrlResponse {
  public get headers(): Deferred<Map<String, String> | Null>;
  public get body(): Deferred<Bytes | Null>;
  public get bodyText(): Deferred<String | Null>;
  public get bodyType(): Deferred<MimeType | Null>;
}

export /* sealed */ interface Deferred<T> {
  public complete: Boolean;
  /** Non-blocking result fetch where no-value-yet produces null. */
  public getOrNull(): T | Null;
  public cancel(): Void /* maybe bubble here */;
  // Maybe have async be a method or getter?
}

// Macro that uses pause
export let await<T extends AnyValue>(d: Deferred<T>): T | Bubble;

export let fetch(req: UrlRequest): UrlResponse;

// Schedules for execution.
export let doAsync(g: Generator<*, Never>);
```

## Concerns

Tom: Splatting would suffice for a non-mutable request configuration

Shaw: prefer setters to set methods

Shaw: Hey if we can do this kind of system effect, what about designing a Filesystem API?
