Как использовать значение параметра, заданное пользователем в веб-приложении, в запросе Optic API в Marklogic?
Blockquote
У меня есть веб-приложение (написанное на js), где пользователь может ввести имя (наряду с другими критериями), выполнить поиск по базе данных ML и табличное представление некоторых данных, связанных с этим именем (или других критериев поиска).) возвращается. На первых этапах разработки я писал оптические api-запросы со значением для имени, жестко закодированным в операторе where запроса. Я сделал это, чтобы проверить, что API REST правильно вызывал запрос и т. Д. Что все работает, и я вижу правильные результаты для этого жестко закодированного имени, возвращаемого в веб-приложении. Теперь я хочу передать введенное пользователем значение для имени в запрос API Optic (EntityInformation_Optic_API_Query.json), чтобы заменить жестко закодированное значение в выражении where. Как мне это сделать? Заранее спасибо.
владелец редактировать
Приложение написано на PHP, и я скопировал код ниже. В этом вы можете увидеть, где вызывается оптический API-запрос и где строятся параметры.
<?php
if (!defined('RSS_BASE_URL')) exit;
use MarkLogic\MLPHP as MLPHP;
function rss_api_call($json, $params = array(), $resource = 'rows', $verb = 'POST')
{
$json = __DIR__ . '/json/' . $json;
if (!file_exists($json)) return false;
$request = new MLPHP\RESTRequest('POST', 'rows', $params, file_get_contents($json), array('Content-type' => 'application/json'));
$response = rss_get_client()->send($request);
return json_decode($response->getBody());
}
function rss_api_entities()
{
$params = array();
return rss_api_call('EntityInformation_Optic_API_Query.json', $params);
//return (empty($params)) ? '' : rss_api_call('EntityInformation_Optic_API_Query.json', $params);
}
function rss_api_search()
{
$params = array();
if (isset($_POST['companyname']) && !empty($_POST['companyname']))
{
$params['CompanyName'] = htmlspecialchars($_POST['companyname']);
}
if (isset($_POST['EIN']) && !empty($_POST['ein']))
{
$params['EIN'] = htmlspecialchars($_POST['ein']);
}
if (isset($_POST['city']) && !empty($_POST['city']))
{
$params['EntityCity'] = htmlspecialchars($_POST['city']);
}
if (isset($_POST['state']) && !empty($_POST['state']))
{
$params['EntityState'] = htmlspecialchars($_POST['state']);
}
if (isset($_POST['zip']) && !empty($_POST['zip']))
{
$params['EntityZip'] = htmlspecialchars($_POST['zip']);
}
return rss_api_call('SearchResults_Optic_API_Query.json', $params);
//return (empty($params)) ? '' : rss_api_call('SearchResults_Optic_API_Query.json', $params);
}
function rss_asset_path($path, $file_name)
{
global $rss_manifest;
if (empty($rss_manifest))
{
ob_start();
include(__DIR__ . '/../manifest.json');
$rss_manifest = json_decode(ob_get_clean(), true);
}
if (isset($rss_manifest[$file_name]))
{
$file_name = $rss_manifest[$file_name];
}
return RSS_ASSET_PATH . $path . '/' . $file_name;
}
function rss_box($title, $content)
{
echo '<div class="rss-box">' .
'<div class="rss-box-title">' . $title . '</div>' .
'<div class="rss-box-content">' . $content . '</div>' .
'</div>';
}
function rss_get_client()
{
$mlphp = new MLPHP\MLPHP(array
(
'host' => RSS_API_HOST,
'port' => RSS_API_PORT,
'version' => RSS_API_VERSION,
'username' => RSS_API_USERNAME,
'password' => RSS_API_PASSWORD
));
return $mlphp->getClient();
}
function rss_hidden_search_fields()
{
echo '<div class="rss-hidden">';
$fields = array('debug', 'companyname', 'ein', 'city', 'state', 'zip');
foreach ($fields as $field)
{
echo (isset($_POST[$field])) ? '<input name="' . $field . '" type="hidden" value="' . htmlspecialchars($_POST[$field]) . '" />' : '';
}
if (!empty($_POST['social']))
{
$social = (is_array($_POST['social'])) ? $_POST['social'] : array($_POST['social']);
foreach ($social as $social_network)
{
echo '<input name="social[]" type="hidden" value="' . htmlspecialchars($social_network) . '" />';
}
}
echo (empty($_POST['social-select-all'])) ? '' : '<input name="social-select-all" type="hidden" value="1" />';
echo '</div>';
}
Part of the EntityInformation_Optic_API_Query.json is below
-----
edit (information from a comment below):
The request will be a POST to /v1/rows. Does the following payload look correct?
```javascript
{
"$optic": {
"ns": "op",
"fn": "operators",
"args": [
{
"ns": "op",
"fn": "from-view",
"args": [ "TestSchema", "SUT", null, null ]
},
{
"ns": "op",
"fn": "where",
"args": [
{
"ns": "op",
"fn": "eq",
"args": [
{
"ns": "op",
"fn": "col",
"args": [ "CompanyName" ]
},
"${req.params.CompanyName}"
]
}
]
}
3 ответа
Я считаю, что вам нужно использовать параметры "связать". Итак, ваш план будет выглядеть так:
{
"$optic": {
"ns": "op",
"fn": "operators",
"args": [
{
"ns": "op",
"fn": "from-view",
"args": [
"TestSchema",
"SUT",
null,
null
]
},
{
"ns": "op",
"fn": "where",
"args": [
{
"ns": "op",
"fn": "eq",
"args": [
{
"ns": "op",
"fn": "col",
"args": [
"CompanyName"
]
},
{
"ns": "op",
"fn": "param",
"args": [
"companyName"
]
}
]
}
]
}
]
}
}
И затем, когда вы публикуете это в /v1/row, вам нужно установить companyName
параметр и тип привязки. Итак, добавьте следующие параметры к вашему POST:
bind:companyName=${req.params.CompanyName}
bind:companyName:type=xs:string
Если предположить, ${req.params.CompanyName}
содержит значение названия компании, переданное пользователем.
Как примечание, работа с сериализованными планами Optic вручную может быть сложной. Я бы порекомендовал вам оставить это за расширением REST и просто передать параметры. Если вы действительно хотите сохранить планы Optic на своем среднем уровне, вы всегда можете использовать консоль запросов MarkLogic для создания плана с надлежащим op.param()
вызовы, где вы хотите иметь параметризованные значения. IE что-то вроде:
const op = require('/MarkLogic/optic');
const plan = op
.fromView("TestSchema", "SUT")
.where(
op.eq(
op.col("CompanyName"), op.param("companyName")
)
)
plan.export()
Для веб-приложения Java или Node.js наилучшим подходом может быть написание функции, которая принимает значение, создает и возвращает запрос Optic.
В других средах использование JSON-представления и вставка значения будет наиболее безопасным.
Сборка JSON-сериализации запроса Optic в виде строки возможна с экранированием, хотя иногда это трудно отладить. В коде MarkLogic JSON анализируется как JSON, а не оценивается, поэтому нет риска инъекционных атак, но возможны ошибки синтаксического анализа.
Надеюсь, что это помогает,
Это зависит от того, как вы настраиваете приложение.
REST API
Если ваш код будет расширением REST API, функция, которую вы напишете, будет иметь params
параметр. Для JavaScript это будет объект. Посмотрите Интерфейс Расширения Ресурса JavaScript. Из этой части документов:
Если запрос PUT
/v1/resource/my-ext?rs:p=1&rs:p=2
тогда значениеparams.p
это ["1", "2"].
Основной модуль
Если клиент получит доступ к вашему коду через обычный (не REST) основной модуль, используйте xdmp.getRequestField
,
Изменить: я обновил ваш вопрос с дополнительной информацией из вашего комментария. Мне кажется, что у вас есть средний уровень, который принимает параметры от клиента (браузера) и использует их для построения запроса для передачи /v1/rows
, Это выглядит как "${req.params.CompanyName}"
предназначен для интерполяции, так что ваш средний уровень получает значение req.params.CompanyName
, который затем будет помещен в строку, которая отправляется в MarkLogic.
Возможно ли, что "${req.params.CompanyName}"
добавили в строку с неповрежденными кавычками, чтобы средний уровень не мог выполнить интерполяцию? Если вы можете предоставить больше информации о том, как полезная нагрузка /v1/rows
строится, мы могли бы предложить больше помощи.