LoginSignup
0
0

More than 1 year has passed since last update.

kintone REST API:GETのURL文字数制限を回避

Last updated at Posted at 2021-03-04

問題

Google Apps Script で kintone REST API を実行する際、
GET の query が長くなるなどで下記エラーとなることがあります。
Exception: Limit Exceeded: URLFetch URL Length.

Google Apps Script では URL の長さは 2kB に制限されているようです。
https://developers.google.com/apps-script/guides/services/quotas

回避案

カーソルを用いたレコード一括取得で回避する例です。

カーソルAPIの本来の目的は、大量のレコード取得を高速に行うことだと思いますが、
https://developer.cybozu.io/hc/ja/articles/360028843531

query を POST でリクエストできることを利用しました。
https://developer.cybozu.io/hc/ja/articles/360029152012

以下は typescript(clasp)での実装例ですが
公式ドキュメントの方が分かりやすいかと思います。

KintoneApi.ts
type Method = GoogleAppsScript.URL_Fetch.HttpMethod;
type Payload = GoogleAppsScript.URL_Fetch.Payload;
type Options = GoogleAppsScript.URL_Fetch.URLFetchRequestOptions;

export default class KintoneApi {
    private host = 'foo-host';
    private user = {
        id      : '',
        password: ''
    };
    constructor(userId: string, password: string) {
        this.user.id = userId;
        this.user.password = password;
    }

    private fetch(endpoint: string, method: Method, payload?: Payload) {
        const options: Options = {
            method  : method,
            headers : {'X-Cybozu-Authorization': Utilities.base64Encode(this.user.id + ':' + this.user.password)},
        };
        if (method != 'get') options.contentType = 'application/json';
        if (payload) options.payload = JSON.stringify(payload);
        const resp = UrlFetchApp.fetch(`https://${this.host}.cybozu.com/k/v1/${endpoint}`, options);
        return JSON.parse(resp.getContentText());
    }

    public getByCursor<T>(appId: number, query: string, fields?: string[]): T[] {
        const payload: Payload = {
            app     : appId,
            query   : query,
            size    : 500
        };
        if (fields) payload.fields = fields;
        const cursor: {id: string} = this.fetch(`records/cursor.json`, 'post', payload);

        try {
            type CursorResp = {records: T[], next: boolean};
            const ret: CursorResp = {records: [], next: true};
            while (ret.next) {  //GASでは非同期とならない
                Utilities.sleep(1000);
                const resp: CursorResp = this.fetch(`records/cursor.json?id=${cursor.id}`, 'get');
                ret.records.push(...resp.records);
                ret.next = resp.next;
            }
            return ret.records;
        } catch (err) {
            try {
                Utilities.sleep(1000);
                this.fetch(`records/cursor.json`, 'delete', {id: cursor.id});
            } catch (delErr) {
                // do nothing
            }
            throw err;
        }
    }
}

exec.ts
import KintoneApi from 'path/to/KintoneApi';

const kintone = new KintoneApi('fooId', 'fooPassword');
const records = kintone.getByCursor<any>(0 /* appId */, 'very long query string over 2kB...');
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0