Consumer and Producer

包路径: github.com/caicloud/nirvana/service

在 HTTP 请求中,Content-Type 说明了请求和响应中的数据类型。为了根据 Content-Type 自动处理数据转换,Nirvana 提供了 Consumer 和 Producer 接口。其中 Consumer 用于将请求体中的数据转换为业务函数需要的类型,而 Producer 则负责将业务函数的返回结果写入到响应体中。

Nirvana 默认提供的 Consumers:

Content-Type 描述
空的 Content-Type 通常对应于 GET 之类的请求,因此不能转换为任何数据类型。
text/plain 只能生成 string 和 []byte 类型
application/json 如果接收类型是 string 和 []byte,则直接将数据转换为这两个类型。对于其他类型,使用 json.Unmarshal 进行解析。
application/xml 如果接收类型是 string 和 []byte,则直接将数据转换为这两个类型。对于其他类型,使用 xml.Unmarshal 进行解析。
application/octet-stream 只能生成 string 和 []byte 类型
application/x-www-form-urlencoded 只能生成 string 和 []byte 类型,这种类型的请求通常会被 Parse 并成为 Form 类型,因此一般不转换为具体类型。
multipart/form-data 只能生成 string 和 []byte 类型,这种类型的请求通常会被 Parse 并成为 Form 或 File 类型,因此一般不转换为具体类型。

Nirvana 默认提供的 Producers:

Content-Type 描述
空的 Content-Type 通常对应于 204 之类的响应,没有响应体,不需要写入。
text/plain 如果类型符合 io.Reader 接口或者是 string 和 []byte,则直接将数据写入到响应。
application/json 如果类型符合 io.Reader 接口或者是 string 和 []byte,则直接将数据写入到响应。如果是其他类型,则使用 json.Marshal 将数据写入到响应。
application/xml 如果类型符合 io.Reader 接口或者是 string 和 []byte,则直接将数据写入到响应。如果是其他类型,则使用 xml.Marshal 将数据写入到响应。
application/octet-stream 如果类型符合 io.Reader 接口或者是 string 和 []byte,则直接将数据写入到响应。

添加 Consumer 和 Producer

在业务的实际场景中,默认提供的 Consumers 和 Producers 可能不能满足实际使用需求。因此 Nirvana 的 service 包提供了相应的工具用于注册用户自己的 Consumer 和 Producer。

注册 Consumer

Consumer 需要实现接口:

// Consumer handles specifically typed data from a reader and unmarshals it into an object.
type Consumer interface {
    // ContentType returns a HTTP MIME type.
    ContentType() string
    // Consume unmarshals data from r into v.
    Consume(r io.Reader, v interface{}) error
}

实现了这个接口后,通过 service 的注册方法即可注册 Consumer:

if err := service.RegisterConsumer(consumer); err != nil {
    log.Fatal(err)
}

在接收到 Content-Type 与 consumer 一致的请求,并且业务函数需要从请求中取得请求体的时候,就会调用这个 Consumer 去读取数据并进行类型转换。

注册 Producer

Producer 需要实现接口:

// Producer marshals an object to specifically typed data and write it into a writer.
type Producer interface {
    // ContentType returns a HTTP MIME type.
    ContentType() string
    // Produce marshals v to data and write to w.
    Produce(w io.Writer, v interface{}) error
}

实现了这个接口后,通过 service 的注册方法即可注册 Producer:

if err := service.RegisterProducer(producer); err != nil {
    log.Fatal(err)
}

在需要生成 Conetent-Type 于 producer 一致的响应,并且业务函数需要返回数据的时候,就会调用这个 producer 将类型转换为字节数据写入到响应体中。

快速生成 Consumer 和 Producer 的工具

通常情况下,我们需要快速添加一些 Consumers 和 Producers,并且他们的行为和 application/octet-stream 一致的时候,那么可以直接使用工具方法:

serializer := NewSimpleSerializer(contentType)

if err := service.RegisterConsumer(serializer); err != nil {
    log.Fatal(err)
}

if err := service.RegisterProducer(serializer); err != nil {
    log.Fatal(err)
}

results matching ""

    No results matching ""