github.com/operandinc/gqlgen@v0.16.1/docs/content/recipes/federation.md (about) 1 --- 2 title: "Using Apollo federation gqlgen" 3 description: How federate many services into a single graph using Apollo 4 linkTitle: Apollo Federation 5 menu: { main: { parent: "recipes" } } 6 --- 7 8 In this quick guide we are going to implement the example [Apollo Federation](https://www.apollographql.com/docs/apollo-server/federation/introduction/) 9 server in gqlgen. You can find the finished result in the [examples directory](https://github.com/operandinc/gqlgen/tree/master/_examples/federation). 10 11 ## Enable federation 12 13 Uncomment federation configuration in your `gqlgen.yml` 14 15 ```yml 16 # Uncomment to enable federation 17 federation: 18 filename: graph/generated/federation.go 19 package: generated 20 ``` 21 22 ## Create the federated servers 23 24 For each server to be federated we will create a new gqlgen project. 25 26 ```bash 27 go run github.com/operandinc/gqlgen 28 ``` 29 30 Update the schema to reflect the federated example 31 32 ```graphql 33 type Review { 34 body: String 35 author: User @provides(fields: "username") 36 product: Product 37 } 38 39 extend type User @key(fields: "id") { 40 id: ID! @external 41 reviews: [Review] 42 } 43 44 extend type Product @key(fields: "upc") { 45 upc: String! @external 46 reviews: [Review] 47 } 48 ``` 49 50 and regenerate 51 52 ```bash 53 go run github.com/operandinc/gqlgen 54 ``` 55 56 then implement the resolvers 57 58 ```go 59 // These two methods are required for gqlgen to resolve the internal id-only wrapper structs. 60 // This boilerplate might be removed in a future version of gqlgen that can no-op id only nodes. 61 func (r *entityResolver) FindProductByUpc(ctx context.Context, upc string) (*model.Product, error) { 62 return &model.Product{ 63 Upc: upc, 64 }, nil 65 } 66 67 func (r *entityResolver) FindUserByID(ctx context.Context, id string) (*model.User, error) { 68 return &model.User{ 69 ID: id, 70 }, nil 71 } 72 73 // Here we implement the stitched part of this service, returning reviews for a product. Of course normally you would 74 // go back to the database, but we are just making some data up here. 75 func (r *productResolver) Reviews(ctx context.Context, obj *model.Product) ([]*model.Review, error) { 76 switch obj.Upc { 77 case "top-1": 78 return []*model.Review{{ 79 Body: "A highly effective form of birth control.", 80 }}, nil 81 82 case "top-2": 83 return []*model.Review{{ 84 Body: "Fedoras are one of the most fashionable hats around and can look great with a variety of outfits.", 85 }}, nil 86 87 case "top-3": 88 return []*model.Review{{ 89 Body: "This is the last straw. Hat you will wear. 11/10", 90 }}, nil 91 92 } 93 return nil, nil 94 } 95 96 func (r *userResolver) Reviews(ctx context.Context, obj *model.User) ([]*model.Review, error) { 97 if obj.ID == "1234" { 98 return []*model.Review{{ 99 Body: "Has an odd fascination with hats.", 100 }}, nil 101 } 102 return nil, nil 103 } 104 ``` 105 106 > Note 107 > 108 > Repeat this step for each of the services in the apollo doc (accounts, products, reviews) 109 110 ## Create the federation gateway 111 112 ```bash 113 npm install --save @apollo/gateway apollo-server graphql 114 ``` 115 116 ```typescript 117 const { ApolloServer } = require("apollo-server"); 118 const { ApolloGateway } = require("@apollo/gateway"); 119 120 const gateway = new ApolloGateway({ 121 serviceList: [ 122 { name: "accounts", url: "http://localhost:4001/query" }, 123 { name: "products", url: "http://localhost:4002/query" }, 124 { name: "reviews", url: "http://localhost:4003/query" }, 125 ], 126 }); 127 128 const server = new ApolloServer({ 129 gateway, 130 131 subscriptions: false, 132 }); 133 134 server.listen().then(({ url }) => { 135 console.log(`🚀 Server ready at ${url}`); 136 }); 137 ``` 138 139 ## Start all the services 140 141 In separate terminals: 142 143 ```bash 144 go run accounts/server.go 145 go run products/server.go 146 go run reviews/server.go 147 node gateway/index.js 148 ``` 149 150 ## Query the federated gateway 151 152 The examples from the apollo doc should all work, eg 153 154 ```graphql 155 query { 156 me { 157 username 158 reviews { 159 body 160 product { 161 name 162 upc 163 } 164 } 165 } 166 } 167 ``` 168 169 should return 170 171 ```json 172 { 173 "data": { 174 "me": { 175 "username": "Me", 176 "reviews": [ 177 { 178 "body": "A highly effective form of birth control.", 179 "product": { 180 "name": "Trilby", 181 "upc": "top-1" 182 } 183 }, 184 { 185 "body": "Fedoras are one of the most fashionable hats around and can look great with a variety of outfits.", 186 "product": { 187 "name": "Trilby", 188 "upc": "top-1" 189 } 190 } 191 ] 192 } 193 } 194 } 195 ```