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