11#if DETWS_ENABLE_HTTP_DELIVERY
19bool read_u32(
const char **p, uint32_t *out)
22 if (*s <
'0' || *s >
'9')
26 while (*s >=
'0' && *s <=
'9')
28 v = v * 10 + (uint32_t)(*s -
'0');
31 if (n > 10 || v > 0xFFFFFFFFu)
47void put(Buf *b,
const char *s)
51 size_t sl = strnlen(s, b->cap + 1);
52 if (b->len + sl >= b->cap)
57 memcpy(b->p + b->len, s, sl);
61void put_u32(Buf *b, uint32_t v)
67 t[n++] = (char)(
'0' + v % 10);
71 for (
int i = 0; i < n; i++)
77void put_json_str(Buf *b,
const char *s)
80 for (
const char *p = s ? s :
""; *p; p++)
82 if (*p ==
'"' || *p ==
'\\')
84 char esc[3] = {
'\\', *p,
'\0'};
87 else if (b->len + 1 < b->cap)
98bool parse_range_spec(
const char *range_header,
bool *have_start,
bool *have_end, uint32_t *s, uint32_t *e)
100 const char *p = range_header;
101 while (*p ==
' ' || *p ==
'\t')
103 if (strncmp(p,
"bytes=", 6) != 0)
113 if (*p >=
'0' && *p <=
'9')
115 if (!read_u32(&p, s))
122 if (*p >=
'0' && *p <=
'9')
124 if (!read_u32(&p, e))
128 while (*p ==
' ' || *p ==
'\t')
130 if (*p !=
'\0' && *p !=
'\r' && *p !=
'\n')
136DeliveryVerdict detws_delivery_swr(uint32_t age_s, uint32_t max_age_s, uint32_t swr_s)
138 if (age_s <= max_age_s)
139 return DeliveryVerdict::DELIVERY_FRESH;
140 uint64_t window = (uint64_t)max_age_s + swr_s;
141 if ((uint64_t)age_s <= window)
142 return DeliveryVerdict::DELIVERY_STALE_REVALIDATE;
143 return DeliveryVerdict::DELIVERY_EXPIRED;
146size_t detws_delivery_cache_control(uint32_t max_age_s, uint32_t swr_s,
char *out,
size_t cap)
148 if (!out || cap == 0)
150 Buf b = {out, cap, 0,
true};
151 put(&b,
"public, max-age=");
152 put_u32(&b, max_age_s);
155 put(&b,
", stale-while-revalidate=");
164int detws_delivery_range(
const char *range_header, uint32_t total, uint32_t *start, uint32_t *end)
166 if (!range_header || !start || !end || total == 0)
169 bool have_start =
false;
170 bool have_end =
false;
173 if (!parse_range_spec(range_header, &have_start, &have_end, &s, &e))
180 if (!have_end || e == 0)
182 rs = (e >= total) ? 0 : (total - e);
190 re = have_end ? e : (total - 1);
201size_t detws_delivery_content_range(uint32_t start, uint32_t end, uint32_t total,
char *out,
size_t cap)
203 if (!out || cap == 0)
205 Buf b = {out, cap, 0,
true};
218size_t detws_delivery_sw_manifest(
const char *
const *paths,
size_t n,
const char *version,
char *out,
size_t cap)
220 if (!out || cap == 0 || (n && !paths))
222 Buf b = {out, cap, 0,
true};
223 put(&b,
"{\"version\":");
224 put_json_str(&b, version ? version :
"");
225 put(&b,
",\"precache\":[");
226 for (
size_t i = 0; i < n; i++)
230 put_json_str(&b, paths[i]);
HTTP delivery optimizations: stale-while-revalidate, Range/206 delta fetch, SW precache (DETWS_ENABLE...