Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

EasyWebApp/KoAJAX

Repository files navigation

KoAJAX

HTTP Client based on Koa-like middlewares

NPM Dependency CI & CD

NPM

Feature

Request Body

Automatic Serialized types:

  1. Pure text: string
  2. Form encoding: URLSearchParams, FormData
  3. DOM object: Node
  4. JSON object: Object
  5. Binary data: Blob, ArrayBuffer, TypedArray, DataView
  6. Stream object: ReadableStream

Response Body

Automatic Parsed type:

  1. HTML/XML: Document
  2. JSON: Object
  3. Binary data: ArrayBuffer

Usage

Browser

Installation

npm install koajax

index.html

<head>
 <script src="https://polyfill.web-cell.dev/feature/Regenerator.js"></script>
 <script src="https://polyfill.web-cell.dev/feature/ECMAScript.js"></script>
 <script src="https://polyfill.web-cell.dev/feature/TextEncoder.js"></script>
 <script src="https://polyfill.web-cell.dev/feature/AbortController.js"></script>
 <script src="https://polyfill.web-cell.dev/feature/Stream.js"></script>
</head>

Node.js

Installation

npm install koajax core-js jsdom

index.ts

import { polyfill } from 'koajax/source/polyfill';
import { HTTPClient } from 'koajax';
const origin = 'https://your-target-origin.com';
polyfill(origin).then(() => {
 const client = new HTTPClient({
 baseURI: `${origin}/api`,
 responseType: 'json'
 });
 const { body } = await client.get('test/interface');
 console.log(body);
});

Execution

npx tsx index.ts

Non-polyfillable runtimes

  1. https://github.com/idea2app/KoAJAX-Taro-adapter

Example

RESTful API with Token-based Authorization

import { HTTPClient } from 'koajax';
var token = '';
export const client = new HTTPClient().use(
 async ({ request: { method, path, headers }, response }, next) => {
 if (token) headers['Authorization'] = 'token ' + token;
 await next();
 if (method === 'POST' && path.startsWith('/session'))
 token = response.headers.Token;
 }
);
client.get('/path/to/your/API').then(console.log);

Up/Download files

Single HTTP request based on XMLHTTPRequest progress events

(based on Async Generator)

import { request } from 'koajax';
document.querySelector('input[type="file"]').onchange = async ({
 target: { files }
}) => {
 for (const file of files) {
 const { upload, download, response } = request({
 method: 'POST',
 path: '/files',
 body: file,
 responseType: 'json'
 });
 for await (const { loaded } of upload)
 console.log(`Upload ${file.name} : ${(loaded / file.size) * 100}%`);
 const { body } = await response;
 console.log(`Upload ${file.name} : ${body.url}`);
 }
};

Single HTTP request based on Fetch duplex streams

This experimental feature has some limitations.

-import { request } from 'koajax';
+import { requestFetch } from 'koajax';
document.querySelector('input[type="file"]').onchange = async ({
 target: { files }
}) => {
 for (const file of files) {
- const { upload, download, response } = request({
+ const { upload, download, response } = requestFetch({
 method: 'POST',
 path: '/files',
+ headers: {
+ 'Content-Type': file.type,
+ 'Content-Length': file.size + ''
+ },
- body: file,
+ body: file.stream(),
 responseType: 'json'
 });
 for await (const { loaded } of upload)
 console.log(`Upload ${file.name} : ${(loaded / file.size) * 100}%`);
 const { body } = await response;
 console.log(`Upload ${file.name} : ${body.url}`);
 }
};

Multiple HTTP requests based on Range header

npm i native-file-system-adapter # Web standard API polyfill
import { showSaveFilePicker } from 'native-file-system-adapter';
import { HTTPClient } from 'koajax';
const bufferClient = new HTTPClient({ responseType: 'arraybuffer' });
document.querySelector('#download').onclick = async () => {
 const fileURL = 'https://your.server/with/Range/header/supported/file.zip';
 const suggestedName = new URL(fileURL).pathname.split('/').pop();
 const fileHandle = await showSaveFilePicker({ suggestedName });
 const writer = await fileHandle.createWritable(),
 stream = bufferClient.download(fileURL);
 try {
 for await (const { total, loaded, percent, buffer } of stream) {
 await writer.write(buffer);
 console.table({ total, loaded, percent });
 }
 window.alert(`File ${fileHandle.name} downloaded successfully!`);
 } finally {
 await writer.close();
 }
};

Global Error fallback

npm install browser-unhandled-rejection # Web standard API polyfill
import { auto } from 'browser-unhandled-rejection';
import { HTTPError } from 'koajax';
auto();
window.addEventListener('unhandledrejection', ({ reason }) => {
 if (!(reason instanceof HTTPError)) return;
 const { message } = reason.response.body;
 if (message) window.alert(message);
});

Read Files

(based on Async Generator)

import { readAs } from 'koajax';
document.querySelector('input[type="file"]').onchange = async ({
 target: { files }
}) => {
 for (const file of files) {
 const { progress, result } = readAs(file, 'dataURL');
 for await (const { loaded } of progress)
 console.log(
 `Loading ${file.name} : ${(loaded / file.size) * 100}%`
 );
 const URI = await result;
 console.log(`Loaded ${file.name} : ${URI}`);
 }
};

About

HTTP Client based on Koa-like middlewares

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published

Contributors 3

AltStyle によって変換されたページ (->オリジナル) /