Class: ElasticGraph::GraphQL::HTTPEndpoint

Inherits:
Object
  • Object
show all
Defined in:
lib/elastic_graph/graphql/http_endpoint.rb

Overview

Handles HTTP concerns for when ElasticGraph is served via HTTP. The logic here is based on the graphql.org recommendations:

graphql.org/learn/serving-over-http/#http-methods-headers-and-body

As that recommends, we support queries in 3 different HTTP forms:

  • A standard POST request as application/json with query/operationName/variables in the body.

  • A GET request with ‘query`, `operationName` and `variables` query params in the URL.

  • A POST as application/graphql with a query string in the body.

Note that this is designed to be agnostic to what the calling HTTP context is (for example, AWS Lambda, or Rails, or Rack…). Instead, this uses simple Request/Response value objects that the calling context can easily translate to/from to use this in any HTTP context.

Constant Summary collapse

APPLICATION_JSON =
"application/json"
APPLICATION_GRAPHQL =
"application/graphql"

Instance Method Summary collapse

Constructor Details

#initialize(query_executor:, monotonic_clock:, client_resolver:) ⇒ HTTPEndpoint

Returns a new instance of HTTPEndpoint.



34
35
36
37
38
# File 'lib/elastic_graph/graphql/http_endpoint.rb', line 34

def initialize(query_executor:, monotonic_clock:, client_resolver:)
  @query_executor = query_executor
  @monotonic_clock = monotonic_clock
  @client_resolver = client_resolver
end

Instance Method Details

#process(request, max_timeout_in_ms: nil, start_time_in_ms: @monotonic_clock.now_in_ms) ⇒ Object

Processes the given HTTP request, returning an HTTP response.

‘max_timeout_in_ms` is not a property of the HTTP request (the calling application will determine it instead!) so it is a separate argument.

Note that this method does not convert exceptions to 500 responses. It’s up to the calling application to do that if it wants to (and to determine how much of the exception to return in the HTTP response…).



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/elastic_graph/graphql/http_endpoint.rb', line 48

def process(request, max_timeout_in_ms: nil, start_time_in_ms: @monotonic_clock.now_in_ms)
  client_or_response = @client_resolver.resolve(request)
  return client_or_response if client_or_response.is_a?(HTTPResponse)

  with_parsed_request(request, max_timeout_in_ms: max_timeout_in_ms) do |parsed|
    result = @query_executor.execute(
      parsed.query_string,
      variables: parsed.variables,
      operation_name: parsed.operation_name,
      client: client_or_response,
      timeout_in_ms: parsed.timeout_in_ms,
      context: parsed.context,
      start_time_in_ms: start_time_in_ms
    )

    HTTPResponse.json(200, result.to_h)
  end
rescue RequestExceededDeadlineError
  HTTPResponse.error(504, "Search exceeded requested timeout.")
end