Skip to content

Commit

Permalink
(#88) Allow all response content types
Browse files Browse the repository at this point in the history
  • Loading branch information
predetermined authored Dec 30, 2021
2 parents fb49406 + ec93a14 commit 85f5f39
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 14 deletions.
31 changes: 30 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ outgoing or incoming request.
```typescript
app.register((req, res) => {
/**
* Skip Uint8Array responses:
* Ignore non-text responses:
* if (typeof res.content !== "string") return res;
*
* res.content = res.content.replace("Hello", "Hi");
Expand Down Expand Up @@ -262,3 +262,32 @@ app.get("/", (req) => {
```

Yes, that's it. Everything else should work as you are used to. :)

### Streaming

```typescript
app.get("/", (req) => {
const stream = new ReadableStream({
start(controller) {
let i = 0;
const interval = setInterval(() => {
controller.enqueue(new TextEncoder().encode("hello world!"));

if (i === 9) {
clearInterval(interval);
controller.close();
}

i++;
}, 500);
}
});

return {
content: stream,
headers: {
"Content-Type": "text/html"
}
};
});
```
30 changes: 17 additions & 13 deletions aqua.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,24 +22,33 @@ export type Method =
| "TRACE"
| "PATCH";

type ResponseContent =
| Uint8Array
| Blob
| BufferSource
| FormData
| URLSearchParams
| ReadableStream<Uint8Array>
| string;

interface ContentResponse {
statusCode?: number;
headers?: Record<string, string>;
cookies?: Record<string, string>;
redirect?: string;
content: string | Uint8Array;
content: ResponseContent;
}

interface RedirectResponse {
statusCode?: number;
headers?: Record<string, string>;
cookies?: Record<string, string>;
redirect: string;
content?: string | Uint8Array;
content?: ResponseContent;
}

export type ResponseObject = ContentResponse | RedirectResponse;
export type Response = string | Uint8Array | ResponseObject;
export type Response = ResponseContent | ResponseObject;

export interface Request {
_internal: {
Expand Down Expand Up @@ -237,23 +246,18 @@ export default class Aqua {
return urlParameters;
}

private isTextContent(response: Response): response is string {
return typeof response === "string";
}

private isDataContent(response: Response): response is Uint8Array {
return response instanceof Uint8Array;
}

private convertResponseToResponseObject(response: Response): ResponseObject {
if (this.isTextContent(response)) {
if (typeof response === "string") {
return {
headers: { "Content-Type": "text/html; charset=UTF-8" },
content: response,
};
}

if (this.isDataContent(response)) {
if (
typeof response !== "object" ||
(!("content" in response) && !("redirect" in response))
) {
return { content: response };
}

Expand Down
35 changes: 35 additions & 0 deletions tests/uptests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,41 @@ registerTest("Fallback handler error types working?", async () => {
}
});

registerTest("Are ReadableStream responses working?", async () => {
app.get("/readable-stream", (_req) => {
const stream = new ReadableStream({
start(controller) {
let i = 0;
const interval = setInterval(() => {
controller.enqueue(new TextEncoder().encode("hello world!"));

if (i === 4) {
clearInterval(interval);
controller.close();
}

i++;
}, 50);
},
});

return {
content: stream,
headers: {
"Content-Type": "text/html",
},
};
});

const content = await requestContent("/readable-stream");
const expected = "hello world!".repeat(5);
if (content !== expected) {
throw new Error(
`Expected handler to return "${expected}". Instead got: ${content}`,
);
}
});

setInterval(() => {
if (registeredTests === solvedTests) Deno.exit(0);
}, 500);

0 comments on commit 85f5f39

Please sign in to comment.