如何使用 Perl 发送异步 json 到 PHP url?

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

我正在尝试使用 POST 将一些 json 格式的数据发送到特定的 url test.php。请求应该是异步的,如果数据发送与否,我需要获取http响应代码(我不会等到test.php上处理完请求)。

我已经构建了一个 perl 函数来发送数据

#!/usr/bin/perl

use strict;
use warnings;
use JSON qw(encode_json);
use AnyEvent;
use AnyEvent::HTTP;


=pod
Function send asynchronus data , get response code 
=cut
sub sendOutboundPostRequestAsync {
    my ($url, $data, $token) = @_;

    # Create a condition variable to wait for the asynchronous request
    my $request_done = AnyEvent->condvar;

    # Convert the data hash to JSON
    my $json_data = encode_json($data);
    print "JSON data being sent: $json_data\n";  # For debugging

    # Make the HTTP POST request asynchronously
    http_post $url,
        headers => {
            'Authorization' => $token,
            'Content-Type'  => 'application/json',
        },
        body => $json_data,
        sub {
            my ($body, $headers) = @_;
            my $status_code = $headers->{Status} // 500;  # Default to 500 if no status
            
            # Print the response for debugging
            print "Response Body: $body\n";
            print "Request completed with status code: $status_code\n";

            # Send the status code back through the condition variable
            $request_done->send($status_code);
        };

    return $request_done;  # Return the condition variable for further processing
}


#####
my $url = 'http://xxx.xxx.xxx/test.php';
my $token = 'eyJ0eXAiOiJKV1QiLCJhbGci'; 

# Example data to send
my %data = (
    uniqueid => '1727331196.gesti',
    start_time => '2024-09-26 08:13:17',
);

# Call the function
my $response_code_condvar = sendOutboundPostRequestAsync($url, \%data, $token);
my $response_code         = $response_code_condvar->recv;  # Wait for the request to complete

print "Final Response Code: $response_code\n";

获取数据的 php 代码(出于测试目的而缩短)

<?php
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
ini_set('display_errors', '1');
ini_set('display_startup_errors', '1');
error_reporting(E_ALL);
    
// Retrieve the raw POST data
$postData = file_get_contents('php://input');

// Log all headers for debugging
$headers = getallheaders();
file_put_contents('postData.txt', "Received Headers:\n" . print_r($headers, true) . "\n", FILE_APPEND);

// Specify the file path
$file_path = 'postData.txt';

// Open the file for writing (append mode)
$file = fopen($file_path, 'a'); // Use 'w' to overwrite the file
  
// Write the POST data to the file
fwrite($file, "Received POST data:\n" . $postData . "\n\n");
    
// Close the file
fclose($file);  

// Decode the JSON data
$data = json_decode($postData, true);

// Check if data decoding was successful
if ($data === null) {
    // Handle error: Invalid JSON
    http_response_code(400);
    echo 'Invalid JSON';
    exit;
}

// Extract the action from the decoded data
$action = $data['action'] ?? null;

// Check if the action is set
if ($action === null) {
    // Handle error: Missing action
    http_response_code(400);
    echo 'Missing action';
    exit;
}   
?>

问题

执行 Perl 脚本后我得到

ast1:~ # perl test.agi
JSON data being sent: {"start_time":"2024-09-26 08:13:17","uniqueid":"1727331196.gesti"}
Response Body: Invalid JSON
Request completed with status code: 400
Final Response Code: 400

数据似乎正确,发送应该没有问题,但在 PHP 端的文本日志中我得到了

Received POST data:
headers

期望的输出

Received POST data:
{
    "start_time": "2024-09-26 08:13:17",
    "uniqueid": "1727331196.gesti"
}

问题

  1. 这是使用 Perl 发送异步数据的最佳方式吗?
  2. 数据结果为空可能是什么问题?
php perl
1个回答
0
投票

解决方案是在以下行添加

POST
关键字

 http_request POST => $url,

即使 Perl 脚本正确生成 JSON,请求似乎也无法以预期格式正确发送 JSON 数据,PHP 脚本将输入解释为标头而不是实际的 POST 数据。

这可能是由于 AnyEvent::HTTP 发送请求的方式所致。默认情况下,http_post 使用 URL 编码的表单数据,即使指定了 Content-Type: application/json 标头也是如此。为了正确发送 JSON 数据,我们需要确保请求被视为正确的 JSON 负载。


工作代码

#!/usr/bin/perl

use strict;
use warnings;
use JSON qw(encode_json);
use AnyEvent;
use AnyEvent::HTTP;


=pod
Function send asynchronus data , get response code 
=cut
sub sendOutboundPostRequestAsync {
    my ($url, $data, $token) = @_;

    # Create a condition variable to wait for the asynchronous request
    my $request_done = AnyEvent->condvar;

    # Convert the data hash to JSON
    my $json_data = encode_json($data);
    print "JSON data being sent: $json_data\n";  # For debugging

    # Make the HTTP POST request asynchronously
    http_request POST => $url,
        headers => {
            'Authorization' => $token,
            'Content-Type'  => 'application/json',
        },
        body => $json_data,
        sub {
            my ($body, $headers) = @_;
            my $status_code = $headers->{Status} // 500;  # Default to 500 if no status
            
            # Print the response for debugging
            print "Response Body: $body\n";
            print "Request completed with status code: $status_code\n";

            # Send the status code back through the condition variable
            $request_done->send($status_code);
        };

    return $request_done;  # Return the condition variable for further processing
}


#####
my $url = 'http://xxx.xxx.xxx/testtt.php';
my $token = 'eyJ0eXAiOiJKV1QiLCJhbGci'; 

# Example data to send
my %data = (
    uniqueid => '1727331196.gesti',
    start_time => '2024-09-26 08:13:17',
);

# Call the function
my $response_code_condvar = sendOutboundPostRequestAsync($url, \%data, $token);
my $response_code         = $response_code_condvar->recv;  # Wait for the request to complete

print "Final Response Code: $response_code\n";

从 Perl 方面

ast1:~ # perl /var/lib/asterisk/agi-bin/it_agi/testt.agi
JSON data being sent: {"start_time":"2024-09-26 08:13:17","uniqueid":"1727331196.gesti"}
Response Body: Missing action
Request completed with status code: 400
Final Response Code: 400

来自 PHP

Received POST data:
{"start_time":"2024-09-26 08:13:17","uniqueid":"1727331196.gesti"}
© www.soinside.com 2019 - 2024. All rights reserved.