Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
b1edb1f3
Commit
b1edb1f3
authored
Apr 03, 2014
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Don't index name/value pair bearing NO_INDEX flag when forwarding it
parent
c53c1dc6
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
276 additions
and
200 deletions
+276
-200
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+4
-0
src/HttpServer.cc
src/HttpServer.cc
+16
-15
src/h2load.cc
src/h2load.cc
+4
-4
src/http2.cc
src/http2.cc
+60
-41
src/http2.h
src/http2.h
+37
-6
src/http2_test.cc
src/http2_test.cc
+22
-15
src/nghttp.cc
src/nghttp.cc
+28
-23
src/shrpx_downstream.cc
src/shrpx_downstream.cc
+41
-36
src/shrpx_downstream.h
src/shrpx_downstream.h
+4
-2
src/shrpx_downstream_test.cc
src/shrpx_downstream_test.cc
+17
-17
src/shrpx_http2_downstream_connection.cc
src/shrpx_http2_downstream_connection.cc
+5
-5
src/shrpx_http2_session.cc
src/shrpx_http2_session.cc
+4
-3
src/shrpx_http2_upstream.cc
src/shrpx_http2_upstream.cc
+8
-7
src/shrpx_http_downstream_connection.cc
src/shrpx_http_downstream_connection.cc
+11
-11
src/shrpx_https_upstream.cc
src/shrpx_https_upstream.cc
+6
-6
src/shrpx_spdy_upstream.cc
src/shrpx_spdy_upstream.cc
+9
-9
No files found.
lib/includes/nghttp2/nghttp2.h
View file @
b1edb1f3
...
...
@@ -1342,6 +1342,10 @@ typedef int (*nghttp2_on_begin_headers_callback)
* The |value| of length |valuelen| is header value. The |flags| is
* bitwise OR of one or more of :type:`nghttp2_nv_flag`.
*
* If :enum:`NGHTTP2_NV_FLAG_NO_INDEX` is set in |flags|, the receiver
* must not index this name/value pair when forwarding it to the next
* hop.
*
* When this callback is invoked, ``frame->hd.type`` is either
* :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`. After all
* header name/value pairs are processed with this callback, and no
...
...
src/HttpServer.cc
View file @
b1edb1f3
...
...
@@ -805,7 +805,7 @@ int Http2Handler::submit_response
http2
::
make_nv_ls
(
"date"
,
date_str
)
};
for
(
size_t
i
=
0
;
i
<
headers
.
size
();
++
i
)
{
nva
.
push_back
(
http2
::
make_nv
(
headers
[
i
].
first
,
headers
[
i
].
second
));
nva
.
push_back
(
http2
::
make_nv
(
headers
[
i
].
first
,
headers
[
i
].
second
,
false
));
}
int
r
=
nghttp2_submit_response
(
session_
,
stream_id
,
nva
.
data
(),
nva
.
size
(),
data_prd
);
...
...
@@ -830,21 +830,21 @@ int Http2Handler::submit_push_promise(Stream *stream,
std
::
string
authority
;
auto
itr
=
std
::
lower_bound
(
std
::
begin
(
stream
->
headers
),
std
::
end
(
stream
->
headers
),
std
::
make_pair
(
std
::
string
(
":authority"
),
std
::
string
(
""
)));
if
(
itr
==
std
::
end
(
stream
->
headers
)
||
(
*
itr
).
first
!=
":authority"
)
{
Header
(
":authority"
,
""
));
if
(
itr
==
std
::
end
(
stream
->
headers
)
||
(
*
itr
).
name
!=
":authority"
)
{
itr
=
std
::
lower_bound
(
std
::
begin
(
stream
->
headers
),
std
::
end
(
stream
->
headers
),
std
::
make_pair
(
std
::
string
(
"host"
),
std
::
string
(
""
)));
Header
(
"host"
,
""
));
}
auto
nva
=
std
::
vector
<
nghttp2_nv
>
{
http2
::
make_nv_ll
(
":method"
,
"GET"
),
http2
::
make_nv_ls
(
":path"
,
push_path
),
get_config
()
->
no_tls
?
http2
::
make_nv_ll
(
":scheme"
,
"http"
)
:
http2
::
make_nv_ll
(
":scheme"
,
"https"
),
http2
::
make_nv_ls
(
":authority"
,
(
*
itr
).
second
)
http2
::
make_nv_ls
(
":authority"
,
(
*
itr
).
value
)
};
return
nghttp2_submit_push_promise
(
session_
,
NGHTTP2_FLAG_END_HEADERS
,
stream
->
stream_id
,
nva
.
data
(),
nva
.
size
(),
...
...
@@ -1008,18 +1008,17 @@ void prepare_response(Stream *stream, Http2Handler *hd, bool allow_push = true)
int
rv
;
auto
url
=
(
*
std
::
lower_bound
(
std
::
begin
(
stream
->
headers
),
std
::
end
(
stream
->
headers
),
std
::
make_pair
(
std
::
string
(
":path"
),
std
::
string
()))).
second
;
Header
(
":path"
,
""
))).
value
;
auto
ims
=
std
::
lower_bound
(
std
::
begin
(
stream
->
headers
),
std
::
end
(
stream
->
headers
),
std
::
make_pair
(
std
::
string
(
"if-modified-since"
),
std
::
string
()));
Header
(
"if-modified-since"
,
""
));
time_t
last_mod
=
0
;
bool
last_mod_found
=
false
;
if
(
ims
!=
std
::
end
(
stream
->
headers
)
&&
(
*
ims
).
first
==
"if-modified-since"
)
{
(
*
ims
).
name
==
"if-modified-since"
)
{
last_mod_found
=
true
;
last_mod
=
util
::
parse_http_date
((
*
ims
).
second
);
last_mod
=
util
::
parse_http_date
((
*
ims
).
value
);
}
auto
query_pos
=
url
.
find
(
"?"
);
if
(
query_pos
!=
std
::
string
::
npos
)
{
...
...
@@ -1078,7 +1077,8 @@ void append_nv(Stream *stream, const std::vector<nghttp2_nv>& nva)
{
for
(
auto
&
nv
:
nva
)
{
http2
::
split_add_header
(
stream
->
headers
,
nv
.
name
,
nv
.
namelen
,
nv
.
value
,
nv
.
valuelen
);
nv
.
name
,
nv
.
namelen
,
nv
.
value
,
nv
.
valuelen
,
nv
.
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
}
}
}
// namespace
...
...
@@ -1114,7 +1114,8 @@ int on_header_callback(nghttp2_session *session,
if
(
!
http2
::
check_nv
(
name
,
namelen
,
value
,
valuelen
))
{
return
0
;
}
http2
::
split_add_header
(
stream
->
headers
,
name
,
namelen
,
value
,
valuelen
);
http2
::
split_add_header
(
stream
->
headers
,
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
return
0
;
}
}
// namespace
...
...
src/h2load.cc
View file @
b1edb1f3
...
...
@@ -792,7 +792,7 @@ int main(int argc, char **argv)
nva
.
push_back
(
http2
::
make_nv_ls
(
":path"
,
req
));
for
(
auto
&
nv
:
shared_nva
)
{
nva
.
push_back
(
http2
::
make_nv
(
nv
.
first
,
nv
.
second
));
nva
.
push_back
(
http2
::
make_nv
(
nv
.
name
,
nv
.
value
,
false
));
}
config
.
nva
.
push_back
(
std
::
move
(
nva
));
...
...
@@ -804,12 +804,12 @@ int main(int argc, char **argv)
cva
.
push_back
(
req
.
c_str
());
for
(
auto
&
nv
:
shared_nva
)
{
if
(
nv
.
first
==
":authority"
)
{
if
(
nv
.
name
==
":authority"
)
{
cva
.
push_back
(
":host"
);
}
else
{
cva
.
push_back
(
nv
.
first
.
c_str
());
cva
.
push_back
(
nv
.
name
.
c_str
());
}
cva
.
push_back
(
nv
.
second
.
c_str
());
cva
.
push_back
(
nv
.
value
.
c_str
());
}
cva
.
push_back
(
":version"
);
cva
.
push_back
(
"HTTP/1.1"
);
...
...
src/http2.cc
View file @
b1edb1f3
...
...
@@ -206,14 +206,14 @@ auto nv_name_less = [](const nghttp2_nv& lhs, const nghttp2_nv& rhs)
bool
name_less
(
const
Headers
::
value_type
&
lhs
,
const
Headers
::
value_type
&
rhs
)
{
return
lhs
.
first
<
rhs
.
first
;
return
lhs
.
name
<
rhs
.
name
;
}
bool
check_http2_headers
(
const
Headers
&
nva
)
{
for
(
size_t
i
=
0
;
i
<
DISALLOWED_HDLEN
;
++
i
)
{
if
(
std
::
binary_search
(
std
::
begin
(
nva
),
std
::
end
(
nva
),
std
::
make_pai
r
(
DISALLOWED_HD
[
i
],
""
),
name_less
))
{
Heade
r
(
DISALLOWED_HD
[
i
],
""
),
name_less
))
{
return
false
;
}
}
...
...
@@ -223,7 +223,7 @@ bool check_http2_headers(const Headers& nva)
void
normalize_headers
(
Headers
&
nva
)
{
for
(
auto
&
kv
:
nva
)
{
util
::
inp_strlower
(
kv
.
first
);
util
::
inp_strlower
(
kv
.
name
);
}
std
::
stable_sort
(
std
::
begin
(
nva
),
std
::
end
(
nva
),
name_less
);
}
...
...
@@ -260,20 +260,23 @@ std::vector<nghttp2_nv> sort_nva(const nghttp2_nv *nva, size_t nvlen)
}
Headers
::
value_type
to_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
)
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
)
{
return
std
::
make_pair
(
std
::
string
(
reinterpret_cast
<
const
char
*>
(
name
),
namelen
),
std
::
string
(
reinterpret_cast
<
const
char
*>
(
value
),
valuelen
));
return
Header
(
std
::
string
(
reinterpret_cast
<
const
char
*>
(
name
),
namelen
),
std
::
string
(
reinterpret_cast
<
const
char
*>
(
value
),
valuelen
),
no_index
);
}
void
split_add_header
(
Headers
&
nva
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
)
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
)
{
if
(
valuelen
==
0
)
{
nva
.
push_back
(
to_header
(
name
,
namelen
,
value
,
valuelen
));
nva
.
push_back
(
to_header
(
name
,
namelen
,
value
,
valuelen
,
no_index
));
return
;
}
auto
j
=
value
;
...
...
@@ -289,7 +292,7 @@ void split_add_header(Headers& nva,
break
;
}
auto
l
=
std
::
find
(
j
,
end
,
'\0'
);
nva
.
push_back
(
to_header
(
name
,
namelen
,
j
,
l
-
j
));
nva
.
push_back
(
to_header
(
name
,
namelen
,
j
,
l
-
j
,
no_index
));
j
=
l
;
}
}
...
...
@@ -299,9 +302,9 @@ const Headers::value_type* get_unique_header(const Headers& nva,
{
auto
nv
=
Headers
::
value_type
(
name
,
""
);
auto
i
=
std
::
lower_bound
(
std
::
begin
(
nva
),
std
::
end
(
nva
),
nv
,
name_less
);
if
(
i
!=
std
::
end
(
nva
)
&&
(
*
i
).
first
==
nv
.
first
)
{
if
(
i
!=
std
::
end
(
nva
)
&&
(
*
i
).
name
==
nv
.
name
)
{
auto
j
=
i
+
1
;
if
(
j
==
std
::
end
(
nva
)
||
(
*
j
).
first
!=
nv
.
first
)
{
if
(
j
==
std
::
end
(
nva
)
||
(
*
j
).
name
!=
nv
.
name
)
{
return
&
(
*
i
);
}
}
...
...
@@ -312,7 +315,7 @@ const Headers::value_type* get_header(const Headers& nva, const char *name)
{
auto
nv
=
Headers
::
value_type
(
name
,
""
);
auto
i
=
std
::
lower_bound
(
std
::
begin
(
nva
),
std
::
end
(
nva
),
nv
,
name_less
);
if
(
i
!=
std
::
end
(
nva
)
&&
(
*
i
).
first
==
nv
.
first
)
{
if
(
i
!=
std
::
end
(
nva
)
&&
(
*
i
).
name
==
nv
.
name
)
{
return
&
(
*
i
);
}
return
nullptr
;
...
...
@@ -321,14 +324,14 @@ const Headers::value_type* get_header(const Headers& nva, const char *name)
std
::
string
value_to_str
(
const
Headers
::
value_type
*
nv
)
{
if
(
nv
)
{
return
nv
->
second
;
return
nv
->
value
;
}
return
""
;
}
bool
value_lws
(
const
Headers
::
value_type
*
nv
)
{
return
(
*
nv
).
second
.
find_first_not_of
(
"
\t
"
)
==
std
::
string
::
npos
;
return
(
*
nv
).
value
.
find_first_not_of
(
"
\t
"
)
==
std
::
string
::
npos
;
}
bool
non_empty_value
(
const
Headers
::
value_type
*
nv
)
...
...
@@ -336,13 +339,18 @@ bool non_empty_value(const Headers::value_type *nv)
return
nv
&&
!
value_lws
(
nv
);
}
nghttp2_nv
make_nv
(
const
std
::
string
&
name
,
const
std
::
string
&
value
)
nghttp2_nv
make_nv
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
no_index
)
{
uint8_t
flags
;
flags
=
no_index
?
NGHTTP2_NV_FLAG_NO_INDEX
:
NGHTTP2_NV_FLAG_NONE
;
return
{
(
uint8_t
*
)
name
.
c_str
(),
(
uint8_t
*
)
value
.
c_str
(),
(
uint16_t
)
name
.
size
(),
(
uint16_t
)
value
.
size
(),
NGHTTP2_NV_FLAG_NONE
flags
};
}
...
...
@@ -351,12 +359,17 @@ Headers concat_norm_headers(Headers headers)
auto
res
=
Headers
();
res
.
reserve
(
headers
.
size
());
for
(
auto
&
kv
:
headers
)
{
if
(
!
res
.
empty
()
&&
res
.
back
().
first
==
kv
.
first
&&
kv
.
first
!=
"cookie"
&&
kv
.
first
!=
"set-cookie"
)
{
if
(
!
kv
.
second
.
empty
())
{
res
.
back
().
second
.
append
(
1
,
'\0'
);
res
.
back
().
second
+=
kv
.
second
;
if
(
!
res
.
empty
()
&&
res
.
back
().
name
==
kv
.
name
&&
kv
.
name
!=
"cookie"
&&
kv
.
name
!=
"set-cookie"
)
{
auto
&
last
=
res
.
back
();
if
(
!
kv
.
value
.
empty
())
{
last
.
value
.
append
(
1
,
'\0'
);
last
.
value
+=
kv
.
value
;
}
// We do ORing nv flags. This is done even if value is empty.
last
.
no_index
|=
kv
.
no_index
;
}
else
{
res
.
push_back
(
std
::
move
(
kv
));
}
...
...
@@ -369,10 +382,11 @@ void copy_norm_headers_to_nva
{
size_t
i
,
j
;
for
(
i
=
0
,
j
=
0
;
i
<
headers
.
size
()
&&
j
<
IGN_HDLEN
;)
{
int
rv
=
strcmp
(
headers
[
i
].
first
.
c_str
(),
IGN_HD
[
j
]);
auto
&
kv
=
headers
[
i
];
int
rv
=
strcmp
(
kv
.
name
.
c_str
(),
IGN_HD
[
j
]);
if
(
rv
<
0
)
{
if
(
!
headers
[
i
].
first
.
empty
()
&&
headers
[
i
].
first
.
c_str
()[
0
]
!=
':'
)
{
nva
.
push_back
(
make_nv
(
headers
[
i
].
first
,
headers
[
i
].
second
));
if
(
!
kv
.
name
.
empty
()
&&
kv
.
name
.
c_str
()[
0
]
!=
':'
)
{
nva
.
push_back
(
make_nv
(
kv
.
name
,
kv
.
value
,
kv
.
no_index
));
}
++
i
;
}
else
if
(
rv
>
0
)
{
...
...
@@ -382,8 +396,9 @@ void copy_norm_headers_to_nva
}
}
for
(;
i
<
headers
.
size
();
++
i
)
{
if
(
!
headers
[
i
].
first
.
empty
()
&&
headers
[
i
].
first
.
c_str
()[
0
]
!=
':'
)
{
nva
.
push_back
(
make_nv
(
headers
[
i
].
first
,
headers
[
i
].
second
));
auto
&
kv
=
headers
[
i
];
if
(
!
kv
.
name
.
empty
()
&&
kv
.
name
.
c_str
()[
0
]
!=
':'
)
{
nva
.
push_back
(
make_nv
(
kv
.
name
,
kv
.
value
,
kv
.
no_index
));
}
}
}
...
...
@@ -393,14 +408,16 @@ void build_http1_headers_from_norm_headers
{
size_t
i
,
j
;
for
(
i
=
0
,
j
=
0
;
i
<
headers
.
size
()
&&
j
<
HTTP1_IGN_HDLEN
;)
{
int
rv
=
strcmp
(
headers
[
i
].
first
.
c_str
(),
HTTP1_IGN_HD
[
j
]);
auto
&
kv
=
headers
[
i
];
auto
rv
=
strcmp
(
kv
.
name
.
c_str
(),
HTTP1_IGN_HD
[
j
]);
if
(
rv
<
0
)
{
if
(
!
headers
[
i
].
first
.
empty
()
&&
headers
[
i
].
first
.
c_str
()[
0
]
!=
':'
)
{
hdrs
+=
headers
[
i
].
first
;
capitalize
(
hdrs
,
hdrs
.
size
()
-
headers
[
i
].
first
.
size
());
if
(
!
kv
.
name
.
empty
()
&&
kv
.
name
.
c_str
()[
0
]
!=
':'
)
{
hdrs
+=
kv
.
name
;
capitalize
(
hdrs
,
hdrs
.
size
()
-
kv
.
name
.
size
());
hdrs
+=
": "
;
hdrs
+=
headers
[
i
].
second
;
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
headers
[
i
].
second
.
size
());
hdrs
+=
kv
.
value
;
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
kv
.
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
++
i
;
...
...
@@ -411,12 +428,14 @@ void build_http1_headers_from_norm_headers
}
}
for
(;
i
<
headers
.
size
();
++
i
)
{
if
(
!
headers
[
i
].
first
.
empty
()
&&
headers
[
i
].
first
.
c_str
()[
0
]
!=
':'
)
{
hdrs
+=
headers
[
i
].
first
;
capitalize
(
hdrs
,
hdrs
.
size
()
-
headers
[
i
].
first
.
size
());
auto
&
kv
=
headers
[
i
];
if
(
!
kv
.
name
.
empty
()
&&
kv
.
name
.
c_str
()[
0
]
!=
':'
)
{
hdrs
+=
kv
.
name
;
capitalize
(
hdrs
,
hdrs
.
size
()
-
kv
.
name
.
size
());
hdrs
+=
": "
;
hdrs
+=
headers
[
i
].
second
;
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
headers
[
i
].
second
.
size
());
hdrs
+=
kv
.
value
;
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
kv
.
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
}
...
...
@@ -472,9 +491,9 @@ void dump_nv(FILE *out, const nghttp2_nv *nva, size_t nvlen)
void
dump_nv
(
FILE
*
out
,
const
Headers
&
nva
)
{
for
(
auto
&
nv
:
nva
)
{
fwrite
(
nv
.
first
.
c_str
(),
nv
.
first
.
size
(),
1
,
out
);
fwrite
(
nv
.
name
.
c_str
(),
nv
.
name
.
size
(),
1
,
out
);
fwrite
(
": "
,
2
,
1
,
out
);
fwrite
(
nv
.
second
.
c_str
(),
nv
.
second
.
size
(),
1
,
out
);
fwrite
(
nv
.
value
.
c_str
(),
nv
.
value
.
size
(),
1
,
out
);
fwrite
(
"
\n
"
,
1
,
1
,
out
);
}
fwrite
(
"
\n
"
,
1
,
1
,
out
);
...
...
src/http2.h
View file @
b1edb1f3
...
...
@@ -38,7 +38,33 @@
namespace
nghttp2
{
typedef
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
Headers
;
struct
Header
{
Header
(
std
::
string
name
,
std
::
string
value
,
bool
no_index
=
false
)
:
name
(
std
::
move
(
name
)),
value
(
std
::
move
(
value
)),
no_index
(
no_index
)
{}
Header
()
:
no_index
(
false
)
{}
bool
operator
==
(
const
Header
&
other
)
const
{
return
name
==
other
.
name
&&
value
==
other
.
value
;
}
bool
operator
<
(
const
Header
&
rhs
)
const
{
return
name
<
rhs
.
name
||
(
name
==
rhs
.
name
&&
value
<
rhs
.
value
);
}
std
::
string
name
;
std
::
string
value
;
bool
no_index
;
};
typedef
std
::
vector
<
Header
>
Headers
;
namespace
http2
{
...
...
@@ -75,15 +101,18 @@ bool name_less(const Headers::value_type& lhs, const Headers::value_type& rhs);
void
normalize_headers
(
Headers
&
nva
);
Headers
::
value_type
to_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
);
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
);
// Add name/value pairs to |nva|. The name is given in the |name| with
// |namelen| bytes. This function inspects the |value| and split it
// using '\0' as delimiter. Each token is added to the |nva| with the
// name |name|.
// name |name|. If |no_index| is true, this name/value pair won't be
// indexed when it is forwarded to the next hop.
void
split_add_header
(
Headers
&
nva
,
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
);
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
);
// Returns sorted |nva| with |nvlen| elements. The headers are sorted
// by name only and not necessarily stable. In addition to the
...
...
@@ -122,8 +151,10 @@ Headers concat_norm_headers(Headers headers);
// Creates nghttp2_nv using |name| and |value| and returns it. The
// returned value only references the data pointer to name.c_str() and
// value.c_str().
nghttp2_nv
make_nv
(
const
std
::
string
&
name
,
const
std
::
string
&
value
);
// value.c_str(). If |no_index| is true, nghttp2_nv flags member has
// NGHTTP2_NV_FLAG_NO_INDEX flag set.
nghttp2_nv
make_nv
(
const
std
::
string
&
name
,
const
std
::
string
&
value
,
bool
no_index
);
// Create nghttp2_nv from string literal |name| and |value|.
template
<
size_t
N
,
size_t
M
>
...
...
src/http2_test.cc
View file @
b1edb1f3
...
...
@@ -44,13 +44,12 @@ using namespace nghttp2;
namespace
shrpx
{
namespace
{
void
check_nv
(
const
std
::
pair
<
std
::
string
,
std
::
string
>&
a
,
const
nghttp2_nv
*
b
)
void
check_nv
(
const
Header
&
a
,
const
nghttp2_nv
*
b
)
{
CU_ASSERT
(
a
.
first
.
size
()
==
b
->
namelen
);
CU_ASSERT
(
a
.
second
.
size
()
==
b
->
valuelen
);
CU_ASSERT
(
memcmp
(
a
.
first
.
c_str
(),
b
->
name
,
b
->
namelen
)
==
0
);
CU_ASSERT
(
memcmp
(
a
.
second
.
c_str
(),
b
->
value
,
b
->
valuelen
)
==
0
);
CU_ASSERT
(
a
.
name
.
size
()
==
b
->
namelen
);
CU_ASSERT
(
a
.
value
.
size
()
==
b
->
valuelen
);
CU_ASSERT
(
memcmp
(
a
.
name
.
c_str
(),
b
->
name
,
b
->
namelen
)
==
0
);
CU_ASSERT
(
memcmp
(
a
.
value
.
c_str
(),
b
->
value
,
b
->
valuelen
)
==
0
);
}
}
// namespace
...
...
@@ -78,7 +77,7 @@ void test_http2_split_add_header(void)
const
uint8_t
concatval
[]
=
{
'4'
,
0x00
,
0x00
,
'6'
,
0x00
,
'5'
,
'9'
,
0x00
};
auto
nva
=
Headers
();
http2
::
split_add_header
(
nva
,
(
const
uint8_t
*
)
"delta"
,
5
,
concatval
,
sizeof
(
concatval
));
concatval
,
sizeof
(
concatval
)
,
false
);
CU_ASSERT
(
Headers
::
value_type
(
"delta"
,
"4"
)
==
nva
[
0
]);
CU_ASSERT
(
Headers
::
value_type
(
"delta"
,
"6"
)
==
nva
[
1
]);
CU_ASSERT
(
Headers
::
value_type
(
"delta"
,
"59"
)
==
nva
[
2
]);
...
...
@@ -86,14 +85,16 @@ void test_http2_split_add_header(void)
nva
.
clear
();
http2
::
split_add_header
(
nva
,
(
const
uint8_t
*
)
"alpha"
,
5
,
(
const
uint8_t
*
)
"123"
,
3
);
(
const
uint8_t
*
)
"123"
,
3
,
false
);
CU_ASSERT
(
Headers
::
value_type
(
"alpha"
,
"123"
)
==
nva
[
0
]);
CU_ASSERT
(
!
nva
[
0
].
no_index
);
nva
.
clear
();
http2
::
split_add_header
(
nva
,
(
const
uint8_t
*
)
"alpha"
,
5
,
(
const
uint8_t
*
)
""
,
0
);
(
const
uint8_t
*
)
""
,
0
,
true
);
CU_ASSERT
(
Headers
::
value_type
(
"alpha"
,
""
)
==
nva
[
0
]);
CU_ASSERT
(
nva
[
0
].
no_index
);
}
void
test_http2_check_http2_headers
(
void
)
...
...
@@ -133,7 +134,7 @@ void test_http2_get_unique_header(void)
const
Headers
::
value_type
*
rv
;
rv
=
http2
::
get_unique_header
(
nva
,
"delta"
);
CU_ASSERT
(
rv
!=
nullptr
);
CU_ASSERT
(
"delta"
==
rv
->
first
);
CU_ASSERT
(
"delta"
==
rv
->
name
);
rv
=
http2
::
get_unique_header
(
nva
,
"bravo"
);
CU_ASSERT
(
rv
==
nullptr
);
...
...
@@ -155,11 +156,11 @@ void test_http2_get_header(void)
const
Headers
::
value_type
*
rv
;
rv
=
http2
::
get_header
(
nva
,
"delta"
);
CU_ASSERT
(
rv
!=
nullptr
);
CU_ASSERT
(
"delta"
==
rv
->
first
);
CU_ASSERT
(
"delta"
==
rv
->
name
);
rv
=
http2
::
get_header
(
nva
,
"bravo"
);
CU_ASSERT
(
rv
!=
nullptr
);
CU_ASSERT
(
"bravo"
==
rv
->
first
);
CU_ASSERT
(
"bravo"
==
rv
->
name
);
rv
=
http2
::
get_header
(
nva
,
"foxtrot"
);
CU_ASSERT
(
rv
==
nullptr
);
...
...
@@ -182,8 +183,8 @@ void test_http2_value_lws(void)
}
namespace
{
auto
headers
=
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
{{
"alpha"
,
"0"
},
auto
headers
=
Headers
{{
"alpha"
,
"0"
,
true
},
{
"bravo"
,
"1"
},
{
"connection"
,
"2"
},
{
"connection"
,
"3"
},
...
...
@@ -207,7 +208,7 @@ void test_http2_concat_norm_headers(void)
hds
.
emplace_back
(
"set-cookie"
,
"buzz"
);
auto
res
=
http2
::
concat_norm_headers
(
hds
);
CU_ASSERT
(
14
==
res
.
size
());
CU_ASSERT
(
std
::
string
(
"2"
)
+
'\0'
+
std
::
string
(
"3"
)
==
res
[
2
].
second
);
CU_ASSERT
(
std
::
string
(
"2"
)
+
'\0'
+
std
::
string
(
"3"
)
==
res
[
2
].
value
);
}
void
test_http2_copy_norm_headers_to_nva
(
void
)
...
...
@@ -218,6 +219,12 @@ void test_http2_copy_norm_headers_to_nva(void)
auto
ans
=
std
::
vector
<
int
>
{
0
,
1
,
4
,
6
,
7
,
12
};
for
(
size_t
i
=
0
;
i
<
ans
.
size
();
++
i
)
{
check_nv
(
headers
[
ans
[
i
]],
&
nva
[
i
]);
if
(
ans
[
i
]
==
0
)
{
CU_ASSERT
(
nva
[
i
].
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
}
else
{
CU_ASSERT
(
NGHTTP2_NV_FLAG_NONE
==
nva
[
i
].
flags
);
}
}
}
...
...
src/nghttp.cc
View file @
b1edb1f3
...
...
@@ -921,7 +921,7 @@ int submit_request
{
auto
path
=
req
->
make_reqpath
();
auto
scheme
=
util
::
get_uri_field
(
req
->
uri
.
c_str
(),
req
->
u
,
UF_SCHEMA
);
auto
build_headers
=
std
::
vector
<
std
::
pair
<
std
::
string
,
std
::
string
>>
auto
build_headers
=
Headers
{{
":method"
,
req
->
data_prd
?
"POST"
:
"GET"
},
{
":path"
,
path
},
{
":scheme"
,
scheme
},
...
...
@@ -942,27 +942,30 @@ int submit_request
for
(
auto
&
kv
:
headers
)
{
size_t
i
;
for
(
i
=
0
;
i
<
num_initial_headers
;
++
i
)
{
if
(
util
::
strieq
(
kv
.
first
,
build_headers
[
i
].
first
))
{
build_headers
[
i
].
second
=
kv
.
second
;
if
(
util
::
strieq
(
kv
.
first
,
build_headers
[
i
].
name
))
{
build_headers
[
i
].
value
=
kv
.
second
;
break
;
}
}
if
(
i
<
num_initial_headers
)
{
continue
;
}
build_headers
.
push_back
(
kv
);
build_headers
.
emplace_back
(
kv
.
first
,
kv
.
second
);
}
std
::
stable_sort
(
std
::
begin
(
build_headers
),
std
::
end
(
build_headers
),
[](
const
std
::
pair
<
std
::
string
,
std
::
string
>
&
lhs
,
const
std
::
pair
<
std
::
string
,
std
::
string
>
&
rhs
)
[](
const
Headers
::
value_type
&
lhs
,
const
Headers
::
value_type
&
rhs
)
{
return
lhs
.
first
<
rhs
.
first
;
return
lhs
.
name
<
rhs
.
name
;
});
build_headers
=
http2
::
concat_norm_headers
(
std
::
move
(
build_headers
));
auto
nva
=
std
::
vector
<
nghttp2_nv
>
();
nva
.
reserve
(
build_headers
.
size
());
for
(
auto
&
kv
:
build_headers
)
{
nva
.
push_back
(
http2
::
make_nv
(
kv
.
first
,
kv
.
second
));
nva
.
push_back
(
http2
::
make_nv
(
kv
.
name
,
kv
.
value
,
false
));
}
auto
rv
=
nghttp2_submit_request
(
client
->
session
,
&
req
->
pri_spec
,
...
...
@@ -1157,13 +1160,13 @@ void check_response_header(nghttp2_session *session, Request* req)
{
bool
gzip
=
false
;
for
(
auto
&
nv
:
req
->
res_nva
)
{
if
(
"content-encoding"
==
nv
.
first
)
{
gzip
=
util
::
strieq
(
"gzip"
,
nv
.
second
)
||
util
::
strieq
(
"deflate"
,
nv
.
second
);
if
(
"content-encoding"
==
nv
.
name
)
{
gzip
=
util
::
strieq
(
"gzip"
,
nv
.
value
)
||
util
::
strieq
(
"deflate"
,
nv
.
value
);
continue
;
}
if
(
":status"
==
nv
.
first
)
{
req
->
status
.
assign
(
nv
.
second
);
if
(
":status"
==
nv
.
name
)
{
req
->
status
.
assign
(
nv
.
value
);
}
}
if
(
gzip
)
{
...
...
@@ -1228,7 +1231,8 @@ int on_header_callback(nghttp2_session *session,
if
(
!
req
)
{
break
;
}
http2
::
split_add_header
(
req
->
res_nva
,
name
,
namelen
,
value
,
valuelen
);
http2
::
split_add_header
(
req
->
res_nva
,
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
break
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
...
...
@@ -1237,7 +1241,8 @@ int on_header_callback(nghttp2_session *session,
if
(
!
req
)
{
break
;
}
http2
::
split_add_header
(
req
->
push_req_nva
,
name
,
namelen
,
value
,
valuelen
);
http2
::
split_add_header
(
req
->
push_req_nva
,
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
break
;
}
}
...
...
@@ -1284,20 +1289,20 @@ int on_frame_recv_callback2
}
std
::
string
scheme
,
authority
,
method
,
path
;
for
(
auto
&
nv
:
req
->
push_req_nva
)
{
if
(
nv
.
first
==
":scheme"
)
{
scheme
=
nv
.
second
;
if
(
nv
.
name
==
":scheme"
)
{
scheme
=
nv
.
value
;
continue
;
}
if
(
nv
.
first
==
":authority"
||
nv
.
first
==
"host"
)
{
authority
=
nv
.
second
;
if
(
nv
.
name
==
":authority"
||
nv
.
name
==
"host"
)
{
authority
=
nv
.
value
;
continue
;
}
if
(
nv
.
first
==
":method"
)
{
method
=
nv
.
second
;
if
(
nv
.
name
==
":method"
)
{
method
=
nv
.
value
;
continue
;
}
if
(
nv
.
first
==
":path"
)
{
path
=
nv
.
second
;
if
(
nv
.
name
==
":path"
)
{
path
=
nv
.
value
;
continue
;
}
}
...
...
src/shrpx_downstream.cc
View file @
b1edb1f3
...
...
@@ -121,8 +121,8 @@ namespace {
void
check_header_field
(
bool
*
result
,
const
Headers
::
value_type
&
item
,
const
char
*
name
,
const
char
*
value
)
{
if
(
util
::
strieq
(
item
.
first
.
c_str
(),
name
))
{
if
(
util
::
strifind
(
item
.
second
.
c_str
(),
value
))
{
if
(
util
::
strieq
(
item
.
name
.
c_str
(),
name
))
{
if
(
util
::
strifind
(
item
.
value
.
c_str
(),
value
))
{
*
result
=
true
;
}
}
...
...
@@ -150,8 +150,8 @@ Headers::const_iterator get_norm_header(const Headers& headers,
const
std
::
string
&
name
)
{
auto
i
=
std
::
lower_bound
(
std
::
begin
(
headers
),
std
::
end
(
headers
),
std
::
make_pai
r
(
name
,
""
),
http2
::
name_less
);
if
(
i
!=
std
::
end
(
headers
)
&&
(
*
i
).
first
==
name
)
{
Heade
r
(
name
,
""
),
http2
::
name_less
);
if
(
i
!=
std
::
end
(
headers
)
&&
(
*
i
).
name
==
name
)
{
return
i
;
}
return
std
::
end
(
headers
);
...
...
@@ -162,8 +162,8 @@ namespace {
Headers
::
iterator
get_norm_header
(
Headers
&
headers
,
const
std
::
string
&
name
)
{
auto
i
=
std
::
lower_bound
(
std
::
begin
(
headers
),
std
::
end
(
headers
),
std
::
make_pai
r
(
name
,
""
),
http2
::
name_less
);
if
(
i
!=
std
::
end
(
headers
)
&&
(
*
i
).
first
==
name
)
{
Heade
r
(
name
,
""
),
http2
::
name_less
);
if
(
i
!=
std
::
end
(
headers
)
&&
(
*
i
).
name
==
name
)
{
return
i
;
}
return
std
::
end
(
headers
);
...
...
@@ -180,12 +180,12 @@ void Downstream::assemble_request_cookie()
std
::
string
&
cookie
=
assembled_request_cookie_
;
cookie
=
""
;
for
(
auto
&
kv
:
request_headers_
)
{
if
(
util
::
strieq
(
"cookie"
,
kv
.
first
.
c_str
()))
{
auto
end
=
kv
.
second
.
find_last_not_of
(
" ;"
);
if
(
util
::
strieq
(
"cookie"
,
kv
.
name
.
c_str
()))
{
auto
end
=
kv
.
value
.
find_last_not_of
(
" ;"
);
if
(
end
==
std
::
string
::
npos
)
{
cookie
+=
kv
.
second
;
cookie
+=
kv
.
value
;
}
else
{
cookie
.
append
(
std
::
begin
(
kv
.
second
),
std
::
begin
(
kv
.
second
)
+
end
+
1
);
cookie
.
append
(
std
::
begin
(
kv
.
value
),
std
::
begin
(
kv
.
value
)
+
end
+
1
);
}
cookie
+=
"; "
;
}
...
...
@@ -199,19 +199,19 @@ void Downstream::crumble_request_cookie()
{
Headers
cookie_hdrs
;
for
(
auto
&
kv
:
request_headers_
)
{
if
(
util
::
strieq
(
"cookie"
,
kv
.
first
.
c_str
()))
{
size_t
last
=
kv
.
second
.
size
();
if
(
util
::
strieq
(
"cookie"
,
kv
.
name
.
c_str
()))
{
size_t
last
=
kv
.
value
.
size
();
size_t
num
=
0
;
std
::
string
rep_cookie
;
for
(
size_t
j
=
0
;
j
<
last
;)
{
j
=
kv
.
second
.
find_first_not_of
(
"
\t
;"
,
j
);
j
=
kv
.
value
.
find_first_not_of
(
"
\t
;"
,
j
);
if
(
j
==
std
::
string
::
npos
)
{
break
;
}
auto
first
=
j
;
j
=
kv
.
second
.
find
(
';'
,
j
);
j
=
kv
.
value
.
find
(
';'
,
j
);
if
(
j
==
std
::
string
::
npos
)
{
j
=
last
;
}
...
...
@@ -220,15 +220,16 @@ void Downstream::crumble_request_cookie()
if
(
first
==
0
&&
j
==
last
)
{
break
;
}
rep_cookie
=
kv
.
second
.
substr
(
first
,
j
-
first
);
rep_cookie
=
kv
.
value
.
substr
(
first
,
j
-
first
);
}
else
{
cookie_hdrs
.
push_back
(
std
::
make_pair
(
"cookie"
,
kv
.
second
.
substr
(
first
,
j
-
first
)));
(
Header
(
"cookie"
,
kv
.
value
.
substr
(
first
,
j
-
first
),
kv
.
no_index
));
}
++
num
;
}
if
(
num
>
0
)
{
kv
.
second
=
std
::
move
(
rep_cookie
);
kv
.
value
=
std
::
move
(
rep_cookie
);
}
}
}
...
...
@@ -269,17 +270,19 @@ void Downstream::set_last_request_header_value(std::string value)
request_header_key_prev_
=
false
;
request_headers_sum_
+=
value
.
size
();
Headers
::
value_type
&
item
=
request_headers_
.
back
();
item
.
second
=
std
::
move
(
value
);
item
.
value
=
std
::
move
(
value
);
check_transfer_encoding_chunked
(
&
chunked_request_
,
item
);
check_expect_100_continue
(
&
request_expect_100_continue_
,
item
);
}
void
Downstream
::
split_add_request_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
)
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
)
{
request_headers_sum_
+=
namelen
+
valuelen
;
http2
::
split_add_header
(
request_headers_
,
name
,
namelen
,
value
,
valuelen
);
http2
::
split_add_header
(
request_headers_
,
name
,
namelen
,
value
,
valuelen
,
no_index
);
}
bool
Downstream
::
get_request_header_key_prev
()
const
...
...
@@ -292,7 +295,7 @@ void Downstream::append_last_request_header_key(const char *data, size_t len)
assert
(
request_header_key_prev_
);
request_headers_sum_
+=
len
;
auto
&
item
=
request_headers_
.
back
();
item
.
first
.
append
(
data
,
len
);
item
.
name
.
append
(
data
,
len
);
}
void
Downstream
::
append_last_request_header_value
(
const
char
*
data
,
size_t
len
)
...
...
@@ -300,7 +303,7 @@ void Downstream::append_last_request_header_value(const char *data, size_t len)
assert
(
!
request_header_key_prev_
);
request_headers_sum_
+=
len
;
auto
&
item
=
request_headers_
.
back
();
item
.
second
.
append
(
data
,
len
);
item
.
value
.
append
(
data
,
len
);
}
size_t
Downstream
::
get_request_headers_sum
()
const
...
...
@@ -498,14 +501,14 @@ void Downstream::rewrite_norm_location_response_header
}
http_parser_url
u
;
memset
(
&
u
,
0
,
sizeof
(
u
));
int
rv
=
http_parser_parse_url
((
*
hd
).
second
.
c_str
(),
(
*
hd
).
second
.
size
(),
int
rv
=
http_parser_parse_url
((
*
hd
).
value
.
c_str
(),
(
*
hd
).
value
.
size
(),
0
,
&
u
);
if
(
rv
!=
0
)
{
return
;
}
std
::
string
new_uri
;
if
(
!
request_http2_authority_
.
empty
())
{
new_uri
=
http2
::
rewrite_location_uri
((
*
hd
).
second
,
u
,
new_uri
=
http2
::
rewrite_location_uri
((
*
hd
).
value
,
u
,
request_http2_authority_
,
upstream_scheme
,
upstream_port
);
}
...
...
@@ -514,11 +517,11 @@ void Downstream::rewrite_norm_location_response_header
if
(
host
==
std
::
end
(
request_headers_
))
{
return
;
}
new_uri
=
http2
::
rewrite_location_uri
((
*
hd
).
second
,
u
,
(
*
host
).
second
,
new_uri
=
http2
::
rewrite_location_uri
((
*
hd
).
value
,
u
,
(
*
host
).
value
,
upstream_scheme
,
upstream_port
);
}
if
(
!
new_uri
.
empty
())
{
(
*
hd
).
second
=
std
::
move
(
new_uri
);
(
*
hd
).
value
=
std
::
move
(
new_uri
);
}
}
...
...
@@ -536,16 +539,18 @@ void Downstream::set_last_response_header_value(std::string value)
response_header_key_prev_
=
false
;
response_headers_sum_
+=
value
.
size
();
auto
&
item
=
response_headers_
.
back
();
item
.
second
=
std
::
move
(
value
);
item
.
value
=
std
::
move
(
value
);
check_transfer_encoding_chunked
(
&
chunked_response_
,
item
);
}
void
Downstream
::
split_add_response_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
)
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
)
{
response_headers_sum_
+=
namelen
+
valuelen
;
http2
::
split_add_header
(
response_headers_
,
name
,
namelen
,
value
,
valuelen
);
http2
::
split_add_header
(
response_headers_
,
name
,
namelen
,
value
,
valuelen
,
no_index
);
}
bool
Downstream
::
get_response_header_key_prev
()
const
...
...
@@ -558,7 +563,7 @@ void Downstream::append_last_response_header_key(const char *data, size_t len)
assert
(
response_header_key_prev_
);
response_headers_sum_
+=
len
;
auto
&
item
=
response_headers_
.
back
();
item
.
first
.
append
(
data
,
len
);
item
.
name
.
append
(
data
,
len
);
}
void
Downstream
::
append_last_response_header_value
(
const
char
*
data
,
...
...
@@ -567,7 +572,7 @@ void Downstream::append_last_response_header_value(const char *data,
assert
(
!
response_header_key_prev_
);
response_headers_sum_
+=
len
;
auto
&
item
=
response_headers_
.
back
();
item
.
second
.
append
(
data
,
len
);
item
.
value
.
append
(
data
,
len
);
}
size_t
Downstream
::
get_response_headers_sum
()
const
...
...
@@ -692,7 +697,7 @@ void Downstream::check_upgrade_fulfilled()
// TODO Do more strict checking for upgrade headers
if
(
response_http_status_
==
101
)
{
for
(
auto
&
hd
:
request_headers_
)
{
if
(
util
::
strieq
(
"upgrade"
,
hd
.
first
.
c_str
()))
{
if
(
util
::
strieq
(
"upgrade"
,
hd
.
name
.
c_str
()))
{
upgraded_
=
true
;
break
;
}
...
...
@@ -713,7 +718,7 @@ void Downstream::check_upgrade_request()
}
else
{
// TODO Do more strict checking for upgrade headers
for
(
auto
&
hd
:
request_headers_
)
{
if
(
util
::
strieq
(
"upgrade"
,
hd
.
first
.
c_str
()))
{
if
(
util
::
strieq
(
"upgrade"
,
hd
.
name
.
c_str
()))
{
upgrade_request_
=
true
;
break
;
}
...
...
@@ -737,12 +742,12 @@ bool Downstream::http2_upgrade_request() const
// For now just check NGHTTP2_CLEARTEXT_PROTO_VERSION_ID in
// Upgrade header field and existence of HTTP2-Settings header
// field.
if
(
util
::
strieq
(
hd
.
first
.
c_str
(),
"upgrade"
))
{
if
(
util
::
strieq
(
hd
.
second
.
c_str
(),
if
(
util
::
strieq
(
hd
.
name
.
c_str
(),
"upgrade"
))
{
if
(
util
::
strieq
(
hd
.
value
.
c_str
(),
NGHTTP2_CLEARTEXT_PROTO_VERSION_ID
))
{
upgrade_seen
=
true
;
}
}
else
if
(
util
::
strieq
(
hd
.
first
.
c_str
(),
"http2-settings"
))
{
}
else
if
(
util
::
strieq
(
hd
.
name
.
c_str
(),
"http2-settings"
))
{
http2_settings_seen
=
true
;
}
}
...
...
src/shrpx_downstream.h
View file @
b1edb1f3
...
...
@@ -103,7 +103,8 @@ public:
void
set_last_request_header_value
(
std
::
string
value
);
void
split_add_request_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
);
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
);
bool
get_request_header_key_prev
()
const
;
void
append_last_request_header_key
(
const
char
*
data
,
size_t
len
);
...
...
@@ -171,7 +172,8 @@ public:
void
set_last_response_header_value
(
std
::
string
value
);
void
split_add_response_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
);
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
);
bool
get_response_header_key_prev
()
const
;
void
append_last_response_header_key
(
const
char
*
data
,
size_t
len
);
...
...
src/shrpx_downstream_test.cc
View file @
b1edb1f3
...
...
@@ -78,13 +78,13 @@ void test_downstream_get_norm_request_header(void)
d
.
add_request_header
(
"delta"
,
"4"
);
d
.
add_request_header
(
"echo"
,
"5"
);
auto
i
=
d
.
get_norm_request_header
(
"alpha"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"alpha"
),
std
::
string
(
"0"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"alpha"
,
"0"
)
==
*
i
);
i
=
d
.
get_norm_request_header
(
"bravo"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"bravo"
),
std
::
string
(
"1"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"bravo"
,
"1"
)
==
*
i
);
i
=
d
.
get_norm_request_header
(
"delta"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"delta"
),
std
::
string
(
"4"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"delta"
,
"4"
)
==
*
i
);
i
=
d
.
get_norm_request_header
(
"echo"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"echo"
),
std
::
string
(
"5"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"echo"
,
"5"
)
==
*
i
);
i
=
d
.
get_norm_request_header
(
"foxtrot"
);
CU_ASSERT
(
i
==
std
::
end
(
d
.
get_request_headers
()));
}
...
...
@@ -99,13 +99,13 @@ void test_downstream_get_norm_response_header(void)
d
.
add_response_header
(
"delta"
,
"4"
);
d
.
add_response_header
(
"echo"
,
"5"
);
auto
i
=
d
.
get_norm_response_header
(
"alpha"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"alpha"
),
std
::
string
(
"0"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"alpha"
,
"0"
)
==
*
i
);
i
=
d
.
get_norm_response_header
(
"bravo"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"bravo"
),
std
::
string
(
"1"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"bravo"
,
"1"
)
==
*
i
);
i
=
d
.
get_norm_response_header
(
"delta"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"delta"
),
std
::
string
(
"4"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"delta"
,
"4"
)
==
*
i
);
i
=
d
.
get_norm_response_header
(
"echo"
);
CU_ASSERT
(
std
::
make_pair
(
std
::
string
(
"echo"
),
std
::
string
(
"5"
)
)
==
*
i
);
CU_ASSERT
(
Header
(
"echo"
,
"5"
)
==
*
i
);
i
=
d
.
get_norm_response_header
(
"foxtrot"
);
CU_ASSERT
(
i
==
std
::
end
(
d
.
get_response_headers
()));
}
...
...
@@ -120,13 +120,13 @@ void test_downstream_crumble_request_cookie(void)
d
.
add_request_header
(
"cookie"
,
"echo"
);
d
.
crumble_request_cookie
();
Headers
ans
=
{
std
::
make_pair
(
":method"
,
"get"
)
,
std
::
make_pair
(
":path"
,
"/"
)
,
std
::
make_pair
(
"cookie"
,
"alpha"
)
,
std
::
make_pair
(
"cookie"
,
"delta"
)
,
std
::
make_pair
(
"cookie"
,
"echo"
)
,
std
::
make_pair
(
"cookie"
,
"bravo"
)
,
std
::
make_pair
(
"cookie"
,
"charlie"
)
{
":method"
,
"get"
}
,
{
":path"
,
"/"
}
,
{
"cookie"
,
"alpha"
}
,
{
"cookie"
,
"delta"
}
,
{
"cookie"
,
"echo"
}
,
{
"cookie"
,
"bravo"
}
,
{
"cookie"
,
"charlie"
}
};
CU_ASSERT
(
ans
==
d
.
get_request_headers
());
}
...
...
@@ -154,7 +154,7 @@ void test_downstream_rewrite_norm_location_response_header(void)
d
.
add_response_header
(
"location"
,
"http://localhost:3000/"
);
d
.
rewrite_norm_location_response_header
(
"https"
,
443
);
auto
location
=
d
.
get_norm_response_header
(
"location"
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
second
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
value
);
}
{
Downstream
d
(
nullptr
,
0
,
0
);
...
...
@@ -162,7 +162,7 @@ void test_downstream_rewrite_norm_location_response_header(void)
d
.
add_response_header
(
"location"
,
"http://localhost/"
);
d
.
rewrite_norm_location_response_header
(
"https"
,
443
);
auto
location
=
d
.
get_norm_response_header
(
"location"
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
second
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
value
);
}
}
...
...
src/shrpx_http2_downstream_connection.cc
View file @
b1edb1f3
...
...
@@ -356,21 +356,21 @@ int Http2DownstreamConnection::push_request_headers()
auto
transfer_encoding
=
downstream_
->
get_norm_request_header
(
"transfer-encoding"
);
if
(
transfer_encoding
!=
end_headers
&&
util
::
strieq
((
*
transfer_encoding
).
second
.
c_str
(),
"chunked"
))
{
util
::
strieq
((
*
transfer_encoding
).
value
.
c_str
(),
"chunked"
))
{
chunked_encoding
=
true
;
}
auto
xff
=
downstream_
->
get_norm_request_header
(
"x-forwarded-for"
);
if
(
get_config
()
->
add_x_forwarded_for
)
{
if
(
xff
!=
end_headers
)
{
xff_value
=
(
*
xff
).
second
;
xff_value
=
(
*
xff
).
value
;
xff_value
+=
", "
;
}
xff_value
+=
downstream_
->
get_upstream
()
->
get_client_handler
()
->
get_ipaddr
();
nva
.
push_back
(
http2
::
make_nv_ls
(
"x-forwarded-for"
,
xff_value
));
}
else
if
(
xff
!=
end_headers
)
{
nva
.
push_back
(
http2
::
make_nv_ls
(
"x-forwarded-for"
,
(
*
xff
).
second
));
nva
.
push_back
(
http2
::
make_nv_ls
(
"x-forwarded-for"
,
(
*
xff
).
value
));
}
if
(
downstream_
->
get_request_method
()
!=
"CONNECT"
)
{
...
...
@@ -389,11 +389,11 @@ int Http2DownstreamConnection::push_request_headers()
auto
via
=
downstream_
->
get_norm_request_header
(
"via"
);
if
(
get_config
()
->
no_via
)
{
if
(
via
!=
end_headers
)
{
nva
.
push_back
(
http2
::
make_nv_ls
(
"via"
,
(
*
via
).
second
));
nva
.
push_back
(
http2
::
make_nv_ls
(
"via"
,
(
*
via
).
value
));
}
}
else
{
if
(
via
!=
end_headers
)
{
via_value
=
(
*
via
).
second
;
via_value
=
(
*
via
).
value
;
via_value
+=
", "
;
}
via_value
+=
http
::
create_via_header_value
...
...
src/shrpx_http2_session.cc
View file @
b1edb1f3
...
...
@@ -814,7 +814,8 @@ int on_header_callback(nghttp2_session *session,
if
(
!
http2
::
check_nv
(
name
,
namelen
,
value
,
valuelen
))
{
return
0
;
}
downstream
->
split_add_response_header
(
name
,
namelen
,
value
,
valuelen
);
downstream
->
split_add_response_header
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
return
0
;
}
}
// namespace
...
...
@@ -886,7 +887,7 @@ int on_response_headers(Http2Session *http2session,
call_downstream_readcb
(
http2session
,
downstream
);
return
0
;
}
downstream
->
set_response_http_status
(
strtoul
(
status
->
second
.
c_str
(),
downstream
->
set_response_http_status
(
strtoul
(
status
->
value
.
c_str
(),
nullptr
,
10
));
downstream
->
set_response_major
(
2
);
downstream
->
set_response_minor
(
0
);
...
...
@@ -916,7 +917,7 @@ int on_response_headers(Http2Session *http2session,
if
(
LOG_ENABLED
(
INFO
))
{
std
::
stringstream
ss
;
for
(
auto
&
nv
:
nva
)
{
ss
<<
TTY_HTTP_HD
<<
nv
.
first
<<
TTY_RST
<<
": "
<<
nv
.
second
<<
"
\n
"
;
ss
<<
TTY_HTTP_HD
<<
nv
.
name
<<
TTY_RST
<<
": "
<<
nv
.
value
<<
"
\n
"
;
}
SSLOG
(
INFO
,
http2session
)
<<
"HTTP response headers. stream_id="
<<
frame
->
hd
.
stream_id
...
...
src/shrpx_http2_upstream.cc
View file @
b1edb1f3
...
...
@@ -101,8 +101,8 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
std
::
string
settings_payload
;
auto
downstream
=
http
->
get_downstream
();
for
(
auto
&
hd
:
downstream
->
get_request_headers
())
{
if
(
util
::
strieq
(
hd
.
first
.
c_str
(),
"http2-settings"
))
{
auto
val
=
hd
.
second
;
if
(
util
::
strieq
(
hd
.
name
.
c_str
(),
"http2-settings"
))
{
auto
val
=
hd
.
value
;
util
::
to_base64
(
val
);
settings_payload
=
base64
::
decode
(
std
::
begin
(
val
),
std
::
end
(
val
));
break
;
...
...
@@ -205,7 +205,8 @@ int on_header_callback(nghttp2_session *session,
if
(
!
http2
::
check_nv
(
name
,
namelen
,
value
,
valuelen
))
{
return
0
;
}
downstream
->
split_add_request_header
(
name
,
namelen
,
value
,
valuelen
);
downstream
->
split_add_request_header
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
);
return
0
;
}
}
// namespace
...
...
@@ -259,7 +260,7 @@ int on_request_headers(Http2Upstream *upstream,
if
(
LOG_ENABLED
(
INFO
))
{
std
::
stringstream
ss
;
for
(
auto
&
nv
:
nva
)
{
ss
<<
TTY_HTTP_HD
<<
nv
.
first
<<
TTY_RST
<<
": "
<<
nv
.
second
<<
"
\n
"
;
ss
<<
TTY_HTTP_HD
<<
nv
.
name
<<
TTY_RST
<<
": "
<<
nv
.
value
<<
"
\n
"
;
}
ULOG
(
INFO
,
upstream
)
<<
"HTTP request headers. stream_id="
<<
downstream
->
get_stream_id
()
...
...
@@ -280,7 +281,7 @@ int on_request_headers(Http2Upstream *upstream,
auto
path
=
http2
::
get_unique_header
(
nva
,
":path"
);
auto
method
=
http2
::
get_unique_header
(
nva
,
":method"
);
auto
scheme
=
http2
::
get_unique_header
(
nva
,
":scheme"
);
bool
is_connect
=
method
&&
"CONNECT"
==
method
->
second
;
bool
is_connect
=
method
&&
"CONNECT"
==
method
->
value
;
bool
having_host
=
http2
::
non_empty_value
(
host
);
bool
having_authority
=
http2
::
non_empty_value
(
authority
);
...
...
@@ -1014,11 +1015,11 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream)
auto
via
=
downstream
->
get_norm_response_header
(
"via"
);
if
(
get_config
()
->
no_via
)
{
if
(
via
!=
end_headers
)
{
nva
.
push_back
(
http2
::
make_nv_ls
(
"via"
,
(
*
via
).
second
));
nva
.
push_back
(
http2
::
make_nv_ls
(
"via"
,
(
*
via
).
value
));
}
}
else
{
if
(
via
!=
end_headers
)
{
via_value
=
(
*
via
).
second
;
via_value
=
(
*
via
).
value
;
via_value
+=
", "
;
}
via_value
+=
http
::
create_via_header_value
...
...
src/shrpx_http_downstream_connection.cc
View file @
b1edb1f3
...
...
@@ -171,16 +171,16 @@ int HttpDownstreamConnection::push_request_headers()
if
(
get_config
()
->
add_x_forwarded_for
)
{
hdrs
+=
"X-Forwarded-For: "
;
if
(
xff
!=
end_headers
)
{
hdrs
+=
(
*
xff
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
xff
).
second
.
size
());
hdrs
+=
(
*
xff
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
xff
).
value
.
size
());
hdrs
+=
", "
;
}
hdrs
+=
client_handler_
->
get_ipaddr
();
hdrs
+=
"
\r\n
"
;
}
else
if
(
xff
!=
end_headers
)
{
hdrs
+=
"X-Forwarded-For: "
;
hdrs
+=
(
*
xff
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
xff
).
second
.
size
());
hdrs
+=
(
*
xff
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
xff
).
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
if
(
downstream_
->
get_request_method
()
!=
"CONNECT"
)
{
...
...
@@ -196,25 +196,25 @@ int HttpDownstreamConnection::push_request_headers()
}
auto
expect
=
downstream_
->
get_norm_request_header
(
"expect"
);
if
(
expect
!=
end_headers
&&
!
util
::
strifind
((
*
expect
).
second
.
c_str
(),
"100-continue"
))
{
!
util
::
strifind
((
*
expect
).
value
.
c_str
(),
"100-continue"
))
{
hdrs
+=
"Expect: "
;
hdrs
+=
(
*
expect
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
expect
).
second
.
size
());
hdrs
+=
(
*
expect
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
expect
).
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
auto
via
=
downstream_
->
get_norm_request_header
(
"via"
);
if
(
get_config
()
->
no_via
)
{
if
(
via
!=
end_headers
)
{
hdrs
+=
"Via: "
;
hdrs
+=
(
*
via
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
second
.
size
());
hdrs
+=
(
*
via
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
}
else
{
hdrs
+=
"Via: "
;
if
(
via
!=
end_headers
)
{
hdrs
+=
(
*
via
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
second
.
size
());
hdrs
+=
(
*
via
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
value
.
size
());
hdrs
+=
", "
;
}
hdrs
+=
http
::
create_via_header_value
(
downstream_
->
get_request_major
(),
...
...
src/shrpx_https_upstream.cc
View file @
b1edb1f3
...
...
@@ -159,8 +159,8 @@ int htp_hdrs_completecb(http_parser *htp)
<<
downstream
->
get_request_minor
()
<<
"
\n
"
;
const
auto
&
headers
=
downstream
->
get_request_headers
();
for
(
size_t
i
=
0
;
i
<
headers
.
size
();
++
i
)
{
ss
<<
TTY_HTTP_HD
<<
headers
[
i
].
first
<<
TTY_RST
<<
": "
<<
headers
[
i
].
second
<<
"
\n
"
;
ss
<<
TTY_HTTP_HD
<<
headers
[
i
].
name
<<
TTY_RST
<<
": "
<<
headers
[
i
].
value
<<
"
\n
"
;
}
ULOG
(
INFO
,
upstream
)
<<
"HTTP request headers
\n
"
<<
ss
.
str
();
}
...
...
@@ -682,15 +682,15 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
if
(
get_config
()
->
no_via
)
{
if
(
via
!=
end_headers
)
{
hdrs
+=
"Via: "
;
hdrs
+=
(
*
via
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
second
.
size
());
hdrs
+=
(
*
via
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
value
.
size
());
hdrs
+=
"
\r\n
"
;
}
}
else
{
hdrs
+=
"Via: "
;
if
(
via
!=
end_headers
)
{
hdrs
+=
(
*
via
).
second
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
second
.
size
());
hdrs
+=
(
*
via
).
value
;
http2
::
sanitize_header_value
(
hdrs
,
hdrs
.
size
()
-
(
*
via
).
value
.
size
());
hdrs
+=
", "
;
}
hdrs
+=
http
::
create_via_header_value
...
...
src/shrpx_spdy_upstream.cc
View file @
b1edb1f3
...
...
@@ -864,18 +864,18 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream)
nv
[
hdidx
++
]
=
":version"
;
nv
[
hdidx
++
]
=
"HTTP/1.1"
;
for
(
auto
&
hd
:
downstream
->
get_response_headers
())
{
if
(
hd
.
first
.
empty
()
||
hd
.
first
.
c_str
()[
0
]
==
':'
||
util
::
strieq
(
hd
.
first
.
c_str
(),
"transfer-encoding"
)
||
util
::
strieq
(
hd
.
first
.
c_str
(),
"keep-alive"
)
||
// HTTP/1.0?
util
::
strieq
(
hd
.
first
.
c_str
(),
"connection"
)
||
util
::
strieq
(
hd
.
first
.
c_str
(),
"proxy-connection"
))
{
if
(
hd
.
name
.
empty
()
||
hd
.
name
.
c_str
()[
0
]
==
':'
||
util
::
strieq
(
hd
.
name
.
c_str
(),
"transfer-encoding"
)
||
util
::
strieq
(
hd
.
name
.
c_str
(),
"keep-alive"
)
||
// HTTP/1.0?
util
::
strieq
(
hd
.
name
.
c_str
(),
"connection"
)
||
util
::
strieq
(
hd
.
name
.
c_str
(),
"proxy-connection"
))
{
// These are ignored
}
else
if
(
!
get_config
()
->
no_via
&&
util
::
strieq
(
hd
.
first
.
c_str
(),
"via"
))
{
via_value
=
hd
.
second
;
util
::
strieq
(
hd
.
name
.
c_str
(),
"via"
))
{
via_value
=
hd
.
value
;
}
else
{
nv
[
hdidx
++
]
=
hd
.
first
.
c_str
();
nv
[
hdidx
++
]
=
hd
.
second
.
c_str
();
nv
[
hdidx
++
]
=
hd
.
name
.
c_str
();
nv
[
hdidx
++
]
=
hd
.
value
.
c_str
();
}
}
if
(
!
get_config
()
->
no_via
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment