У меня есть api, который является точкой входа в кластер elasticsearch. API не совсем тривиален со многими входными параметрами xxx.contains=
, yyy.in=
и zzz.equals=
, которые я перевожу в запрос ES POST. Затем я использую ax ios для прямого запроса кластера ES. Он работает нормально.
const buildElasticSearchRequestBody = (page, size, params) => {
//highlighting options https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-highlighting.html
let requestBody = {
from: page * size,
size: size,
highlight:
params.highlight === "true" || params.highlight == true
? highlightOptions
: {},
};
let must = [];
//For now we are doing an AND across supplied field predicates- AND in ES is 'must'
let queryObj = {
bool: {
must: must,
},
};
for (const [key, value] of Object.entries(params).filter((pair) =>
searchTypes.some((searchType) => pair[0].includes(searchType))
)) {
if (!allowedSearches.includes(key)) {
throw new Error(`Search key ${key} is not permitted currently`);
}
//we need to exclude empty or undefined params but allow true/false
if (value === "" || value == undefined) {
continue;
}
const field = key.split(".")[0];
//.contains queries are ES 'match's
//https://www.elastic.co/guide/en/elasticsearch/reference/master/query-dsl-match-query.html
if (key.includes(".contains")) {
if (key.includes("any.")) {
//but any.contains is our special case
must.push({
simple_query_string: {
query: value,
default_operator: "and",
},
});
} else {
must.push({
match: {
[field]: {
query: value,
fuzziness: "AUTO",
operator: "AND",
},
},
});
}
}
//.contains queries are ES 'term's
if (key.includes(".equals")) {
//use ES terms
must.push({
term: {
[field]: value,
},
});
}
if (key.includes(".in")) {
//use ES terms
if (value) {
const stringified = value.toString().replace(",", " ");
if (key.includes("any.")) {
must.push({
simple_query_string: {
query: value,
default_operator: "or",
},
});
} else {
must.push({
match: {
[field]: {
query: stringified,
operator: "OR",
},
},
});
}
}
}
// "than" queries are ES range queries"
if (key.includes("Than")) {
//use ES range
let op;
if (key.includes("greaterThanOrEqual")) {
op = "gte";
} else {
op = "lte";
}
must.push({
range: {
[field]: {
[op]: value,
},
},
});
}
if (key.includes("custom.glutenFree")) {
if (value === true || value === "true") {
must.push({
simple_query_string: {
query: '"gluten free"',
default_operator: "and",
},
});
} else {
must.push({
simple_query_string: {
query: '-("gluten free")',
default_operator: "and",
},
});
}
}
if (key.includes("custom.grainFree")) {
if (value === true || value === "true") {
must.push({
simple_query_string: {
query: '"grain free"',
default_operator: "and",
},
});
} else {
must.push({
simple_query_string: {
query: '-("grain free")',
default_operator: "and",
},
});
}
}
}
if (must.length != 0) {
requestBody.query = queryObj;
}
return requestBody;
};
Очевидная потенциальная проблема здесь (я думаю) - это атака с помощью инъекции. На самом деле я должен использовать библиотеку ElasticSearch для выполнения запроса, но, вероятно, это будет сложно, поэтому мне интересно, каким будет правильный способ дезинфекции любых значений?