Server
Tanka provides server components in Tanka.GraphQL.server
NuGet
package. It can be used to get up and running or if more control is
required then you can implement your own server.
See also
Tanka Server provides two server components which can be used together or separately.
- SignalR - server built on top of SignalR Core
- GraphQL-WS - custom WebSockets server supporting
graphql-ws
messages
Following steps are required to get the server running with your schema.
- Build schema
- Configure schema options
- Configure server
- HTTP API
1. Build schema
First step for either server is to configure your schema options for execution. Schema should be built only once and cached as singleton.
private async Task<ISchema> Create()
{
// Do some async work to build the schema. For example
// load SDL from file
await Task.Delay(0);
// Build simple schema from SDL string
var builder = new SchemaBuilder()
.Sdl(
@"
type Query {
firstName: String!
lastName: String!
}
schema {
query: Query
}
");
// Bind resolvers and build
return SchemaTools
.MakeExecutableSchemaWithIntrospection(
builder,
new ObjectTypeMap
{
["Query"] = new FieldResolversMap
{
{"firstName", context => ResolveSync.As("Tanka")},
{"lastName", UseService()}
}
});
}
2. Configure
Next needed step is to configure server options. These options tell the executor where to get the schema and also allows configuring the validation rules for the execution. By default all validation rules from the GraphQL specification are included.
private static void AddTanka(IServiceCollection services)
{
// Configure schema options
services.AddTankaGraphQL()
.ConfigureSchema<SchemaCache>(async cache => await cache.GetOrAdd());
}
3. Configure server
Server components require calling their Add*
methods to add required
services and configure their options. Depending on the server also
middleware needs to be configured using the paired Use*
methods.
Configure SignalR server
private static void AddSignalRServer(IServiceCollection services)
{
// Configure Tanka server
services.AddSignalR()
.AddTankaGraphQL();
}
Use SignalR server
private static void UseSignalRServer(IApplicationBuilder app)
{
// add SignalR
app.UseEndpoints(routes => { routes.MapTankaGraphQLSignalR("/graphql/hub"); });
}
Configure GraphQL WS server
private void AddWebSocketsServer(IServiceCollection services)
{
// Configure websockets
services.AddWebSockets(options => { options.AllowedOrigins.Add("https://localhost:5000"); });
// Add Tanka GraphQL-WS server
services.AddTankaGraphQL()
.ConfigureWebSockets();
}
Use GraphQL WS Server
private void UseWebSocketsServer(IApplicationBuilder app)
{
// Add Websockets middleware
app.UseWebSockets();
// Add Tanka GraphQL-WS middleware
app.UseEndpoints(endpoints => endpoints.MapTankaGraphQLWebSockets("/graphql/ws"));
}
4. HTTP API
Tanka Server does not provide out of the box "server" for basic HTTP/JSON API as that can be easily implemented.
Here's an example of ASP.NET Core MVC Controller taken from the
Tanka.GraphQL.Samples.Chat.Web
project included in the solution.
IQueryStreamService
is registered by the AddTankaGraphQL
and is also used by the SignalR and GraphQL-WS based servers to
execute the queries.
[]
[Route("api/graphql")]
public class QueryController : Controller
{
private readonly IQueryStreamService _queryStreamService;
public QueryController(IQueryStreamService queryStreamService)
{
_queryStreamService = queryStreamService;
}
[HttpPost]
public async Task<IActionResult> Post([FromBody] OperationRequest request)
{
var stream = await _queryStreamService.QueryAsync(new Query
{
Document = ParseDocument(request.Query),
Variables = request.Variables,
OperationName = request.OperationName
}, Request.HttpContext.RequestAborted);
var result = await stream.Reader.ReadAsync();
return Ok(result);
}
}