コンテンツにスキップ
UniKVS
日本語
Esc
↑↓移動↵開く⌘Jプレビュー
このページの内容

@unikvs/base64url

バイト列を URL 安全な base64 文字列として表すバイト列へ透過的に変換する Transformer プラグインの使い方を説明します。

概要

@unikvs/base64url は、バイト列を URL 安全な base64 (base64url) として表すバイト列へ変換する Transformer プラグインです。Transformer

書き込み時は encode で base64url 化し、読み取り時は decode で元のバイト列に戻すため、変換の詳細を意識せずに読み書きできます。URL やファイル名に埋め込む値、テキストしか保存できない保存先への格納に使います。

使用する 64 文字は RFC 4648 §5 の A-Z・a-z・0-9・-・_ です。標準の base64 が使う +・/ は含まず、受け付けもしません。

入出力はどちらも Uint8Array<ArrayBuffer> です。変換後のサイズは元のサイズの約 1.37 倍になります。

常にオープン状態です。open・close は不要で、isOpen は常に true、name は常に "Base64Url" を返します。

Node.js・Bun・ブラウザーで動作します。実行環境による振る舞いの違いはありません。

インストールは次のとおりです。

npm install @unikvs/base64url
pnpm add @unikvs/base64url
yarn add @unikvs/base64url
bun add @unikvs/base64url
nub add @unikvs/base64url
aube add @unikvs/base64url

使い方

通常は引数なしで生成します。末尾の = を付けたい場合や、UTF-8 変換に使うインスタンスを差し替えたい場合にだけ Base64UrlOptions を指定します。

import { Base64Url } from "@unikvs/base64url";

const base64url = new Base64Url();
import { Base64Url, type Base64UrlOptions } from "@unikvs/base64url";
import { FastUtf8 } from "fast-utf8";

const options: Base64UrlOptions = {
  encoder: new FastUtf8(),
  decoder: new FastUtf8({ strict: true }),
  padding: true,
};

const base64url = new Base64Url(options);

Base64UrlOptions の内容は次のとおりです。通常は省略し、既定のまま使います。padding を省略すると false として扱われ、= を付けずに出力します。decode は = の有無にかかわらず受け付けます。decoder に strict: false のインスタンスを指定した場合は、不正な UTF-8 は Base64UrlDecodeError として投げられます。詳しくはエラーを参照してください。

type Base64UrlOptions = {
  readonly encoder?: FastUtf8 | undefined;
  readonly decoder?: FastUtf8 | undefined;
  readonly padding?: boolean | undefined;
};

主なメンバーは次のとおりです。

メンバー 概要
new Base64Url(options?) オプションなしで初期化します。差し替えが必要な場合だけ Base64UrlOptions を渡します。
name 常に "Base64Url" を返します。
isOpen 常に true を返します。
encode({ data }) Uint8Array<ArrayBuffer> を base64url の Uint8Array<ArrayBuffer> に変換します。
decode({ data }) base64url の Uint8Array<ArrayBuffer> を元のバイト列に戻します。
getEncodable() base64url 化用の TransformStream を返します。
getDecodable() base64url 復元用の TransformStream を返します。

一括変換の例です。encode の結果を UTF-8 文字列として解釈すると base64url になります。

import { Base64Url } from "@unikvs/base64url";

const base64url = new Base64Url();

const encoded = base64url.encode({ data: new TextEncoder().encode("foobar") });
console.log(new TextDecoder().decode(encoded)); // "Zm9vYmFy"

const decoded = base64url.decode({ data: new TextEncoder().encode("Zm9vYmFy") });
console.log(new TextDecoder().decode(decoded)); // "foobar"

padding: true を指定すると、一括・ストリームいずれも RFC 4648 §5 の正準形どおり = で埋めた出力を返します。既定 (false) では = を付けません。

import { Base64Url } from "@unikvs/base64url";

const omitted = new Base64Url();
console.log(new TextDecoder().decode(omitted.encode({ data: new TextEncoder().encode("f") }))); // "Zg"

const padded = new Base64Url({ padding: true });
console.log(new TextDecoder().decode(padded.encode({ data: new TextEncoder().encode("f") }))); // "Zg=="

UniKvs には appendTransformer で登録します。以降に登録するストレージの前段になります。

