如何将我的请求与responseMiddleware 中的响应关联起来?

问题描述 投票:0回答:1

我尝试为 Laravel 的 http 客户端提供自定义日志机制:


$httpClient = Http::withBasicAuth($this->apiKey, $this->apiSecret)
            ->retry(3,100,null,false)
            ->withRequestMiddleware(function (RequestInterface $request) {
                $identifier = $request->getHeaderLine('X-RequestId'); 
                $attempt = $request->getAttribute('retry_attempts',1);

                $authMethod = $request->getHeaderLine('Authorization')??null;
                $authMethod  = is_string($authMethod)?preg_replace("/\s*(\w+)\s+.*/","\$1",$authMethod):null;

                DB::table('api_call_log')->insert([
                    'identifier'=>$identifier,
                    'attempt'=>$attempt,
                    'method'=>$request->getMethod(),
                    'url' => $request->getUri(),
                    'request_auth_method'=>$authMethod,
                    'headers' => serialize($request->getHeaders()),
                    'body' => serialize($request->getBody()),
                    'request_start_unix' => now()->unix(),
                ]);

                return $request;
            })
            ->withResponseMiddleware(function(ResponseInterface $response) {
               // How I can get requestId and attempt here
            });
    }

记录到此表:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::dropIfExists('api_call_log');

        Schema::create('api_call_log', function (Blueprint $table) {
           $table->string('identifier', 32);
           $table->integer('attempt')->default(1)->unsigned();

           $table->primary(['identifier','attempt']);

           $table->string('method', 32);
           $table->string('url', 32);
           $table->string('request_auth_method', 32)->nullable();
           $table->binary('headers')->nullable();
           $table->binary('body')->nullable();
           $table->integer('request_start_unix')->unsigned();
           $table->integer('request_end_unix')->unsigned()->nullable();
           $table->smallInteger('response_code')->unsigned()->nullable();
           $table->binary('response_body')->nullable();
           $table->binary('response_headers')->nullable();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('api_call_log');
    }
};

这个想法是,一旦我尝试调用请求,我会在

withRequestMiddleware
上记录尝试,完成后,我会在
withResponseMiddleware
上记录每个请求的响应,我会提供一个唯一的标识符,以便每次尝试调用 api 时都可以进行分组:


  $requestId = Str::uuid()->toString();
  $endpoint = $this->apiUrl.'/myendpoint';
  $response = $this->httpClient->withHeaders(['X-RequestId'=>$requestId])
            ->put($endpoint,['name'=>"Hello"]);

这样我每次尝试调用 api 时都可以保留日志并记录尝试是否成功。

问题是我如何将必要的请求与我在

withResponseMiddleware
关闭时的响应关联起来?

php laravel laravel-http-client
1个回答
0
投票

还有另一个技巧可能对你的情况有帮助

首先创建一个名为

macro
withRequestId
,如下所示

Http::macro('withRequestId', function ($id) {
   return $this->withHeaders(['X-Request-ID' => $id]);
});

之后你可以像这样到达相同的请求ID


 $id = str()->uuid()->toString();
 
 $response = Http::withRequestId($id)->get('https://google.com');

 info(['request_id' => $id]);
© www.soinside.com 2019 - 2024. All rights reserved.