Skip to content
ferroseekdocumentation homemain, packages at version v0.1.0
Ferroseek on GitHub

Routes

Ferroseek serves a subset of the Elasticsearch 7.17 REST API. Requests and responses have the same shape as Elasticsearch’s. Every response, including errors, carries Content-Type: application/json; charset=UTF-8 and X-Elastic-Product: Elasticsearch; the official clients (7.14 and later) refuse a server without that header.

One Worker serves one index. In the examples it is products, the name given to the index builder with --name.

Method Path Answer
GET, HEAD / Cluster information, with version.number "7.17.4"
GET, POST /{index}/_search Search; body as in Queries
GET, POST /{index}/_count {"count": n, "_shards": …}; optional body {"query": …}
GET /{index}/_doc/{id} The document, or 404 with "found": false
GET /{index}/_mapping The mapping, properties sorted by name
GET, POST /_msearch, /{index}/_msearch Several searches in one request

A request for an index other than the one loaded answers 404 index_not_found_exception, as Elasticsearch does.

{
"name": "ferroseek",
"cluster_name": "ferroseek",
"cluster_uuid": "ferroseek",
"version": {
"number": "7.17.4",
"build_flavor": "default",
"build_type": "ferroseek",
"lucene_version": "8.11.1",
"minimum_wire_compatibility_version": "6.8.0",
"minimum_index_compatibility_version": "6.0.0-beta1"
},
"tagline": "You Know, for Search"
}

(Some version fields are left out here.) Clients use this route to check what they are talking to; Ferroseek reports the Elasticsearch version whose behaviour it reproduces.

GET and POST behave the same. With no body, the search matches all documents and returns the first 10. The body accepts query, post_filter, aggs (or aggregations), sort, from, size, _source, track_total_hits, track_scores and search_after. Anything else is rejected; see Limits and differences.

The body is optional and may only contain query:

curl -s http://localhost:4090/products/_count \
-H 'Content-Type: application/json' \
-d '{ "query": { "term": { "color": "red" } } }'
{ "count": 8484, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 } }
{
"_index": "products",
"_type": "_doc",
"_id": "SKU-000001",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": { "sku": "SKU-000001", "name": "Sonece Wireless Crib A100", "…": "…" }
}

An unknown id answers 404 with {"_index": "products", "_type": "_doc", "_id": "…", "found": false}.

The body is NDJSON: a header line, then a body line, for each search. A header may only contain index; with /{index}/_msearch, it may be empty ({}). The response has one entry per search, each either a search response with "status": 200 or an error object.

printf '%s\n' \
'{"index":"products"}' '{"size":0,"query":{"term":{"color":"red"}}}' \
'{"index":"products"}' '{"size":0}' \
| curl -s http://localhost:4090/_msearch \
-H 'Content-Type: application/x-ndjson' --data-binary @-

At most 32 searches per request, and they share one CPU budget and one response-size budget. See Limits and differences.

Only pretty is accepted (?pretty or ?pretty=true), which indents the response. Any other parameter, including ones Elasticsearch accepts such as ?size= or ?q=, is rejected:

{
"error": {
"type": "illegal_argument_exception",
"reason": "request [/products/_search] contains unrecognized parameter: [size]",
"root_cause": [ { "type": "illegal_argument_exception", "reason": "request [/products/_search] contains unrecognized parameter: [size]" } ]
},
"status": 400
}

Put search options in the request body instead.

  • A known route with the wrong method, such as DELETE /products/_search, answers 405 with illegal_argument_exception (“Incorrect HTTP method for uri …”).
  • Any other path answers 400 with illegal_argument_exception (“no handler found for uri … and method …”).

There are no write routes: no _bulk, no PUT /{index}/_doc/{id}, no index management. The index is built offline; see Build and update the index.