An OCaml webserver, but the allocating version (vs httpz which doesnt)
1(** Range request parsing and Content-Range response writing per RFC 7233. *)
2
3(** {1 Types} *)
4
5(** A single byte range specification.
6 Use query functions ([is_range], [is_suffix], [is_open]) to inspect the kind. *)
7type byte_range =
8 { kind : int
9 ; start : int64
10 ; end_ : int64
11 }
12
13(** Maximum number of ranges that can be parsed. *)
14val max_ranges : int
15
16(** Empty byte_range for array initialization. *)
17val empty : byte_range
18
19(** {2 Range Queries} *)
20
21(** Returns true if this is a standard range with explicit start and end. *)
22val is_range : byte_range -> bool
23
24(** Returns true if this is a suffix range (last N bytes). *)
25val is_suffix : byte_range -> bool
26
27(** Returns true if this is an open-ended range (start to EOF). *)
28val is_open : byte_range -> bool
29
30(** Parse status. *)
31type parse_status =
32 | Valid
33 | Invalid
34
35(** A resolved byte range with concrete start/end positions. *)
36type resolved =
37 { start : int64 (** First byte position (0-indexed) *)
38 ; end_ : int64 (** Last byte position (inclusive) *)
39 ; length : int64 (** Number of bytes: end_ - start + 1 *)
40 }
41
42(** Empty resolved range for array initialization. *)
43val empty_resolved : resolved
44
45(** Range evaluation result. *)
46type eval_result =
47 | Full_content (** Serve full content *)
48 | Single_range (** Single range - use first resolved *)
49 | Multiple_ranges (** Multiple ranges - use resolved array *)
50 | Not_satisfiable (** 416 error *)
51
52(** {1 Parsing} *)
53
54(** Parse Range header value into array of byte_ranges.
55 Returns (status, count) where count is number of ranges parsed.
56 Only supports "bytes" unit. *)
57val parse
58 : Base_bigstring.t
59 -> Span.t
60 -> byte_range array
61 -> parse_status * int
62
63(** Parse Range header from a string. Creates a local buffer internally. *)
64val parse_string : string -> byte_range array -> parse_status * int
65
66(** {1 Range Resolution} *)
67
68(** Evaluate ranges and determine result.
69 Returns (result, resolved_count).
70 Resolved ranges are written to the output array. *)
71val evaluate
72 : byte_range array
73 -> count:int
74 -> resource_length:int64
75 -> resolved array
76 -> eval_result * int
77
78(** Resolve a single byte_range against resource length.
79 Returns (valid, resolved) where valid indicates if range is satisfiable. *)
80val resolve_range
81 : byte_range
82 -> resource_length:int64
83 -> bool * resolved
84
85(** {1 Response Writing} *)
86
87(** Write [Accept-Ranges: bytes\r\n] header. Returns new offset. *)
88val write_accept_ranges : Base_bigstring.t -> off:int -> int
89
90(** Write [Accept-Ranges: none\r\n] header. Returns new offset. *)
91val write_accept_ranges_none : Base_bigstring.t -> off:int -> int
92
93(** Write [Content-Range: bytes start-end/total\r\n] header. *)
94val write_content_range
95 : Base_bigstring.t
96 -> off:int
97 -> start:int64
98 -> end_:int64
99 -> total:int64
100 -> int
101
102(** Write Content-Range header from resolved range. *)
103val write_content_range_resolved
104 : Base_bigstring.t
105 -> off:int
106 -> resolved
107 -> total:int64
108 -> int
109
110(** Write [Content-Range: bytes * /total\r\n] header for 416 responses. *)
111val write_content_range_unsatisfiable
112 : Base_bigstring.t
113 -> off:int
114 -> total:int64
115 -> int
116
117(** {1 Multipart Helpers} *)
118
119(** Write multipart boundary line: [--boundary\r\n]. *)
120val write_multipart_boundary : Base_bigstring.t -> off:int -> boundary:string -> int
121
122(** Write final multipart boundary: [--boundary--\r\n]. *)
123val write_multipart_final : Base_bigstring.t -> off:int -> boundary:string -> int
124
125(** Generate a random boundary string suitable for multipart responses. *)
126val generate_boundary : unit -> string