Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2020 - Manifold Systems LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package manifold.graphql.rt.api.request;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import manifold.ext.rt.RuntimeMethods;
import manifold.rt.api.Bindings;
import manifold.json.rt.api.Endpoint;
import manifold.json.rt.api.Requester;
/**
* Based on: "How to make GraphQL HTTP request using cUrl"
*
* Based on the GET/POST and the Content-Type header, it expects the input params differently.
* This behaviour was ported from express-graphql.
*
* So given the following operation:
*
* mutation M {
* newTodo: createTodo(text: "This is a mutation example") {
* text
* done
* }
* }
*
*
* using GET
* $ curl -g -GET 'http://localhost:8080/graphql?query=mutation+M{newTodo:createTodo(text:"This+is+a+mutation+example"){text+done}}'
* using POST + Content-Type: application/graphql
* $ curl -XPOST http://localhost:8080/graphql -H 'Content-Type: application/graphql' -d 'mutation M { newTodo: createTodo(text: "This is a mutation example") { text done } }'
* using POST + Content-Type: application/json
* $ curl -XPOST http://localhost:8080/graphql -H 'Content-Type: application/json' -d '{"query": "mutation M { newTodo: createTodo(text: \"This is a mutation example\") { text done } }"}'
*
* @param
*/
public class Executor
{
private final GqlRequestBody _reqArgs;
private final Requester _requester;
public Executor( String url, String operation, String query, Bindings variables, Class resultType )
{
_requester = new Requester<>( url, result -> coerce( (Class) resultType, result ) );
_requester.withHeader( "Content-Type", "application/json" );
_reqArgs = GqlRequestBody.create( query, variables );
}
public Executor( Endpoint endpoint, String operation, String query, Bindings variables, Class resultType )
{
_requester = new Requester<>( endpoint, result -> coerce( resultType, result ) );
_requester.withHeader( "Content-Type", "application/json" );
_reqArgs = GqlRequestBody.create( query, variables );
}
public Executor( Supplier> requester, String operation, String query, Bindings variables, Class resultType )
{
_requester = requester.get();
_requester.withCoercer( result -> coerce( resultType, result ) );
_requester.withHeader( "Content-Type", "application/json" );
_reqArgs = GqlRequestBody.create( query, variables );
}
private Object coerce( Class resultType, Object result )
{
Bindings response = (Bindings) result;
Object customResult = handleRawResponse( response );
if( customResult != null )
{
// a custom result bindings
return customResult;
}
handleErrors( response );
return RuntimeMethods.coerce( response.get( "data" ), resultType );
}
/**
* Access the full GraphQL request body, which includes {@code query} and {@code variables} bindings.
*
* @return the GraphQL request body consisting of bindings for both the query and variables.
*/
public GqlRequestBody getRequestBody()
{
return _reqArgs;
}
/**
* Access an unmodifiable view of the GraphQL request headers.
*/
public Map getHeaders()
{
return _requester.getHeaders();
}
/**
* Access the GraphQL request endpoint.
*/
public Endpoint getEndpoint()
{
return _requester.getEndpoint();
}
/**
* Access the GraphQL request format.
*/
public Requester.Format getFormat()
{
return _requester.getFormat();
}
/**
* Access the GraphqL request timeout.
*/
public int getTimeout()
{
return _requester.getTimeout();
}
/**
* Set an HTTP request header {@code name : value} pair
* See HTTP header fields
*/
public Executor withHeader( String name, String value )
{
_requester.withHeader( name, value );
return this;
}
/**
* Add a {@code name=value} parameter to the request URL.
*/
public Executor withParam( String name, String value )
{
_requester.withParam( name, value );
return this;
}
/**
* Set the Basic Authorization header using the provided {@code username} and {@code password}
*/
@SuppressWarnings("unused")
public Executor withBasicAuthorization( String username, String password )
{
_requester.withBasicAuthorization( username, password );
return this;
}
/**
* Set the Bearer Authorization header using the provided {@code accessToken}.
* For instance, if using OAuth, {@code accessToken} is the token response from:
*
*/
@SuppressWarnings("unused")
public Executor withBearerAuthorization( String accessToken )
{
return withAuthorization( "Bearer", accessToken );
}
@SuppressWarnings("unused")
public Executor withAuthorization( String tokenType, String accessToken )
{
return withHeader( "Authorization", tokenType + " " + accessToken );
}
/**
* The connection timeout setting in milliseconds. If the timeout expires before the connection can be established, a
* {@link java.net.SocketTimeoutException) is thrown. A value of zero is interpreted as an infinite timeout, this is
* the default setting.
*/
public Executor withTimeout( int timeout )
{
_requester.withTimeout( timeout );
return this;
}
/**
* @param handler An optional handler for processing the raw response as an arbitrary Bindings instance. The handler
* may return a custom bindings object which overrides the default, type-safe result instance. In any
* case, the handler can process the response in any way. Note, modifications made to the response
* persist and, therefore, affect default internal data and error processing.
* @return this {@code Executor} instance.
*/
public Executor withRawResponseHandler( Function handler )
{
_requester.withRawResponseHandler( handler );
return this;
}
public Function getRawResponseHandler()
{
return _requester.getRawResponseHandler();
}
/**
* Make an HTTP POST request to {@code url}. The {@code payload}, if non-null, is sent as JSON encoded
* text in the request's message body.
*
* @return A JSON value parsed from the {@code format} specified encoded response (primitive/boxed type, String, List of JSON values, or Bindings of String/JSON value)
*
* @throws GqlRequestException If the response contains errors, wraps them in a list of {@link GqlError} and throws
*/
public T post() throws GqlRequestException
{
return _requester.postOne( _reqArgs.getBindings() );
}
/**
* Make an HTTP POST request to {@code url}. The {@code payload}, if non-null, is sent as JSON encoded
* text in the request's message body.
*
* @param format The expected format of the response. One of: {@code Json}, {@code Yaml}, or {@code Plain}
*
* @return A JSON value parsed from the {@code format} specified encoded response (primitive/boxed type, String, List of JSON values, or Bindings of String/JSON value)
*
* @throws GqlRequestException If the response contains errors, wraps them in a list of {@link GqlError} and throws
*/
public T post( Requester.Format format ) throws GqlRequestException
{
return _requester.postOne( "", _reqArgs.getBindings(), format );
}
/**
* Make an HTTP GET request to {@code url}. The {@code payload}, if non-null, is sent as JSON encoded
* text in the request's message body.
*
* @return A JSON value parsed from the {@code format} specified encoded response (primitive/boxed type, String, List of JSON values, or Bindings of String/JSON value)
*
* @throws GqlRequestException If the response contains errors, wraps them in a list of {@link GqlError} and throws
*/
public T get() throws GqlRequestException
{
return (T)_requester.getOne( _reqArgs.getBindings() );
}
/**
* Make an HTTP GET request to {@code url}. The {@code payload}, if non-null, is sent as JSON encoded
* text in the request's message body.
*
* @param format The expected format of the response. One of: {@code Json}, {@code Yaml}, or {@code Plain}
*
* @return A JSON value parsed from the {@code format} specified encoded response (primitive/boxed type, String, List of JSON values, or Bindings of String/JSON value)
*
* @throws GqlRequestException If the response contains errors, wraps them in a list of {@link GqlError} and throws
*/
public T get( Requester.Format format ) throws GqlRequestException
{
return (T)_requester.getOne( "", _reqArgs.getBindings(), format );
}
private Object handleRawResponse( Bindings response )
{
Function handler = _requester.getRawResponseHandler();
if( handler != null )
{
return handler.apply( response );
}
return null;
}
private void handleErrors( Bindings response )
{
//noinspection unchecked
List errors = (List)response.get( "errors" );
if( errors != null && !errors.isEmpty() )
{
throw new GqlRequestException( response );
}
}
}