3 Content negotiation
Gerasimos (Makis) Maropoulos edited this page 2020-06-18 09:47:07 +03:00

Sometimes a server application needs to serve different representations of a resource at the same URI. Of course this can be done by hand, manually checking the Accept request header and push the requested form of the content. However, as your app manages more resources and different kind of representations this can be very painful, as you may need to check for Accept-Charset, Accept-Encoding, put some server-side priorities, handle the errors correctly and e.t.c.

There are some web frameworks in Go already struggle to implement a feature like this but they don't do it correctly:

  • they don't handle accept-charset at all
  • they don't handle accept-encoding at all
  • they don't send error status code (406 not acceptable) as RFC proposes and more...

But, fortunately for us, Iris always follows the best practises and the Web standards.

Based on:

Implemented on:


Example

type testdata struct {
	Name string `json:"name" xml:"Name"`
	Age  int    `json:"age" xml:"Age"`
}

Render a resource with "gzip" encoding algorithm as application/json or text/xml or application/xml

  • when client's accept header contains one of them
  • or JSON (the first declared) if accept is empty,
  • and when client's accept-encoding header contains "gzip" or it's empty.
app.Get("/resource", func(ctx iris.Context) {
	data := testdata{
		Name: "test name",
		Age:  26,
	}

        ctx.Negotiation().JSON().XML().EncodingGzip()

	_, err := ctx.Negotiate(data)
	if err != nil {
		ctx.Writef("%v", err)
	}
})

OR define them in a middleware and call Negotiate with nil in the final handler.

ctx.Negotiation().JSON(data).XML(data).Any("content for */*")
ctx.Negotiate(nil)
app.Get("/resource2", func(ctx iris.Context) {
	jsonAndXML := testdata{
		Name: "test name",
		Age:  26,
	}

	ctx.Negotiation().
		JSON(jsonAndXML).
		XML(jsonAndXML).
		HTML("<h1>Test Name</h1><h2>Age 26</h2>")

	ctx.Negotiate(nil)
})

Read the full example.

Documentation

The Context.Negotiation method creates once and returns the negotiation builder to build server-side available prioritized content for specific content type(s), charset(s) and encoding algorithm(s).

Context.Negotiation() *context.NegotiationBuilder

The Context.Negotiate method used for serving different representations of a resource at the same URI. It returns context.ErrContentNotSupported when not matched mime type(s).

Context.Negotiate(v interface{}) (int, error)