# 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?