Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions controllers/federation_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
require 'faraday'

class FederationController < ApplicationController

GATEWAY_URL = "https://terminology.services.base4nfdi.de/api-gateway"
GATEWAY_CONNECTION = Faraday.new(url: GATEWAY_URL) do |conn|
conn.headers['Accept'] = 'application/json'
end


namespace "/api/federation" do

get'/search' do
query = params[:query] || params[:q]

if query.nil? || query.strip.empty?
error 400, "You must provide a 'query' parameter to execute a search"
end

gateway_params = { query: query, database: "ontoportal" }

response = GATEWAY_CONNECTION.get("search", gateway_params)

unless response.success?
error response.status, "API Gateway error: #{response.body}"
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid returning the raw upstream response body to clients on gateway errors; it can be large and may leak upstream details. Prefer a generic client-facing message and log the gateway body/status for debugging.

Suggested change
error response.status, "API Gateway error: #{response.body}"
Rails.logger.error("API Gateway error: status=#{response.status}, body=#{response.body}") if defined?(Rails) && Rails.respond_to?(:logger) && Rails.logger
error response.status, "API Gateway error: upstream service returned an error"

Copilot uses AI. Check for mistakes.
end

gateway_response_data = JSON.parse(response.body)
results = gateway_response_data.is_a?(Array) ? gateway_response_data : []

docs = []

results.each do |item|
acronym = item["ontology"]
ontology_iri = item["ontology_iri"] || item["source"].to_s + "/ontologies/" + acronym.to_s

doc = {
id: item["@id"] || item["iri"],
prefLabel: item["label"],
synonym: item["synonyms"] || [],
definition: item["descriptions"] || [],
obsolete: item["obsolete"] || false,
matchType: "",
ontologyType: "",
ontology_rank: 0.0
}

ontology = LinkedData::Models::Ontology.read_only(
id: ontology_iri,
acronym: acronym
)

submission = LinkedData::Models::OntologySubmission.read_only(
id: ontology_iri ,
ontology: ontology
)

doc[:submission] = submission

instance = LinkedData::Models::Class.read_only(doc)
docs.push(instance)

end

total_found = results.size

reply 200, page_object(docs, total_found)
Copy link

Copilot AI Mar 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This endpoint ignores page/pagesize request params and always returns all gateway results. Because page_object assumes the collection is already paginated, this can produce responses where itemsPerPage doesn’t match the number of returned members and pagination links become misleading. Please apply local slicing (using page_params + offset_and_limit) before building the page object.

Suggested change
reply 200, page_object(docs, total_found)
page, page_size = page_params
offset, limit = offset_and_limit(total_found, page, page_size)
paginated_docs = docs.slice(offset, limit) || []
reply 200, page_object(paginated_docs, total_found)

Copilot uses AI. Check for mistakes.
end

end

end
Loading