mirror of
https://github.com/nghttp2/nghttp2.git
synced 2025-12-07 02:28:53 +08:00
Previously we did not check HTTP semantics and it is left out for application. Although checking is relatively easy, but they are scattered and error prone. We have implemented these checks in our applications and also feel they are tedious. To make application development a bit easier, this commit adds basic HTTP semantics validation to library code. We do following checks: server: * HEADERS is either request header or trailer header. Other type of header is disallowed. client: * HEADERS is either zero or more non-final response header or final response header or trailer header. Other type of header is disallowed. For both: * Check mandatory pseudo header fields. * Make sure that content-length matches the amount of DATA we received. If validation fails, RST_STREAM of type PROTOCOL_ERROR is issued.
86 lines
1.7 KiB
Python
Executable File
86 lines
1.7 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
HEADERS = [
|
|
':authority',
|
|
':method',
|
|
':path',
|
|
':scheme',
|
|
':status',
|
|
"content-length",
|
|
"host",
|
|
"te",
|
|
'connection',
|
|
'keep-alive',
|
|
'proxy-connection',
|
|
'transfer-encoding',
|
|
'upgrade'
|
|
]
|
|
|
|
def to_enum_hd(k):
|
|
res = 'NGHTTP2_TOKEN_'
|
|
for c in k.upper():
|
|
if c == ':' or c == '-':
|
|
res += '_'
|
|
continue
|
|
res += c
|
|
return res
|
|
|
|
def build_header(headers):
|
|
res = {}
|
|
for k in headers:
|
|
size = len(k)
|
|
if size not in res:
|
|
res[size] = {}
|
|
ent = res[size]
|
|
c = k[-1]
|
|
if c not in ent:
|
|
ent[c] = []
|
|
ent[c].append(k)
|
|
|
|
return res
|
|
|
|
def gen_enum():
|
|
print '''\
|
|
typedef enum {'''
|
|
for k in sorted(HEADERS):
|
|
print '''\
|
|
{},'''.format(to_enum_hd(k))
|
|
print '''\
|
|
NGHTTP2_TOKEN_MAXIDX,
|
|
} nghttp2_token;'''
|
|
|
|
def gen_index_header():
|
|
print '''\
|
|
static int lookup_token(const uint8_t *name, size_t namelen) {
|
|
switch (namelen) {'''
|
|
b = build_header(HEADERS)
|
|
for size in sorted(b.keys()):
|
|
ents = b[size]
|
|
print '''\
|
|
case {}:'''.format(size)
|
|
print '''\
|
|
switch (name[namelen - 1]) {'''
|
|
for c in sorted(ents.keys()):
|
|
headers = sorted(ents[c])
|
|
print '''\
|
|
case '{}':'''.format(c)
|
|
for k in headers:
|
|
print '''\
|
|
if (streq("{}", name, {})) {{
|
|
return {};
|
|
}}'''.format(k[:-1], size - 1, to_enum_hd(k))
|
|
print '''\
|
|
break;'''
|
|
print '''\
|
|
}
|
|
break;'''
|
|
print '''\
|
|
}
|
|
return -1;
|
|
}'''
|
|
|
|
if __name__ == '__main__':
|
|
gen_enum()
|
|
print ''
|
|
gen_index_header()
|