web-dev-qa-db-ja.com

AWS Gateway APIを使用して、Cookieにアクセスできますか?

HTTPプロキシ統合を使用してCookieにアクセスし、json応答に追加したいと思います。それは可能ですか?

9
Barry King

バックエンドでクライアントから送信されたCookieにアクセスするには、メソッドリクエストヘッダーから統合リクエストヘッダーへのマッピングを設定する必要があります。

これらの手順は、APIGatewayで簡単なメソッドをすでに設定していることを前提としています。

バックエンドのCookieにアクセスします

  1. [メソッドリクエスト]で、「Cookie」という名前のHTTPリクエストヘッダーを作成します
  2. Integration Requestの下で、「Cookie」という名前と「Mappedfrom」の値がmethod.request.header.CookieのHTTPヘッダーを作成します。
  3. また、このメソッドのCORSを設定する必要がある可能性があります。参照: http://docs.aws.Amazon.com/apigateway/latest/developerguide/how-to-cors.html
  4. APIをデプロイし、ブラウザ/クライアントを使用してAPIGatewayエンドポイントにリクエストを送信します。ブラウザから送信されたCookieヘッダー値とともにHTTPバックエンドにリクエストが届くのを確認する必要があります。

応答にCookieを追加します

メソッド構成の統合応答/メソッド応答側と同様の方法で、Set-Cookie応答ヘッダーを設定できます。

  1. [メソッド応答]で、Set-Cookieという名前の応答ヘッダーを作成します
  2. Integration Responseの設定で、ResponseヘッダーSet-Cookieとマッピング値integration.response.header.Set-Cookieを使用したヘッダーマッピングを設定します。

現時点では、APIGatewayは単一のSet-Cookie応答ヘッダーの設定のみをサポートしていることに注意してください。バックエンドが複数のSet-Cookieヘッダーを設定しようとすると、最後のヘッダーのみが設定されます。詳細については、このフォーラムの投稿を参照してください: https://forums.aws.Amazon.com/thread.jspa?messageID=701434

9
Lorenzo de Lara

APIGatewayメソッドで[UseLambda Proxy Integration]オプションをオンにすると、リクエストヘッダーがevent変数を介してLambda関数に渡されます。 API Gatewayは、コールバック関数からの異なる応答も期待します。この応答形式は、Set-Cookieヘッダーを指示するために使用できます。例えば。:

callback(null, {
    statusCode: 200,
    headers: {'Set-Cookie': 'key=val'},
    body: 'Some response'
})`

このアプローチには、メソッド要求またはメソッド応答の調整を必要としないという利点があります。

これは、このロジックを使用して各リクエストの後にCookie値をローテーションするLambda関数のサンプルです。

exports.handler = (event, context, callback) => {

    var cookies = getCookiesFromHeader(event.headers);

    var old_cookie = cookies.flavor;
    var new_cookie = pickCookieFlavor(old_cookie);

    return callback(null, {
        statusCode: 200,
        headers: {
            'Set-Cookie': setCookieString('flavor', new_cookie),
            'Content-Type': 'text/plain'
        },
        body: 'Your cookie flavor was ' + old_cookie + '. Your new flavor is ' + new_cookie + '.'
    });
};

/**
 * Rotate the cookie flavor
 */
function pickCookieFlavor(cookie) {
    switch (cookie) {
        case 'peanut':
            return 'chocolate';
        case 'chocolate':
            return 'raisin and oat';
        default:
            return 'peanut';
    }
}

/**
 * Receives an array of headers and extract the value from the cookie header
 * @param  {String}   errors List of errors
 * @return {Object}
 */
function getCookiesFromHeader(headers) {

    if (headers === null || headers === undefined || headers.Cookie === undefined) {
        return {};
    }

    // Split a cookie string in an array (Originally found http://stackoverflow.com/a/3409200/1427439)
    var list = {},
        rc = headers.Cookie;

    rc && rc.split(';').forEach(function( cookie ) {
        var parts = cookie.split('=');
        var key = parts.shift().trim()
        var value = decodeURI(parts.join('='));
        if (key != '') {
            list[key] = value
        }
    });

    return list;
};


/**
 * Build a string appropriate for a `Set-Cookie` header.
 * @param {string} key     Key-name for the cookie.
 * @param {string} value   Value to assign to the cookie.
 * @param {object} options Optional parameter that can be use to define additional option for the cookie.
 * ```
 * {
 *     secure: boolean // Watever to output the secure flag. Defaults to true.
 *     httpOnly: boolean // Watever to ouput the HttpOnly flag. Defaults to true.
 *     domain: string // Domain to which the limit the cookie. Default to not being outputted.
 *     path: string // Path to which to limit the cookie. Defaults to '/'
 *     expires: UTC string or Date // When this cookie should expire.  Default to not being outputted.
 *     maxAge: integer // Max age of the cookie in seconds. For compatibility with IE, this will be converted to a
*          `expires` flag. If both the expires and maxAge flags are set, maxAge will be ignores. Default to not being
*           outputted.
 * }
 * ```
 * @return string
 */
function setCookieString(key, value, options) {
    var defaults = {
        secure: true,
        httpOnly: true,
        domain: false,
        path: '/',
        expires: false,
        maxAge: false
    }
    if (typeof options == 'object') {
        options = Object.assign({}, defaults, options);
    } else {
        options = defaults;
    }

    var cookie = key + '=' + value;

    if (options.domain) {
        cookie = cookie + '; domain=' + options.domain;
    }

    if (options.path) {
        cookie = cookie + '; path=' + options.path;
    }

    if (!options.expires && options.maxAge) {
        options.expires = new Date(new Date().getTime() + parseInt(options.maxAge) * 1000); // JS operate in Milli-seconds
    }

    if (typeof options.expires == "object" && typeof options.expires.toUTCString) {
        options.expires = options.expires.toUTCString();
    }

    if (options.expires) {
        cookie = cookie + '; expires=' + options.expires.toString();
    }

    if (options.secure) {
        cookie = cookie + '; Secure';
    }

    if (options.httpOnly) {
        cookie = cookie + '; HttpOnly';
    }

    return cookie;
}
8