int qpack_encode_field_section_line(struct buffer *out);
int qpack_encode_int_status(struct buffer *out, unsigned int status);
int qpack_encode_method(struct buffer *out, enum http_meth_t meth, struct ist other);
-int qpack_encode_scheme(struct buffer *out);
+int qpack_encode_scheme(struct buffer *out, const struct ist scheme);
int qpack_encode_path(struct buffer *out, const struct ist path);
int qpack_encode_header(struct buffer *out, const struct ist n, const struct ist v);
enum htx_blk_type type;
struct htx_blk *blk;
struct htx_sl *sl;
- struct ist meth;
+ struct ist meth, uri, scheme = IST_NULL, auth = IST_NULL;
int frame_length_size; /* size in bytes of frame length varint field */
int ret, err, hdr;
BUG_ON_HOT(sl); /* Only one start-line expected */
sl = htx_get_blk_ptr(htx, blk);
meth = htx_sl_req_meth(sl);
+ uri = htx_sl_req_uri(sl);
break;
case HTX_BLK_HDR:
if (qpack_encode_method(&headers_buf, sl->info.req.meth, meth))
goto err;
- if (qpack_encode_scheme(&headers_buf))
+ if (uri.ptr[0] != '/' && uri.ptr[0] != '*') {
+ int len = 1;
+
+ /* the URI seems to start with a scheme */
+ while (len < uri.len && uri.ptr[len] != ':')
+ len++;
+
+ if (len + 2 < uri.len && uri.ptr[len + 1] == '/' && uri.ptr[len + 2] == '/') {
+ /* make the uri start at the authority now */
+ scheme = ist2(uri.ptr, len);
+ uri = istadv(uri, len + 3);
+
+ /* find the auth part of the URI */
+ auth = ist2(uri.ptr, 0);
+ while (auth.len < uri.len && auth.ptr[auth.len] != '/')
+ auth.len++;
+
+ uri = istadv(uri, auth.len);
+ }
+ }
+
+ if (!istlen(scheme)) {
+ if ((sl->flags & (HTX_SL_F_HAS_SCHM|HTX_SL_F_SCHM_HTTP)) == (HTX_SL_F_HAS_SCHM|HTX_SL_F_SCHM_HTTP))
+ scheme = ist("http");
+ else
+ scheme = ist("https");
+ }
+
+ if (qpack_encode_scheme(&headers_buf, scheme))
goto err;
if (qpack_encode_path(&headers_buf, ist('/')))
return 0;
}
-/* Encode pseudo-header scheme defined to https on <out> buffer.
- *
- * Returns 0 on success else non-zero.
- */
-int qpack_encode_scheme(struct buffer *out)
+/* Returns 0 on success else non-zero. */
+int qpack_encode_scheme(struct buffer *out, const struct ist scheme)
{
- if (b_room(out) < 2)
- return 1;
+ int sz;
+
+ if (unlikely(!isteq(scheme, ist("https"))) && !isteq(scheme, ist("http"))) {
+ sz = 2 + qpack_get_prefix_int_size(istlen(scheme), 7) + istlen(scheme);
+ if (b_room(out) < sz)
+ return 1;
+
+ /* literal field line with name ref */
+ qpack_encode_prefix_integer(out, 23, 4, 0x50);
+ qpack_encode_prefix_integer(out, istlen(scheme), 7, 0);
+ for (size_t i = 0; i < istlen(scheme); ++i)
+ b_putchr(out, istptr(scheme)[i]);
+ }
+ else {
+ int idx = 23;
+
+ if (unlikely(!isteq(scheme, ist("http"))))
+ idx = 22;
+ if (b_room(out) < 2)
+ return 1;
+
+ /* :scheme: http[s] */
+ qpack_encode_prefix_integer(out, idx, 6, 0xc0);
+ }
- /* :scheme: https */
- qpack_encode_prefix_integer(out, 23, 6, 0xc0);
return 0;
}