bugfix> node.js > 投稿

amazons Sponsored Products APIからproductAdsをダウンロードする次のアプリがあります

ドキュメント:https://advertising.amazon.com/API/docs/reference/reports

楽しんでみると、レポートをリクエストして応答が返され、s3バケットのファイルが取得されます。

server is running at localhost:3000
{"reportId":"amzn1.clicPI.v1.p7.5B7EE.d141f-e5-4b-a8-6a4e712","status":"SUCCESS","statusDetails":"Report has been successfully generated","location":"https://advertising-api.amazon.com/v1/reports/amzn1.clsAPI.v1.p7.5B7EE.d151f-e5-4b-a8-699e712/download","fileSize":22}

次に、レポートをダウンロードしてみます

そして安息は私が次のエラーを取得します:

donwloading <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>InvalidArgument</Code><Message>Only one auth mechanism allowed; only the X-Amz-Algorithm query parameter, Signature query string parameter or the Authorization header should be specified</Message><ArgumentName>Authorization</ArgumentName><ArgumentValue>bearer Atza|IwEBIJvCt20TUi122srkN4JCOdUxlBNuLJBrtbIGF9x5QbKG67f-K-0L4RkLzeyouXWy_U_-VscaCe1aFqOJK55X9Mu2X6nwWkAWRyhc6cCMfPjKpyyVjKtPqC8Plme84om1dqtmIqC93yUVc_clHimQqmnl262te2EXyUhYoVQg8hK2nlDG67Iw7xjsLK4rgl3E4RR36DHnZkEOnVQZtfjIkIbcYtsCSAdpRZRazF4FQfpS-jHvMlwuH8TZfY9tRpmBEx5fjJw1WZ14Dejqti23mZ7yt-MjNkUuD-DdPXs3fek1ZJePlHEVzcI2y_WzCnwJnoSVp5a5w1WgNco8YqEGEuLsT9S0dxQRluTiw8f4b4lx2FFFm9jz0K7pqo1Mvs6DZOVCDJzE-xJ_VLlWoE5QDMUAMor4AEQH44_0NWBjJDrYaVvn1vZLCER1uxW4jgr127W5yXaj4y1vj_vADwFq9a3330hAc73EWwL6FFSfoTQZyNc4Fh1d3DXfVHpXFk6cv0bHt4cV_OotGwGHat5fv75VHX5K3al3Xd5-QJv2cTiQ9srY5oqKsdbxptGaxAdrdMQaUlFHhyHEGbwED9xYoCw6-IauN15gvMAei9wz2kzRCA</ArgumentValue><RequestId>BDCE812C4363E9D2</RequestId><HostId>4ixH24mPtMBt+FDnI3rM9UJP95toaNBmmR1v0uQJ5XkyiXbtLEuZ8d+vDI0+gquwhn6/Fkz6/+o=</HostId></Error>

こちらがアプリです。レポートをダウンロードしてヘッダーを正しく渡すにはどうすればよいですか?ダウンロード機能を備えたPHPでこのレポを見つけました:https://github.com/dbrent-amazon/amazon-advertising-api-php/blob/master/AmazonAdvertisingApi/Client.php

const express = require('express')
const app = express();
const request = require('request');
const moment = require('moment');
const fs = require('fs')
const path = require('path')
const config = require('./config')
const auth = require('./helpers/auth');
const cron = require('./helpers/cron');
const con = require('./helpers/database');
const getProfiles = (headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/profiles',
            method: "GET",
            headers: headers
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}
const createReport = (params, recordType, headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/' + recordType + '/report',
            method: "POST",
            headers: headers,
            json: params
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}
const getReport = (reportId, headers) => {
    return new Promise((resolve, reject) => {
        request({
            url: config.ad_url + '/v1/reports/' + reportId,
            method: "GET",
            headers: headers
        }, (err, httpResponse, body) => {
            if (err) {
                reject(err);
            }
            resolve(body);
        });
    })
}
function download(fileUrl, apiPath, callback) {
    var url = require('url'),
        http = require('http'),
        p = url.parse(fileUrl),
        timeout = 10000;
    var file = fs.createWriteStream(apiPath);
    var timeout_wrapper = function (req) {
        return function () {
            console.log('abort');
            req.abort();
            callback("File transfer timeout!");
        };
    };

    console.log('before');
    var request = http.get(fileUrl).on('response', function (res) {
        console.log('in cb');
        var len = parseInt(res.headers['content-length'], 10);
        var downloaded = 0;
        res.on('data', function (chunk) {
            file.write(chunk);
            downloaded += chunk.length;
            process.stdout.write("Downloading " + (100.0 * downloaded / len).toFixed(2) + "% " + downloaded + " bytes" + isWin ? "\033[0G" : "\r");
            // reset timeout
            clearTimeout(timeoutId);
            timeoutId = setTimeout(fn, timeout);
        }).on('end', function () {
            // clear timeout
            clearTimeout(timeoutId);
            file.end();
            console.log(file_name + ' downloaded to: ' + apiPath);
            callback(null);
        }).on('error', function (err) {
            // clear timeout
            clearTimeout(timeoutId);
            callback(err.message);
        });
    });
    // generate timeout handler
    var fn = timeout_wrapper(request);
    // set initial timeout
    var timeoutId = setTimeout(fn, timeout);
}
const recordType = 'productAds';
const campaignType = 'sponsoredProducts';
const reportDate = moment().format('YYYYMMDD');
const metrics = 'campaignId,sku,currency,attributedConversions1d';
const reportParam = {
    campaignType: campaignType,  
    // segment: "query",
    reportDate: reportDate,      
    metrics: metrics             
}

auth().then(res => {
    const headers = {
        'Content-Type': 'application/json',
        'Authorization': config.token_type + ' ' + res.access_token,
        'Amazon-Advertising-API-Scope': '196354651614',
    }
    // getProfiles(headers).then(res => {})
    const reportId = 'amzn1.clicksAI.1.p.5B057EE.d41f-e5-4a-a8-699e712';
        getReport(reportId, headers).then(res => {
            console.log(res)
            const file = JSON.parse(res);
            // console.log(file.location )
            // download
            request({
                url: file.location,
                method: 'GET',
                headers: {
                    'Authorization': headers.Authorization,
                    'Amazon-Advertising-API-Scope': '196335474',
                    'Allow': 'GET, HEAD, PUT, DELETE'
                }
            }, (err, response, body) => {
                console.log('donwloading', body)
            })
        })
    createReport(reportParam, recordType, headers).then(res => {
        const reportId = 'amzn1.clicksI.v1.p7.5B07EE.d1541f-e5-eb-a68-6996e712';
    })
})

app.listen(3000, function(err) {
    console.log("server is running at localhost:3000");
})

回答 1 件
  • これは、「Authorization」ヘッダーをS3に送信するために発生しますが、これは望ましくありません。これは、APIからの/ download応答がリダイレクト307であるため、使用しているクライアントが完全なAPIヘッダーでリダイレクトしているためです。これを回避するには、クライアントがリダイレクトをたどらないようにし、代わりに応答のヘッダーからS3ロケーションを解析します。

あなたの答え