Handle multiple kind of requests in GraphQL controller
* Added support for GET requests * Added support for application/graphql content-type for POST requests * Handling query string parsing errors in controller * Wrote specs for all this
This commit is contained in:
@@ -4,11 +4,25 @@ class GraphqlController < ApplicationController
|
|||||||
skip_authorization_check
|
skip_authorization_check
|
||||||
|
|
||||||
def query
|
def query
|
||||||
# ConsulSchema.execute returns the query result in the shape of a Hash, which
|
|
||||||
# is sent back to the client rendered in JSON
|
if request.headers["CONTENT_TYPE"] == 'application/graphql'
|
||||||
render json: ConsulSchema.execute(
|
query_string = request.body.string # request.body.class => StringIO
|
||||||
params[:query],
|
else
|
||||||
|
query_string = params[:query]
|
||||||
|
end
|
||||||
|
|
||||||
|
if query_string.nil?
|
||||||
|
render json: { message: 'Query string not present' }, status: :bad_request
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
response = ConsulSchema.execute(
|
||||||
|
query_string,
|
||||||
variables: params[:variables] || {}
|
variables: params[:variables] || {}
|
||||||
)
|
)
|
||||||
|
render json: response, status: :ok
|
||||||
|
rescue GraphQL::ParseError
|
||||||
|
render json: { message: 'Query string is not valid JSON' }, status: :bad_request
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -264,6 +264,7 @@ Rails.application.routes.draw do
|
|||||||
|
|
||||||
# GraphQL
|
# GraphQL
|
||||||
mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql'
|
mount GraphiQL::Rails::Engine, at: '/graphiql', graphql_path: '/graphql'
|
||||||
|
get '/graphql', to: 'graphql#query'
|
||||||
post '/graphql', to: 'graphql#query'
|
post '/graphql', to: 'graphql#query'
|
||||||
|
|
||||||
if Rails.env.development?
|
if Rails.env.development?
|
||||||
|
|||||||
@@ -1,90 +1,56 @@
|
|||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
||||||
# Hacerlo como los test de controlador de rails
|
# Useful resource: http://graphql.org/learn/serving-over-http/
|
||||||
|
|
||||||
describe GraphqlController, type: :request do
|
describe GraphqlController, type: :request do
|
||||||
let(:proposal) { create(:proposal) }
|
let(:proposal) { create(:proposal) }
|
||||||
|
|
||||||
it "answers simple json queries" do
|
describe "handles GET request" do
|
||||||
headers = { "CONTENT_TYPE" => "application/json" }
|
specify "with query string inside query params" do
|
||||||
#post "/widgets", '{ "widget": { "name":"My Widget" } }', headers
|
get '/graphql', query: "{ proposal(id: #{proposal.id}) { title } }"
|
||||||
post '/graphql', { query: "{ proposal(id: #{proposal.id}) { title } }" }.to_json, headers
|
expect(response).to have_http_status(:ok)
|
||||||
expect(response).to have_http_status(200)
|
|
||||||
expect(JSON.parse(response.body)['data']['proposal']['title']).to eq(proposal.title)
|
expect(JSON.parse(response.body)['data']['proposal']['title']).to eq(proposal.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
specify "with malformed query string" do
|
||||||
end
|
get '/graphql', query: 'Malformed query string'
|
||||||
|
expect(response).to have_http_status(:bad_request)
|
||||||
=begin
|
expect(JSON.parse(response.body)['message']).to eq('Query string is not valid JSON')
|
||||||
describe GraphqlController do
|
|
||||||
let(:uri) { URI::HTTP.build(host: 'localhost', path: '/graphql', port: 3000) }
|
|
||||||
let(:query_string) { "" }
|
|
||||||
let(:body) { {query: query_string}.to_json }
|
|
||||||
|
|
||||||
describe "POST requests" do
|
|
||||||
let(:author) { create(:user) }
|
|
||||||
let(:proposal) { create(:proposal, author: author) }
|
|
||||||
let(:response) { HTTP.headers('Content-Type' => 'application/json').post(uri, body: body) }
|
|
||||||
let(:response_body) { JSON.parse(response.body) }
|
|
||||||
|
|
||||||
context "when query string is valid" do
|
|
||||||
let(:query_string) { "{ proposal(id: #{proposal.id}) { title, author { username } } }" }
|
|
||||||
let(:returned_proposal) { response_body['data']['proposal'] }
|
|
||||||
|
|
||||||
it "returns HTTP 200 OK" do
|
|
||||||
expect(response.code).to eq(200)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns first-level fields" do
|
specify "without query string" do
|
||||||
expect(returned_proposal['title']).to eq(proposal.title)
|
get '/graphql'
|
||||||
end
|
expect(response).to have_http_status(:bad_request)
|
||||||
|
expect(JSON.parse(response.body)['message']).to eq('Query string not present')
|
||||||
it "returns nested fields" do
|
|
||||||
expect(returned_proposal['author']['username']).to eq(author.username)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when query string asks for invalid fields" do
|
describe "handles POST request" do
|
||||||
let(:query_string) { "{ proposal(id: #{proposal.id}) { missing_field } }" }
|
let(:json_headers) { { "CONTENT_TYPE" => "application/json" } }
|
||||||
|
|
||||||
it "returns HTTP 200 OK" do
|
specify "with json-encoded query string inside body" do
|
||||||
expect(response.code).to eq(200)
|
post '/graphql', { query: "{ proposal(id: #{proposal.id}) { title } }" }.to_json, json_headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(JSON.parse(response.body)['data']['proposal']['title']).to eq(proposal.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "doesn't return any data" do
|
specify "with raw query string inside body" do
|
||||||
expect(response_body['data']).to be_nil
|
graphql_headers = { "CONTENT_TYPE" => "application/graphql" }
|
||||||
|
post '/graphql', "{ proposal(id: #{proposal.id}) { title } }", graphql_headers
|
||||||
|
expect(response).to have_http_status(:ok)
|
||||||
|
expect(JSON.parse(response.body)['data']['proposal']['title']).to eq(proposal.title)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns error inside body" do
|
specify "with malformed query string" do
|
||||||
expect(response_body['errors']).to be_present
|
post '/graphql', { query: "Malformed query string" }.to_json, json_headers
|
||||||
end
|
expect(response).to have_http_status(:bad_request)
|
||||||
|
expect(JSON.parse(response.body)['message']).to eq('Query string is not valid JSON')
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when query string is not valid" do
|
it "without query string" do
|
||||||
let(:query_string) { "invalid" }
|
post '/graphql', json_headers
|
||||||
|
expect(response).to have_http_status(:bad_request)
|
||||||
it "returns HTTP 400 Bad Request" do
|
expect(JSON.parse(response.body)['message']).to eq('Query string not present')
|
||||||
expect(response.code).to eq(400)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "when query string is missing" do
|
|
||||||
let(:query_string) { nil }
|
|
||||||
|
|
||||||
it "returns HTTP 400 Bad Request" do
|
|
||||||
expect(response.code).to eq(400)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
context "when body is missing" do
|
|
||||||
let(:body) { nil }
|
|
||||||
|
|
||||||
it "returns HTTP 400 Bad Request" do
|
|
||||||
expect(response.code).to eq(400)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
=end
|
|
||||||
|
|||||||
Reference in New Issue
Block a user