1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Choosing a response representation from the client's `Accept` header.
//!
//! ```text
//! cargo run -p kynos --example negotiation
//! ```
//!
//! Three things are worth noticing:
//!
//! * **`Accept` is never a parameter.** The specification says a parameter
//! definition for that field shall be ignored, so declaring one would put a
//! claim in the description that no consumer will honour — and
//! `#[derive(HeaderParams)]` refuses the name for exactly that reason. What
//! describes the negotiation is the operation's `content` map, which the
//! representation tuple contributes. `Accept<T>`'s own `Describe` adds only
//! the rejections, the 406 among them.
//! * **The offer is a type, so the description cannot miss one.** `Negotiated<T>`
//! carries the same tuple `Accept<T>` was parameterised by, so a
//! representation the handler can return is a representation the document
//! lists. There is no way to add an arm at run time.
//! * **`Representation` is sealed, and still nameable.** The offerable set is
//! exactly the codecs Kynos can describe. Both traits are public — they
//! appear in `Accept::respond_with`'s bound, and a bound nobody can write down is
//! a bound nobody can satisfy deliberately — but a private supertrait is what
//! stops an outside implementation, rather than the module being shut.
//!
//! * **Only the chosen representation is built.** `respond_with` takes closures
//! rather than values, so the PDF below is rendered for a client that asked
//! for a PDF and for nobody else. Handing `respond` three finished values
//! would mean rendering all three and discarding two — work no request asked
//! for, and invisible until one of the alternatives is expensive.
//!
//! Tuple order is meaningful: it breaks the tie when a client's `Accept` ranks
//! two alternatives equally. Put the representation you would rather serve
//! first.
use Ipv4Addr;
use ;
use ;
/// A monthly report.
/// What `/reports/{month}` captures.
/// The three ways this service will serve a report.
///
/// A type alias rather than three spellings, so the extractor, the return type
/// and the offer cannot drift apart — they are the same tuple by construction.
/// JSON first: it is what an integration wants, and it wins a tie.
type ReportFormats = ;
/// Renders a report as a PDF.
///
/// Stands in for something genuinely expensive — a layout engine, a font
/// cache, a subprocess. It exists so the example is honest about what eager
/// negotiation would have cost: this would run on every request, including the
/// ones that asked for JSON.
/// Serves a report as JSON, plain text or a PDF.
///
/// Three arms, one `content` map, and no branch in this function chooses a
/// media type: `respond_with` scores the client's ranked preferences against
/// the tuple's media types and returns the 406 when nothing matches.
///
/// The closures all borrow `report` rather than one of them owning it, which is
/// why the source is passed separately: three arms cannot each take the same
/// value, and a captured one would put that problem in every handler.
async
/// A program generic over what it offers.
///
/// This is why the traits are public rather than merely sealed. The bound is
/// writable, so a helper can be generic over an offer — and it is still closed,
/// so the offer can only be codecs the description knows.
/// The same, for one alternative rather than a tuple.
async