我正在使用API后端从头开始构建GraphQL服务器,以取代REST API服务器。当前,现有API服务器中的一些请求(主要是创建/更新请求)将是GraphQL中的突变,其中包括客户端使用的请求ID。此请求ID是有关请求本身的元数据,而不是域资源的一部分。
我的问题是如何在GraphQL查询和变异中建模/包含请求元数据?到目前为止,我唯一的解决方案是创建一个请求类型,其他类型也可以将其作为字段包括在内,以便请求数据可以包含在变异返回类型中。但是我不喜欢这种方法,因为它将请求数据混合到我的域类型中,这在很大程度上与GraphQL的精神背道而驰。是否有通过``任意''的公认方法,例如GraphQL中查询或突变的响应中获取非域类型数据?
示例-我想避免的事情:
type UserType {
id: ID
name: String
request: RequestType // mixing request data in with domain type of User
}
type RequestType {
id: ID
}
对于对此问题感兴趣的其他人,根据此处的响应,我认为GraphQL extensions
键是在GraphQL响应中添加任意数据而不使数据成为数据Graph的一部分的好选择。在Express-GraphQL中,有关在响应中添加扩展键的文档,请参见:https://github.com/graphql/express-graphql#providing-extensions。这里的扩展概述:https://marmelab.com/blog/2017/09/06/dive-into-graphql-part-iii-building-a-graphql-server-with-nodejs.html#server-logging
也就是说,如果请求元数据从概念上讲是域数据的一部分,则遵循Kashif的以下建议,即创建嵌入域类型的ResponseTypes可能是正确的方法。
答案 0 :(得分:0)
这种元元素通常随每个请求传递到HEADERS中。然后,您可以根据需要在GraphQL服务器中处理这些问题
例如。
//Request Headers
...
X-Request-Id: <Your_Request_Id>
...
标头可以双向工作,因此在客户端上使用标头也不会有任何问题。随时根据需要将它们拉出响应。
但是,如果您确实希望您的突变响应中包含requestId,那么这就是您域的一部分。拥有自定义响应类型没有什么问题,许多现有的GraphQL api确实具有自定义响应类型,例如LoginResponse
,RegisterResponse
,它会包裹您的域对象,但在{{1 }}字段
答案 1 :(得分:0)
由于GraphQL被设计为与协议无关,因此您应该使用所选协议的元数据模式。如果使用的是HTTP,则应传递标头。如果您使用的是WS / STOMP / MQTT / AMQP,则可以在每个帧中包含元数据。
或者GraphQL有一个extensions protocol。您可以在扩展对象中的响应中添加import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Map<String, String> textMessageMap = {'message': 'Home'};
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'${textMessageMap != null ? textMessageMap['message'] : 'map is null'}',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: new FloatingActionButton(
onPressed: () {
_launchSecondScreen();
},
child: new Icon(Icons.add),
),
);
}
_launchSecondScreen() async {
final value = await Navigator.push(
context,
MaterialPageRoute<Map<String, String>>(
builder: (BuildContext _) => SecondScreen()));
setState(() {
textMessageMap = value;
});
}
}
class SecondScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Second Screen"),
),
body: Center(
child: RaisedButton(
onPressed: () {
// Navigate back to the first screen by popping the current route
// off the stack. The text 'Second Screen' will replace 'Home'.
// If you hit the scaffold's back button, the return value will be
// null instead.
final map = {'message': 'Second Screen'};
Navigator.pop(context, map);
},
child: Text('Go back!'),
),
),
);
}
}
。 Apollo使用扩展进行缓存,遥测等。
我们已经在生产中使用GraphQL大约一年了,我们犯了将元数据添加到GraphQL中的错误,并且变得难以管理。不要失去正在使用的协议功能的好处。