在 V8Js 中运行 Axios 时,所有请求都失败,因为XMLHttpRequest
不可用。
我们如何使 axios 请求在服务器端工作?
可以使用 V8J 将 PHP 函数或类绑定到 JavaScript。
例如,在 PHP 中,您可以:
$v8 = new \V8Js();
$v8->sayHello = function($name) {
print('Hello ' . $name);
};
$js = 'PHP.sayHello('Bob')';
$v8->executeString($js);
执行时,这将产生字符串“Hello Bob”。
因此,知道了这一点,我们可以在 PHP 中创建 XMLHttpRequest,然后以相同的方式将其绑定到 JS。
首先,我们需要创建 XMLHttpRequest 类来实际发出请求。为此,我使用 Guzzle。
<?php
namespace App\Http\Helpers;
use GuzzleHttp\Client;
class XMLHttpRequest
{
protected $url;
protected $method;
public $status;
public $statusText;
public $readyState;
public $responseData;
public $responseHeaders;
public $onreadystatechange;
public function open($method, $url)
{
$this->method = $method;
$this->url = $url;
}
public function send($data = '')
{
$headers = [];
// Here I am using a Laravel function to fetch the session id but this could be replaced
if($sessionId = request()->session()->getId()) {
// Set whatever auth values are needed for your application
$headers['Cookie'] = 'session=' . $sessionId;
}
$options = [
'http_errors' => false,
'headers' => $headers,
'body' => $data
];
$client = new Client();
$response = $client->request($this->method, $this->url, $options);
$this->responseHeaders = $response->getHeaders();
$this->responseData = (string) $response->getBody();
$this->status = $response->getStatusCode();
$this->readyState = 4;
$this->statusText = $response->getReasonPhrase();
if (is_callable($this->onreadystatechange)) {
call_user_func($this->onreadystatechange);
}
}
}
然后在创建 V8Js 实例后,我们可以附加新库:
$v8 = new \V8Js();
$v8->XMLHttpRequest = function () {
return new XMLHttpRequest;
};
现在我们需要告诉 Axios 使用我们的库。我们可以通过首先创建一个适配器来做到这一点:
const XMLHttpRequest = PHP.XMLHttpRequest;
const adapter = (config) => {
return new Promise(function(resolve, reject) {
const xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = () => {
const response = {
data: xhttp.responseData,
status: xhttp.status,
statusText: xhttp.statusText,
headers: xhttp.responseHeaders,
config: config,
request: {}
};
settle(resolve, reject, response);
};
xhttp.open(config.method, config.baseURL + config.url);
xhttp.send();
})
}
然后添加一个拦截器来设置适配器和baseURL:
axios.interceptors.request.use(config => {
config.baseURL = 'https://YOUR-URL.com'
config.adapter = adapter
return config
})
在此之后使用正常axios.post
将工作服务器端。