我正在尝试将 Amazon CloudSearch 集成到 SilverStripe 中。我想要做的是当页面发布时我想要一个 CURL 请求将关于页面的数据作为 JSON 字符串发送到搜索云。
我正在使用 http://docs.aws.amazon.com/cloudsearch/latest/developerguide/uploading-data.html#uploading-data-api 作为参考。
每次我尝试上传时,它都会返回 403。我也在搜索域的访问策略中允许了 IP 地址。
我将其用作代码参考:https://github.com/markwilson/AwsCloudSearchPhp
我认为问题是 AWS 没有正确验证。我如何正确验证它?
如果您遇到以下错误
403 Forbidden, Request forbidden by administrative rules.
如果你确定你有适当的规则,我会检查你正在使用的 api url。确保您使用的是正确的端点。如果您正在进行批量上传,则 api 端点应如下所示
your-search-doc-endpoint/2013-01-01/documents/batch
通知 2013-01-01,这是 url 的必需部分。那就是您将使用的 api 版本。您不能执行以下操作,即使它可能有意义
your-search-doc-endpoint/documents/batch<- Won't work
要搜索,您需要点击以下 api
your-search-endpoint/2013-01-01/search?your-search-params
经过多次搜索和反复试验后,我能够将来自各处的小代码块组合成一个小代码块,以便能够使用 CURL 和 PHP 将“文件”上传到 aws cloudsearch。
最重要的一件事是确保您的数据已正确准备好以 JSON 格式发送。
注意:对于云搜索,您不是在上传文件,而是在发布 JSON 数据流。这就是为什么我们很多人在上传数据时遇到问题。
所以在我的例子中,我希望能够上传我的搜索引擎在 clousearch 上的数据,这看起来很简单,但确实缺少示例代码来做到这一点,大多数人告诉你去通常的文档有示例,但要使用 aws CLI。 php SDK 只是一个学习障碍,而不是让它变得简单,你需要执行 20 个步骤来完成一项任务,而且你不仅需要拥有所有这些其他库,这些库只是原生 PHP 函数的包装器,有时而不是制作它简单它变得复杂。
回到我的做法,首先我从数据库中提取数据作为数组并将其序列化以将其保存到文件中。
$row = $database_data;
foreach ($rows as $key => $row) {
$data['type'] = 'add';
$data['id'] = $row->id;
$data['fields']['title'] = $row->title;
$data['fields']['content'] = $row->content;
$data2[] = $data;
}
// now save your data to a file and make sure
// to serialize() it
$fp = fopen($path_to_file, $mode)
flock($fp, LOCK_EX);
fwrite($fp, serialize($data2));
flock($fp, LOCK_UN);
fclose($fp);
现在您已经保存了数据,我们可以玩了
$aws_doc_endpoint = '{Your AWS CloudSearch Document Endpoint URL}';
// Lets read the data
$data = file_get_contents($path_to_file);
// Now lets unserialize() it and encoded in JSON format
$data = json_encode(unserialize($data));
// finally lets use CURL
$ch = curl_init($aws_doc_endpoint);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Length: ' . strlen($data)));
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
$response = curl_exec($ch);
curl_close($ch);
$response = json_decode($response);
if ($response->status == 'success')
{
return TRUE;
}
return FALSE;
就像我说的,没什么。我遇到的大多数答案,使用 Guzzle 真的很简单,是的,但是对于像这样的简单任务,你不需要它。
除此之外,如果您仍然遇到错误,请务必检查以下内容。
格式良好的 JSON 数据。 确保您有权访问端点。
好吧,我希望有人觉得这段代码有用。
诊断是否是访问策略问题,是否尝试过允许所有访问上传的策略?像下面这样的东西可以打开一切:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "cloudsearch:*"
}
]
}
我注意到,如果您只是在浏览器中访问文档上传端点(我的看起来像“doc-YOURDOMAIN-RANDOMID.REGION.cloudsearch.amazonaws.com”),您将收到 403“Request forbidden by administrative rules”错误,即使是开放访问,所以@dminer said你需要确保你发布到正确的full url.
您是否考虑过使用 PHP SDK?喜欢http://docs.aws.amazon.com/aws-sdk-php/guide/latest/service-cloudsearchdomain.html。它应该负责提出正确的请求,在这种情况下,您可以排除传输错误。
这对我没用。我使用 Cloudsearch 终端上传文件。和 php curl 来搜索文件。
尝试在 Actions 下的 CloudSearch 访问策略中添加“cloudsearch:document”
我遇到了与
403 Forbidden, Request forbidden by administrative rules
相同的问题。这完全是由于使用文档端点并添加 API 版本,如下所示。
这部分在向云搜索中插入数据时非常重要,需要添加:
由于您尝试将数据插入云搜索,因此您需要使用 AWS 提供给您的云搜索的文档端点。
后面需要跟API版本如下:
https://doc-xxxxx.zzzz.cloudsearch.amazonaws.com/2013-01-01/documents/batch
同时也要注意添加内容类型,否则最终可能会出现
HTTP 415 Unsupported Media Type
错误。
addRequestHeader("Content-Type", "application/xml");