import { Base64Url } from "@unikvs/base64url";
import UniKvs from "unikvs";

const kvs = UniKvs.config()
  .appendTransformer(new Base64Url())
  .appendStorage(storage)
  .create();

await kvs.open();

await kvs.set("data", input);

const output = await kvs.get("data");

set で base64url 化して保存し、get で自動的に元のバイト列へ戻します。

ストリーム

単体値とストリームの両方に対応しています。

  • 単体値は encode・decode で変換します。
  • ストリーム値は getEncodable・getDecodable の TransformStream で変換します。

getEncodable は、入力チャンクの境界をまたいでも正しく base64url 化します。padding の設定はストリームにも適用され、= の有無はストリーム終了時に確定します。

getDecodable は、チャンク境界で分割された base64url も正しく復元します。

  • 空のストリームと長さ 0 のチャンクは値を 1 つも生成せず、エラーにもなりません。
  • 終了時に文字数が 4 で割って 1 余る場合や、= の位置が正しくない場合は Base64UrlDecodeError を投げます。
  • base64url として不正な文字が含まれている場合は、その時点で Base64UrlDecodeError を投げます。
  • 既定では、不正な UTF-8 や途中で切れたマルチバイト文字が含まれている場合は TypeError を投げます。詳しくはエラーを参照してください。
import { Base64Url } from "@unikvs/base64url";

const base64url = new Base64Url();

const source = new ReadableStream({
  start(controller) {
    controller.enqueue(new TextEncoder().encode("fo"));
    controller.enqueue(new TextEncoder().encode("obar"));
    controller.close();
  },
});

const decoded = source.pipeThrough(base64url.getEncodable()).pipeThrough(base64url.getDecodable());

注意点

形式の扱いは次のとおりです。

  • +・/ は受け付けません。標準の base64 が必要な場合は別パッケージを使ってください。置き換えも自動では行いません。必要な場合は呼び出し側で変換してください。
  • 空白・改行などの区切りは読み飛ばしません。不正文字として拒否されます。
  • = は末尾の 1 文字から 2 文字にだけ付けられ、全体が 4 文字境界である場合に限ります。"Zg=" のような長さ 3 の入力は拒否されます。途中や先頭にある = は拒否されます。
  • 空入力は空出力です。new Uint8Array(0) を渡してもエラーになりません。

サイズ(バイト長)は元のサイズの約 1.37 倍になります(padding: false の既定ではわずかに小さくなります)。圧縮や暗号化、改ざん検知の目的には使えません。

エラー

このパッケージが投げるエラーは次のとおりです。

エラー 意味 対処
Base64UrlDecodeError base64url として解釈できません。+・/ や空白の混入、= の位置の誤り、4 で割って 1 余る長さ(例: "a"・"abcde")が原因です。 入力が base64url (A-Z・a-z・0-9・-・_ と末尾の =) の連続か確認してください。

既定では(一括・ストリームいずれも)、UTF-8 として不正なバイト列は Base64UrlDecodeError ではなくネイティブの TypeError として伝わります。Base64UrlOptions で strict: false の decoder を注入した場合は Base64UrlDecodeError として投げられます。

import { Base64Url, Base64UrlDecodeError } from "@unikvs/base64url";

const base64url = new Base64Url();

try {
  base64url.decode({ data: new TextEncoder().encode("ab+c") });
} catch (error) {
  if (error instanceof Base64UrlDecodeError) {
    console.log("base64url として解釈できません。");
  } else {
    throw error;
  }
}

使用例

Memory と組み合わせた最小例です。書き込んだ値は base64url 化して保存し、読み取り時に自動的に元のバイト列に戻します。

import { Base64Url } from "@unikvs/base64url";
import { Memory } from "@unikvs/memory";
import UniKvs, { type PlainValue } from "unikvs";

const kvs = UniKvs.config<{ data: PlainValue<Uint8Array<ArrayBuffer>> }>()
  .appendTransformer(new Base64Url())
  .appendStorage(new Memory())
  .create();

await kvs.open();

const input = new TextEncoder().encode("foobar");
await kvs.set("data", input);

const output = await kvs.get("data");
console.log(output.length === input.length);

await kvs.close();

このページは役に立ちましたか?