forked from ThreeMammals/Ocelot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* ThreeMammals#298 initial hacking around better aggregation * ThreeMammals#298 bit more hacking around * ThreeMammals#298 abstraction over httpresponsemessage * ThreeMammals#298 tidying up * ThreeMammals#298 docs * ThreeMammals#298 missed this * ThreeMammals#306 example of how to do GraphQL
- Loading branch information
1 parent
a15f75d
commit b46ef19
Showing
7 changed files
with
270 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
GraphQL | ||
======= | ||
|
||
OK you got me Ocelot doesn't directly support GraphQL but so many people have asked about it I wanted to show how easy it is to integrate | ||
the `graphql-dotnet <https://github.com/graphql-dotnet/graphql-dotnet>`_ library. | ||
|
||
|
||
Please see the sample project `OcelotGraphQL <https://github.com/ThreeMammals/Ocelot/tree/develop/samples/OcelotGraphQL>`_. | ||
Using a combination of the graphql-dotnet project and Ocelot's DelegatingHandler features this is pretty easy to do. | ||
However I do not intend to integrate more closely with GraphQL at the moment. Check out the samples readme and that should give | ||
you enough instruction on how to do this! | ||
|
||
Good luck and have fun :> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
<Project Sdk="Microsoft.NET.Sdk.Web"> | ||
<PropertyGroup> | ||
<TargetFramework>netcoreapp2.0</TargetFramework> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<None Update="configuration.json;appsettings.json"> | ||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<Folder Include="wwwroot\"/> | ||
</ItemGroup> | ||
<ItemGroup> | ||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.6"/> | ||
<PackageReference Include="Ocelot" Version="5.5.1"/> | ||
<PackageReference Include="GraphQL" Version="2.0.0-alpha-870"/> | ||
</ItemGroup> | ||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using Microsoft.AspNetCore; | ||
using Microsoft.AspNetCore.Hosting; | ||
using Microsoft.Extensions.Configuration; | ||
using Microsoft.Extensions.Logging; | ||
using Ocelot.Middleware; | ||
using Ocelot.DependencyInjection; | ||
using GraphQL.Types; | ||
using GraphQL; | ||
using Ocelot.Requester; | ||
using Ocelot.Responses; | ||
using System.Net.Http; | ||
using System.Net; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using System.Threading; | ||
|
||
namespace OcelotGraphQL | ||
{ | ||
public class Hero | ||
{ | ||
public int Id { get; set; } | ||
public string Name { get; set; } | ||
} | ||
|
||
public class Query | ||
{ | ||
private List<Hero> _heroes = new List<Hero> | ||
{ | ||
new Hero { Id = 1, Name = "R2-D2" }, | ||
new Hero { Id = 2, Name = "Batman" }, | ||
new Hero { Id = 3, Name = "Wonder Woman" }, | ||
new Hero { Id = 4, Name = "Tom Pallister" } | ||
}; | ||
|
||
[GraphQLMetadata("hero")] | ||
public Hero GetHero(int id) | ||
{ | ||
return _heroes.FirstOrDefault(x => x.Id == id); | ||
} | ||
} | ||
|
||
public class GraphQlDelegatingHandler : DelegatingHandler | ||
{ | ||
private readonly ISchema _schema; | ||
|
||
public GraphQlDelegatingHandler(ISchema schema) | ||
{ | ||
_schema = schema; | ||
} | ||
|
||
protected async override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) | ||
{ | ||
//try get query from body, could check http method :) | ||
var query = await request.Content.ReadAsStringAsync(); | ||
|
||
//if not body try query string, dont hack like this in real world.. | ||
if(query.Length == 0) | ||
{ | ||
var decoded = WebUtility.UrlDecode(request.RequestUri.Query); | ||
query = decoded.Replace("?query=", ""); | ||
} | ||
|
||
var result = _schema.Execute(_ => | ||
{ | ||
_.Query = query; | ||
}); | ||
|
||
//maybe check for errors and headers etc in real world? | ||
var response = new HttpResponseMessage(HttpStatusCode.OK) | ||
{ | ||
Content = new StringContent(result) | ||
}; | ||
|
||
//ocelot will treat this like any other http request... | ||
return response; | ||
} | ||
} | ||
|
||
public class Program | ||
{ | ||
public static void Main(string[] args) | ||
{ | ||
var schema = Schema.For(@" | ||
type Hero { | ||
id: Int | ||
name: String | ||
} | ||
type Query { | ||
hero(id: Int): Hero | ||
} | ||
", _ => { | ||
_.Types.Include<Query>(); | ||
}); | ||
|
||
new WebHostBuilder() | ||
.UseKestrel() | ||
.UseContentRoot(Directory.GetCurrentDirectory()) | ||
.ConfigureAppConfiguration((hostingContext, config) => | ||
{ | ||
config | ||
.SetBasePath(hostingContext.HostingEnvironment.ContentRootPath) | ||
.AddJsonFile("appsettings.json", true, true) | ||
.AddJsonFile($"appsettings.{hostingContext.HostingEnvironment.EnvironmentName}.json", true, true) | ||
.AddJsonFile("configuration.json") | ||
.AddEnvironmentVariables(); | ||
}) | ||
.ConfigureServices(s => { | ||
s.AddSingleton<ISchema>(schema); | ||
s.AddOcelot() | ||
.AddSingletonDelegatingHandler<GraphQlDelegatingHandler>(); | ||
}) | ||
.ConfigureLogging((hostingContext, logging) => | ||
{ | ||
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging")); | ||
logging.AddConsole(); | ||
}) | ||
.UseIISIntegration() | ||
.Configure(app => | ||
{ | ||
app.UseOcelot().Wait(); | ||
}) | ||
.Build() | ||
.Run(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
# Ocelot using GraphQL example | ||
|
||
Loads of people keep asking me if Ocelot will every support GraphQL, in my mind Ocelot and GraphQL are two different things that can work together. | ||
I would not try and implement GraphQL in Ocelot instead I would either have Ocelot in front of GraphQL to handle things like authorisation / authentication or I would | ||
bring in the awesome [graphql-dotnet](https://github.com/graphql-dotnet/graphql-dotnet) library and use it in a [DelegatingHandler](http://ocelot.readthedocs.io/en/latest/features/delegatinghandlers.html). This way you could have Ocelot and GraphQL without the extra hop to GraphQL. This same is an example of how to do that. | ||
|
||
## Example | ||
|
||
If you run this project with | ||
|
||
$ dotnet run | ||
|
||
Use postman or something to make the following requests and you can see Ocelot and GraphQL in action together... | ||
|
||
GET http://localhost:5000/graphql?query={ hero(id: 4) { id name } } | ||
|
||
RESPONSE | ||
```json | ||
{ | ||
"data": { | ||
"hero": { | ||
"id": 4, | ||
"name": "Tom Pallister" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
POST http://localhost:5000/graphql | ||
|
||
BODY | ||
```json | ||
{ hero(id: 4) { id name } } | ||
``` | ||
|
||
RESPONSE | ||
```json | ||
{ | ||
"data": { | ||
"hero": { | ||
"id": 4, | ||
"name": "Tom Pallister" | ||
} | ||
} | ||
} | ||
``` | ||
|
||
## Notes | ||
|
||
Please note this project never goes out to another service, it just gets the data for GraphQL in memory. You would need to add the details of your GraphQL server in configuration.json e.g. | ||
|
||
```json | ||
{ | ||
"ReRoutes": [ | ||
{ | ||
"DownstreamPathTemplate": "/graphql", | ||
"DownstreamScheme": "http", | ||
"DownstreamHostAndPorts": [ | ||
{ | ||
"Host": "yourgraphqlhost.com", | ||
"Port": 80 | ||
} | ||
], | ||
"UpstreamPathTemplate": "/graphql", | ||
"DelegatingHandlers": [ | ||
"GraphQlDelegatingHandler" | ||
] | ||
} | ||
] | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"ReRoutes": [ | ||
{ | ||
"DownstreamPathTemplate": "/", | ||
"DownstreamScheme": "http", | ||
"DownstreamHostAndPorts": [ | ||
{ | ||
"Host": "jsonplaceholder.typicode.com", | ||
"Port": 80 | ||
} | ||
], | ||
"UpstreamPathTemplate": "/graphql", | ||
"DelegatingHandlers": [ | ||
"GraphQlDelegatingHandler" | ||
] | ||
} | ||
] | ||
} | ||
|