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
3b8889a2
Commit
3b8889a2
authored
Jan 14, 2016
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttpx: Extract response related fields to Response struct
parent
a7fd37ff
Changes
13
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
246 additions
and
511 deletions
+246
-511
src/shrpx-unittest.cc
src/shrpx-unittest.cc
+4
-8
src/shrpx_client_handler.cc
src/shrpx_client_handler.cc
+2
-2
src/shrpx_downstream.cc
src/shrpx_downstream.cc
+29
-235
src/shrpx_downstream.h
src/shrpx_downstream.h
+21
-71
src/shrpx_downstream_test.cc
src/shrpx_downstream_test.cc
+30
-54
src/shrpx_downstream_test.h
src/shrpx_downstream_test.h
+2
-4
src/shrpx_http2_session.cc
src/shrpx_http2_session.cc
+19
-19
src/shrpx_http2_upstream.cc
src/shrpx_http2_upstream.cc
+30
-24
src/shrpx_http_downstream_connection.cc
src/shrpx_http_downstream_connection.cc
+24
-26
src/shrpx_https_upstream.cc
src/shrpx_https_upstream.cc
+32
-27
src/shrpx_mruby.cc
src/shrpx_mruby.cc
+1
-1
src/shrpx_mruby_module_response.cc
src/shrpx_mruby_module_response.cc
+29
-24
src/shrpx_spdy_upstream.cc
src/shrpx_spdy_upstream.cc
+23
-16
No files found.
src/shrpx-unittest.cc
View file @
3b8889a2
...
...
@@ -101,14 +101,10 @@ int main(int argc, char *argv[]) {
shrpx
::
test_http2_get_pure_path_component
)
||
!
CU_add_test
(
pSuite
,
"http2_construct_push_component"
,
shrpx
::
test_http2_construct_push_component
)
||
!
CU_add_test
(
pSuite
,
"downstream_index_request_headers"
,
shrpx
::
test_downstream_index_request_headers
)
||
!
CU_add_test
(
pSuite
,
"downstream_index_response_headers"
,
shrpx
::
test_downstream_index_response_headers
)
||
!
CU_add_test
(
pSuite
,
"downstream_get_request_header"
,
shrpx
::
test_downstream_get_request_header
)
||
!
CU_add_test
(
pSuite
,
"downstream_get_response_header"
,
shrpx
::
test_downstream_get_response_header
)
||
!
CU_add_test
(
pSuite
,
"downstream_field_store_index_headers"
,
shrpx
::
test_downstream_field_store_index_headers
)
||
!
CU_add_test
(
pSuite
,
"downstream_field_store_header"
,
shrpx
::
test_downstream_field_store_header
)
||
!
CU_add_test
(
pSuite
,
"downstream_crumble_request_cookie"
,
shrpx
::
test_downstream_crumble_request_cookie
)
||
!
CU_add_test
(
pSuite
,
"downstream_assemble_request_cookie"
,
...
...
src/shrpx_client_handler.cc
View file @
3b8889a2
...
...
@@ -812,6 +812,7 @@ std::string construct_absolute_request_uri(const Request &req) {
void
ClientHandler
::
write_accesslog
(
Downstream
*
downstream
)
{
nghttp2
::
ssl
::
TLSSessionInfo
tls_info
;
const
auto
&
req
=
downstream
->
request
();
const
auto
&
resp
=
downstream
->
response
();
upstream_accesslog
(
get_config
()
->
accesslog_format
,
...
...
@@ -832,8 +833,7 @@ void ClientHandler::write_accesslog(Downstream *downstream) {
downstream
->
get_request_start_time
(),
// request_start_time
std
::
chrono
::
high_resolution_clock
::
now
(),
// request_end_time
req
.
http_major
,
req
.
http_minor
,
downstream
->
get_response_http_status
(),
req
.
http_major
,
req
.
http_minor
,
resp
.
http_status
,
downstream
->
get_response_sent_bodylen
(),
port_
.
c_str
(),
get_config
()
->
port
,
get_config
()
->
pid
,
});
...
...
src/shrpx_downstream.cc
View file @
3b8889a2
This diff is collapsed.
Click to expand it.
src/shrpx_downstream.h
View file @
3b8889a2
...
...
@@ -73,6 +73,7 @@ public:
// the beginning. If no such header is found, returns nullptr.
// This function must be called after headers are indexed
const
Headers
::
value_type
*
header
(
int16_t
token
)
const
;
Headers
::
value_type
*
header
(
int16_t
token
);
// Returns pointer to the header field with the name |name|. If no
// such header is found, returns nullptr.
const
Headers
::
value_type
*
header
(
const
std
::
string
&
name
)
const
;
...
...
@@ -156,6 +157,18 @@ struct Request {
bool
http2_expect_body
;
};
struct
Response
{
Response
()
:
fs
(
32
),
http_status
(
0
),
http_major
(
1
),
http_minor
(
1
),
connection_close
(
false
)
{}
FieldStore
fs
;
// HTTP status code
unsigned
int
http_status
;
int
http_major
,
http_minor
;
bool
connection_close
;
};
class
Downstream
{
public:
Downstream
(
Upstream
*
upstream
,
MemchunkPool
*
mcpool
,
int32_t
stream_id
,
...
...
@@ -251,58 +264,17 @@ public:
bool
get_request_pending
()
const
;
// Returns true if request is ready to be submitted to downstream.
bool
request_submission_ready
()
const
;
// downstream response API
const
Headers
&
get_response_headers
()
const
;
Headers
&
get_response_headers
();
// Lower the response header field names and indexes response
// headers. If there are invalid headers (e.g., multiple
// Content-Length with different values), returns -1.
int
index_response_headers
();
// Returns pointer to the response header with the name |name|. If
// multiple header have |name| as name, return last occurrence from
// the beginning. If no such header is found, returns nullptr.
// This function must be called after response headers are indexed.
const
Headers
::
value_type
*
get_response_header
(
int16_t
token
)
const
;
Headers
::
value_type
*
get_response_header
(
int16_t
token
);
const
Response
&
response
()
const
{
return
resp_
;
}
Response
&
response
()
{
return
resp_
;
}
// Rewrites the location response header field.
void
rewrite_location_response_header
(
const
std
::
string
&
upstream_scheme
);
void
add_response_header
(
std
::
string
name
,
std
::
string
value
);
void
set_last_response_header_value
(
const
char
*
data
,
size_t
len
);
void
add_response_header
(
std
::
string
name
,
std
::
string
value
,
int16_t
token
);
void
add_response_header
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
,
int16_t
token
);
bool
get_response_header_key_prev
()
const
;
void
append_last_response_header_key
(
const
char
*
data
,
size_t
len
);
void
append_last_response_header_value
(
const
char
*
data
,
size_t
len
);
// Empties response headers.
void
clear_response_headers
();
size_t
get_response_headers_sum
()
const
;
const
Headers
&
get_response_trailers
()
const
;
void
add_response_trailer
(
const
uint8_t
*
name
,
size_t
namelen
,
const
uint8_t
*
value
,
size_t
valuelen
,
bool
no_index
,
int16_t
token
);
void
add_response_trailer
(
std
::
string
name
,
std
::
string
value
);
void
set_last_response_trailer_value
(
const
char
*
data
,
size_t
len
);
bool
get_response_trailer_key_prev
()
const
;
void
append_last_response_trailer_key
(
const
char
*
data
,
size_t
len
);
void
append_last_response_trailer_value
(
const
char
*
data
,
size_t
len
);
unsigned
int
get_response_http_status
()
const
;
void
set_response_http_status
(
unsigned
int
status
);
void
set_response_major
(
int
major
);
void
set_response_minor
(
int
minor
);
int
get_response_major
()
const
;
int
get_response_minor
()
const
;
int
get_response_version
()
const
;
bool
get_chunked_response
()
const
;
void
set_chunked_response
(
bool
f
);
bool
get_response_connection_close
()
const
;
void
set_response_connection_close
(
bool
f
);
void
set_response_state
(
int
state
);
int
get_response_state
()
const
;
DefaultMemchunks
*
get_response_buf
();
...
...
@@ -311,8 +283,6 @@ public:
int64_t
get_response_bodylen
()
const
;
void
add_response_sent_bodylen
(
size_t
amount
);
int64_t
get_response_sent_bodylen
()
const
;
int64_t
get_response_content_length
()
const
;
void
set_response_content_length
(
int64_t
len
);
// Validates that received response body length and content-length
// matches.
bool
validate_response_bodylen
()
const
;
...
...
@@ -331,7 +301,6 @@ public:
void
dec_response_datalen
(
size_t
len
);
size_t
get_response_datalen
()
const
;
void
reset_response_datalen
();
bool
response_pseudo_header_allowed
(
int16_t
token
)
const
;
// Call this method when there is incoming data in downstream
// connection.
...
...
@@ -402,12 +371,7 @@ public:
private:
Request
req_
;
Headers
response_headers_
;
// trailer part. For HTTP/1.1, trailer part is only included with
// chunked encoding. For HTTP/2, there is no such limit.
Headers
response_trailers_
;
Response
resp_
;
std
::
chrono
::
high_resolution_clock
::
time_point
request_start_time_
;
...
...
@@ -434,17 +398,12 @@ private:
// the length of response body sent to upstream client
int64_t
response_sent_bodylen_
;
// content-length of response body, -1 if it is unknown.
int64_t
response_content_length_
;
Upstream
*
upstream_
;
std
::
unique_ptr
<
DownstreamConnection
>
dconn_
;
// only used by HTTP/2 or SPDY upstream
BlockedLink
*
blocked_link_
;
size_t
response_headers_sum_
;
// The number of bytes not consumed by the application yet.
size_t
request_datalen_
;
size_t
response_datalen_
;
...
...
@@ -460,26 +419,17 @@ private:
uint32_t
response_rst_stream_error_code_
;
int
request_state_
;
int
response_state_
;
unsigned
int
response_http_status_
;
int
response_major_
;
int
response_minor_
;
// only used by HTTP/2 or SPDY upstream
int
dispatch_state_
;
http2
::
HeaderIndex
response_hdidx_
;
// true if the connection is upgraded (HTTP Upgrade or CONNECT)
bool
upgraded_
;
bool
chunked_request_
;
bool
chunked_response_
;
bool
response_connection_close_
;
bool
response_header_key_prev_
;
bool
response_trailer_key_prev_
;
bool
expect_final_response_
;
// true if downstream request is pending because backend connection
// has not been established or should be checked before use;
...
...
src/shrpx_downstream_test.cc
View file @
3b8889a2
...
...
@@ -32,17 +32,17 @@
namespace
shrpx
{
void
test_downstream_
index_request
_headers
(
void
)
{
Request
req
;
req
.
fs
.
add_header
(
"1"
,
"0"
);
req
.
fs
.
add_header
(
"2"
,
"1"
);
req
.
fs
.
add_header
(
"Charlie"
,
"2"
);
req
.
fs
.
add_header
(
"Alpha"
,
"3"
);
req
.
fs
.
add_header
(
"Delta"
,
"4"
);
req
.
fs
.
add_header
(
"BravO"
,
"5"
);
req
.
fs
.
add_header
(
":method"
,
"6"
);
req
.
fs
.
add_header
(
":authority"
,
"7"
);
req
.
fs
.
index_headers
();
void
test_downstream_
field_store_index
_headers
(
void
)
{
FieldStore
fs
(
0
)
;
fs
.
add_header
(
"1"
,
"0"
);
fs
.
add_header
(
"2"
,
"1"
);
fs
.
add_header
(
"Charlie"
,
"2"
);
fs
.
add_header
(
"Alpha"
,
"3"
);
fs
.
add_header
(
"Delta"
,
"4"
);
fs
.
add_header
(
"BravO"
,
"5"
);
fs
.
add_header
(
":method"
,
"6"
);
fs
.
add_header
(
":authority"
,
"7"
);
fs
.
index_headers
();
auto
ans
=
Headers
{{
"1"
,
"0"
},
{
"2"
,
"1"
},
...
...
@@ -52,49 +52,23 @@ void test_downstream_index_request_headers(void) {
{
"bravo"
,
"5"
},
{
":method"
,
"6"
},
{
":authority"
,
"7"
}};
CU_ASSERT
(
ans
==
req
.
fs
.
headers
());
CU_ASSERT
(
ans
==
fs
.
headers
());
}
void
test_downstream_index_response_headers
(
void
)
{
Downstream
d
(
nullptr
,
nullptr
,
0
,
0
);
d
.
add_response_header
(
"Charlie"
,
"0"
);
d
.
add_response_header
(
"Alpha"
,
"1"
);
d
.
add_response_header
(
"Delta"
,
"2"
);
d
.
add_response_header
(
"BravO"
,
"3"
);
d
.
index_response_headers
();
auto
ans
=
Headers
{{
"charlie"
,
"0"
},
{
"alpha"
,
"1"
},
{
"delta"
,
"2"
},
{
"bravo"
,
"3"
}};
CU_ASSERT
(
ans
==
d
.
get_response_headers
());
}
void
test_downstream_get_request_header
(
void
)
{
Request
req
;
req
.
fs
.
add_header
(
"alpha"
,
"0"
);
req
.
fs
.
add_header
(
":authority"
,
"1"
);
req
.
fs
.
add_header
(
"content-length"
,
"2"
);
req
.
fs
.
index_headers
();
void
test_downstream_field_store_header
(
void
)
{
FieldStore
fs
(
0
);
fs
.
add_header
(
"alpha"
,
"0"
);
fs
.
add_header
(
":authority"
,
"1"
);
fs
.
add_header
(
"content-length"
,
"2"
);
fs
.
index_headers
();
// By token
CU_ASSERT
(
Header
(
":authority"
,
"1"
)
==
*
req
.
fs
.
header
(
http2
::
HD__AUTHORITY
));
CU_ASSERT
(
nullptr
==
req
.
fs
.
header
(
http2
::
HD__METHOD
));
CU_ASSERT
(
Header
(
":authority"
,
"1"
)
==
*
fs
.
header
(
http2
::
HD__AUTHORITY
));
CU_ASSERT
(
nullptr
==
fs
.
header
(
http2
::
HD__METHOD
));
// By name
CU_ASSERT
(
Header
(
"alpha"
,
"0"
)
==
*
req
.
fs
.
header
(
"alpha"
));
CU_ASSERT
(
nullptr
==
req
.
fs
.
header
(
"bravo"
));
}
void
test_downstream_get_response_header
(
void
)
{
Downstream
d
(
nullptr
,
nullptr
,
0
,
0
);
d
.
add_response_header
(
"alpha"
,
"0"
);
d
.
add_response_header
(
":status"
,
"1"
);
d
.
add_response_header
(
"content-length"
,
"2"
);
d
.
index_response_headers
();
// By token
CU_ASSERT
(
Header
(
":status"
,
"1"
)
==
*
d
.
get_response_header
(
http2
::
HD__STATUS
));
CU_ASSERT
(
nullptr
==
d
.
get_response_header
(
http2
::
HD__METHOD
));
CU_ASSERT
(
Header
(
"alpha"
,
"0"
)
==
*
fs
.
header
(
"alpha"
));
CU_ASSERT
(
nullptr
==
fs
.
header
(
"bravo"
));
}
void
test_downstream_crumble_request_cookie
(
void
)
{
...
...
@@ -154,24 +128,26 @@ void test_downstream_rewrite_location_response_header(void) {
{
Downstream
d
(
nullptr
,
nullptr
,
0
,
0
);
auto
&
req
=
d
.
request
();
auto
&
resp
=
d
.
response
();
d
.
set_request_downstream_host
(
"localhost:3000"
);
req
.
fs
.
add_header
(
"host"
,
"localhost"
);
d
.
add_response
_header
(
"location"
,
"http://localhost:3000/"
);
resp
.
fs
.
add
_header
(
"location"
,
"http://localhost:3000/"
);
req
.
fs
.
index_headers
();
d
.
index_response
_headers
();
resp
.
fs
.
index
_headers
();
d
.
rewrite_location_response_header
(
"https"
);
auto
location
=
d
.
get_response_
header
(
http2
::
HD_LOCATION
);
auto
location
=
resp
.
fs
.
header
(
http2
::
HD_LOCATION
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
value
);
}
{
Downstream
d
(
nullptr
,
nullptr
,
0
,
0
);
auto
&
req
=
d
.
request
();
auto
&
resp
=
d
.
response
();
d
.
set_request_downstream_host
(
"localhost"
);
req
.
authority
=
"localhost"
;
d
.
add_response
_header
(
"location"
,
"http://localhost:3000/"
);
d
.
index_response
_headers
();
resp
.
fs
.
add
_header
(
"location"
,
"http://localhost:3000/"
);
resp
.
fs
.
index
_headers
();
d
.
rewrite_location_response_header
(
"https"
);
auto
location
=
d
.
get_response_
header
(
http2
::
HD_LOCATION
);
auto
location
=
resp
.
fs
.
header
(
http2
::
HD_LOCATION
);
CU_ASSERT
(
"https://localhost/"
==
(
*
location
).
value
);
}
}
...
...
src/shrpx_downstream_test.h
View file @
3b8889a2
...
...
@@ -31,10 +31,8 @@
namespace
shrpx
{
void
test_downstream_index_request_headers
(
void
);
void
test_downstream_index_response_headers
(
void
);
void
test_downstream_get_request_header
(
void
);
void
test_downstream_get_response_header
(
void
);
void
test_downstream_field_store_index_headers
(
void
);
void
test_downstream_field_store_header
(
void
);
void
test_downstream_crumble_request_cookie
(
void
);
void
test_downstream_assemble_request_cookie
(
void
);
void
test_downstream_rewrite_location_response_header
(
void
);
...
...
src/shrpx_http2_session.cc
View file @
3b8889a2
...
...
@@ -752,6 +752,8 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
return
0
;
}
auto
&
resp
=
downstream
->
response
();
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_HEADERS
:
{
auto
trailer
=
frame
->
headers
.
cat
==
NGHTTP2_HCAT_HEADERS
&&
...
...
@@ -759,15 +761,15 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
if
(
trailer
)
{
// just store header fields for trailer part
downstream
->
add_response
_trailer
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
,
-
1
);
resp
.
fs
.
add
_trailer
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
,
-
1
);
return
0
;
}
auto
token
=
http2
::
lookup_token
(
name
,
namelen
);
downstream
->
add_response
_header
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
,
token
);
resp
.
fs
.
add
_header
(
name
,
namelen
,
value
,
valuelen
,
flags
&
NGHTTP2_NV_FLAG_NO_INDEX
,
token
);
return
0
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
...
...
@@ -857,18 +859,19 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream,
auto
upstream
=
downstream
->
get_upstream
();
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
auto
&
nva
=
downstream
->
get_response_
headers
();
auto
&
nva
=
resp
.
fs
.
headers
();
downstream
->
set_expect_final_response
(
false
);
auto
status
=
downstream
->
get_response_
header
(
http2
::
HD__STATUS
);
auto
status
=
resp
.
fs
.
header
(
http2
::
HD__STATUS
);
// libnghttp2 guarantees this exists and can be parsed
auto
status_code
=
http2
::
parse_http_status_code
(
status
->
value
);
downstream
->
set_response_http_status
(
status_code
)
;
downstream
->
set_response_major
(
2
)
;
downstream
->
set_response_minor
(
0
)
;
resp
.
http_status
=
status_code
;
resp
.
http_major
=
2
;
resp
.
http_minor
=
0
;
if
(
LOG_ENABLED
(
INFO
))
{
std
::
stringstream
ss
;
...
...
@@ -904,7 +907,7 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream,
downstream
->
check_upgrade_fulfilled
();
if
(
downstream
->
get_upgraded
())
{
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
// On upgrade sucess, both ends can send data
if
(
upstream
->
resume_read
(
SHRPX_NO_BUFFER
,
downstream
,
0
)
!=
0
)
{
// If resume_read fails, just drop connection. Not ideal.
...
...
@@ -917,27 +920,24 @@ int on_response_headers(Http2Session *http2session, Downstream *downstream,
<<
"HTTP upgrade success. stream_id="
<<
frame
->
hd
.
stream_id
;
}
}
else
{
auto
content_length
=
downstream
->
get_response_header
(
http2
::
HD_CONTENT_LENGTH
);
auto
content_length
=
resp
.
fs
.
header
(
http2
::
HD_CONTENT_LENGTH
);
if
(
content_length
)
{
// libnghttp2 guarantees this can be parsed
auto
len
=
util
::
parse_uint
(
content_length
->
value
);
downstream
->
set_response_content_length
(
len
);
resp
.
fs
.
content_length
=
util
::
parse_uint
(
content_length
->
value
);
}
if
(
downstream
->
get_response_content_length
()
==
-
1
&&
downstream
->
expect_response_body
())
{
if
(
resp
.
fs
.
content_length
==
-
1
&&
downstream
->
expect_response_body
())
{
// Here we have response body but Content-Length is not known in
// advance.
if
(
req
.
http_major
<=
0
||
(
req
.
http_major
==
1
&&
req
.
http_minor
==
0
))
{
// We simply close connection for pre-HTTP/1.1 in this case.
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
}
else
{
// Otherwise, use chunked encoding to keep upstream connection
// open. In HTTP2, we are supporsed not to receive
// transfer-encoding.
downstream
->
add_response
_header
(
"transfer-encoding"
,
"chunked"
,
http2
::
HD_TRANSFER_ENCODING
);
resp
.
fs
.
add
_header
(
"transfer-encoding"
,
"chunked"
,
http2
::
HD_TRANSFER_ENCODING
);
downstream
->
set_chunked_response
(
true
);
}
}
...
...
src/shrpx_http2_upstream.cc
View file @
3b8889a2
...
...
@@ -1242,6 +1242,7 @@ ssize_t downstream_data_read_callback(nghttp2_session *session,
assert
(
body
);
auto
dconn
=
downstream
->
get_downstream_connection
();
const
auto
&
resp
=
downstream
->
response
();
if
(
body
->
rleft
()
==
0
&&
dconn
&&
downstream
->
get_response_state
()
!=
Downstream
::
MSG_COMPLETE
)
{
...
...
@@ -1263,7 +1264,7 @@ ssize_t downstream_data_read_callback(nghttp2_session *session,
*
data_flags
|=
NGHTTP2_DATA_FLAG_EOF
;
if
(
!
downstream
->
get_upgraded
())
{
auto
&
trailers
=
downstream
->
get_response_
trailers
();
const
auto
&
trailers
=
resp
.
fs
.
trailers
();
if
(
!
trailers
.
empty
())
{
std
::
vector
<
nghttp2_nv
>
nva
;
nva
.
reserve
(
trailers
.
size
());
...
...
@@ -1303,18 +1304,19 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
data_prd_ptr
=
&
data_prd
;
}
auto
&
headers
=
downstream
->
get_response_headers
();
const
auto
&
resp
=
downstream
->
response
();
const
auto
&
headers
=
resp
.
fs
.
headers
();
auto
nva
=
std
::
vector
<
nghttp2_nv
>
();
// 2 for :status and server
nva
.
reserve
(
2
+
headers
.
size
());
std
::
string
status_code_str
;
auto
response_status_const
=
http2
::
stringify_status
(
downstream
->
get_response_http_status
());
auto
response_status_const
=
http2
::
stringify_status
(
resp
.
http_status
);
if
(
response_status_const
)
{
nva
.
push_back
(
http2
::
make_nv_lc_nocopy
(
":status"
,
response_status_const
));
}
else
{
status_code_str
=
util
::
utos
(
downstream
->
get_response_http_status
()
);
status_code_str
=
util
::
utos
(
resp
.
http_status
);
nva
.
push_back
(
http2
::
make_nv_ls
(
":status"
,
status_code_str
));
}
...
...
@@ -1334,7 +1336,7 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
nva
.
push_back
(
http2
::
make_nv_nocopy
(
kv
.
name
,
kv
.
value
,
kv
.
no_index
));
}
if
(
!
downstream
->
get_response_
header
(
http2
::
HD_SERVER
))
{
if
(
!
resp
.
fs
.
header
(
http2
::
HD_SERVER
))
{
nva
.
push_back
(
http2
::
make_nv_lc_nocopy
(
"server"
,
get_config
()
->
server_name
));
}
...
...
@@ -1359,8 +1361,10 @@ int Http2Upstream::send_reply(Downstream *downstream, const uint8_t *body,
int
Http2Upstream
::
error_reply
(
Downstream
*
downstream
,
unsigned
int
status_code
)
{
int
rv
;
auto
&
resp
=
downstream
->
response
();
auto
html
=
http
::
create_error_html
(
status_code
);
downstream
->
set_response_http_status
(
status_code
)
;
resp
.
http_status
=
status_code
;
auto
body
=
downstream
->
get_response_buf
();
body
->
append
(
html
.
c_str
(),
html
.
size
());
downstream
->
set_response_state
(
Downstream
::
MSG_COMPLETE
);
...
...
@@ -1429,6 +1433,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
int
rv
;
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
if
(
LOG_ENABLED
(
INFO
))
{
if
(
downstream
->
get_non_final_response
())
{
...
...
@@ -1462,25 +1467,24 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
}
#endif // HAVE_MRUBY
size_t
nheader
=
downstream
->
get_response_headers
().
size
();
auto
nva
=
std
::
vector
<
nghttp2_nv
>
();
// 4 means :status and possible server, via and x-http2-push header
// field.
nva
.
reserve
(
nheader
+
4
+
get_config
()
->
add_response_headers
.
size
());
nva
.
reserve
(
resp
.
fs
.
headers
().
size
()
+
4
+
get_config
()
->
add_response_headers
.
size
());
std
::
string
via_value
;
std
::
string
response_status
;
auto
response_status_const
=
http2
::
stringify_status
(
downstream
->
get_response_http_status
());
auto
response_status_const
=
http2
::
stringify_status
(
resp
.
http_status
);
if
(
response_status_const
)
{
nva
.
push_back
(
http2
::
make_nv_lc_nocopy
(
":status"
,
response_status_const
));
}
else
{
response_status
=
util
::
utos
(
downstream
->
get_response_http_status
()
);
response_status
=
util
::
utos
(
resp
.
http_status
);
nva
.
push_back
(
http2
::
make_nv_ls
(
":status"
,
response_status
));
}
if
(
downstream
->
get_non_final_response
())
{
http2
::
copy_headers_to_nva
(
nva
,
downstream
->
get_response_
headers
());
http2
::
copy_headers_to_nva
(
nva
,
resp
.
fs
.
headers
());
if
(
LOG_ENABLED
(
INFO
))
{
log_response_headers
(
downstream
,
nva
);
...
...
@@ -1490,7 +1494,7 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
downstream
->
get_stream_id
(),
nullptr
,
nva
.
data
(),
nva
.
size
(),
nullptr
);
downstream
->
clear_response
_headers
();
resp
.
fs
.
clear
_headers
();
if
(
rv
!=
0
)
{
ULOG
(
FATAL
,
this
)
<<
"nghttp2_submit_headers() failed"
;
...
...
@@ -1500,19 +1504,19 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
return
0
;
}
http2
::
copy_headers_to_nva_nocopy
(
nva
,
downstream
->
get_response_
headers
());
http2
::
copy_headers_to_nva_nocopy
(
nva
,
resp
.
fs
.
headers
());
if
(
!
get_config
()
->
http2_proxy
&&
!
get_config
()
->
client_proxy
)
{
nva
.
push_back
(
http2
::
make_nv_lc_nocopy
(
"server"
,
get_config
()
->
server_name
));
}
else
{
auto
server
=
downstream
->
get_response_
header
(
http2
::
HD_SERVER
);
auto
server
=
resp
.
fs
.
header
(
http2
::
HD_SERVER
);
if
(
server
)
{
nva
.
push_back
(
http2
::
make_nv_ls_nocopy
(
"server"
,
(
*
server
).
value
));
}
}
auto
via
=
downstream
->
get_response_
header
(
http2
::
HD_VIA
);
auto
via
=
resp
.
fs
.
header
(
http2
::
HD_VIA
);
if
(
get_config
()
->
no_via
)
{
if
(
via
)
{
nva
.
push_back
(
http2
::
make_nv_ls_nocopy
(
"via"
,
(
*
via
).
value
));
...
...
@@ -1522,8 +1526,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
via_value
=
(
*
via
).
value
;
via_value
+=
", "
;
}
via_value
+=
http
::
create_via_header_value
(
downstream
->
get_response_major
(),
downstream
->
get_response_minor
()
);
via_value
+=
http
::
create_via_header_value
(
resp
.
http_major
,
resp
.
http_minor
);
nva
.
push_back
(
http2
::
make_nv_ls
(
"via"
,
via_value
));
}
...
...
@@ -1575,9 +1579,8 @@ int Http2Upstream::on_downstream_header_complete(Downstream *downstream) {
nghttp2_session_get_remote_settings
(
session_
,
NGHTTP2_SETTINGS_ENABLE_PUSH
)
==
1
&&
!
get_config
()
->
http2_proxy
&&
!
get_config
()
->
client_proxy
&&
(
downstream
->
get_stream_id
()
%
2
)
&&
downstream
->
get_response_header
(
http2
::
HD_LINK
)
&&
downstream
->
get_response_http_status
()
==
200
&&
(
downstream
->
get_stream_id
()
%
2
)
&&
resp
.
fs
.
header
(
http2
::
HD_LINK
)
&&
resp
.
http_status
==
200
&&
(
req
.
method
==
HTTP_GET
||
req
.
method
==
HTTP_POST
))
{
if
(
prepare_push_promise
(
downstream
)
!=
0
)
{
...
...
@@ -1619,9 +1622,11 @@ int Http2Upstream::on_downstream_body_complete(Downstream *downstream) {
DLOG
(
INFO
,
downstream
)
<<
"HTTP response completed"
;
}
auto
&
resp
=
downstream
->
response
();
if
(
!
downstream
->
validate_response_bodylen
())
{
rst_stream
(
downstream
,
NGHTTP2_PROTOCOL_ERROR
);
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
return
0
;
}
...
...
@@ -1762,13 +1767,14 @@ int Http2Upstream::prepare_push_promise(Downstream *downstream) {
size_t
baselen
;
const
auto
&
req
=
downstream
->
request
();
const
auto
&
resp
=
downstream
->
response
();
rv
=
http2
::
get_pure_path_component
(
&
base
,
&
baselen
,
req
.
path
);
if
(
rv
!=
0
)
{
return
0
;
}
for
(
auto
&
kv
:
downstream
->
get_response_
headers
())
{
for
(
auto
&
kv
:
resp
.
fs
.
headers
())
{
if
(
kv
.
token
!=
http2
::
HD_LINK
)
{
continue
;
}
...
...
src/shrpx_http_downstream_connection.cc
View file @
3b8889a2
...
...
@@ -54,9 +54,10 @@ void timeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
auto
downstream
=
dconn
->
get_downstream
();
auto
upstream
=
downstream
->
get_upstream
();
auto
handler
=
upstream
->
get_client_handler
();
auto
&
resp
=
downstream
->
response
();
// Do this so that dconn is not pooled
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
if
(
upstream
->
downstream_error
(
dconn
,
Downstream
::
EVENT_TIMEOUT
)
!=
0
)
{
delete
handler
;
...
...
@@ -482,13 +483,14 @@ int htp_hdrs_completecb(http_parser *htp) {
auto
downstream
=
static_cast
<
Downstream
*>
(
htp
->
data
);
auto
upstream
=
downstream
->
get_upstream
();
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
int
rv
;
downstream
->
set_response_http_status
(
htp
->
status_code
)
;
downstream
->
set_response_major
(
htp
->
http_major
)
;
downstream
->
set_response_minor
(
htp
->
http_minor
)
;
resp
.
http_status
=
htp
->
status_code
;
resp
.
http_major
=
htp
->
http_major
;
resp
.
http_minor
=
htp
->
http_minor
;
if
(
downstream
->
index_response
_headers
()
!=
0
)
{
if
(
resp
.
fs
.
index
_headers
()
!=
0
)
{
downstream
->
set_response_state
(
Downstream
::
MSG_BAD_HEADER
);
return
-
1
;
}
...
...
@@ -500,7 +502,7 @@ int htp_hdrs_completecb(http_parser *htp) {
if
(
downstream
->
get_non_final_response
())
{
// Reset content-length because we reuse same Downstream for the
// next response.
downstream
->
set_response_content_length
(
-
1
)
;
resp
.
fs
.
content_length
=
-
1
;
// For non-final response code, we just call
// on_downstream_header_complete() without changing response
// state.
...
...
@@ -514,13 +516,13 @@ int htp_hdrs_completecb(http_parser *htp) {
return
1
;
}
downstream
->
set_response_connection_close
(
!
http_should_keep_alive
(
htp
)
);
resp
.
connection_close
=
!
http_should_keep_alive
(
htp
);
downstream
->
set_response_state
(
Downstream
::
HEADER_COMPLETE
);
downstream
->
inspect_http1_response
();
if
(
downstream
->
get_upgraded
())
{
// content-length must be ignored for upgraded connection.
downstream
->
set_response_content_length
(
-
1
)
;
downstream
->
set_response_connection_close
(
true
)
;
resp
.
fs
.
content_length
=
-
1
;
resp
.
connection_close
=
true
;
// transfer-encoding not applied to upgraded connection
downstream
->
set_chunked_response
(
false
);
}
...
...
@@ -540,7 +542,7 @@ int htp_hdrs_completecb(http_parser *htp) {
}
}
unsigned
int
status
=
downstream
->
get_response_http_status
()
;
auto
status
=
resp
.
http_status
;
// Ignore the response body. HEAD response may contain
// Content-Length or Transfer-Encoding: chunked. Some server send
// 304 status code with nonzero Content-Length, but without response
...
...
@@ -559,18 +561,20 @@ int htp_hdrs_completecb(http_parser *htp) {
namespace
{
int
htp_hdr_keycb
(
http_parser
*
htp
,
const
char
*
data
,
size_t
len
)
{
auto
downstream
=
static_cast
<
Downstream
*>
(
htp
->
data
);
auto
&
resp
=
downstream
->
response
();
if
(
downstream
->
get_response_state
()
==
Downstream
::
INITIAL
)
{
if
(
downstream
->
get_response_
header_key_prev
())
{
downstream
->
append_last_response
_header_key
(
data
,
len
);
if
(
resp
.
fs
.
header_key_prev
())
{
resp
.
fs
.
append_last
_header_key
(
data
,
len
);
}
else
{
downstream
->
add_response
_header
(
std
::
string
(
data
,
len
),
""
);
resp
.
fs
.
add
_header
(
std
::
string
(
data
,
len
),
""
);
}
}
else
{
// trailer part
if
(
downstream
->
get_response_
trailer_key_prev
())
{
downstream
->
append_last_response
_trailer_key
(
data
,
len
);
if
(
resp
.
fs
.
trailer_key_prev
())
{
resp
.
fs
.
append_last
_trailer_key
(
data
,
len
);
}
else
{
downstream
->
add_response
_trailer
(
std
::
string
(
data
,
len
),
""
);
resp
.
fs
.
add
_trailer
(
std
::
string
(
data
,
len
),
""
);
}
}
return
0
;
...
...
@@ -580,18 +584,12 @@ int htp_hdr_keycb(http_parser *htp, const char *data, size_t len) {
namespace
{
int
htp_hdr_valcb
(
http_parser
*
htp
,
const
char
*
data
,
size_t
len
)
{
auto
downstream
=
static_cast
<
Downstream
*>
(
htp
->
data
);
auto
&
resp
=
downstream
->
response
();
if
(
downstream
->
get_response_state
()
==
Downstream
::
INITIAL
)
{
if
(
downstream
->
get_response_header_key_prev
())
{
downstream
->
set_last_response_header_value
(
data
,
len
);
}
else
{
downstream
->
append_last_response_header_value
(
data
,
len
);
}
resp
.
fs
.
append_last_header_value
(
data
,
len
);
}
else
{
if
(
downstream
->
get_response_trailer_key_prev
())
{
downstream
->
set_last_response_trailer_value
(
data
,
len
);
}
else
{
downstream
->
append_last_response_trailer_value
(
data
,
len
);
}
resp
.
fs
.
append_last_trailer_value
(
data
,
len
);
}
return
0
;
}
...
...
src/shrpx_https_upstream.cc
View file @
3b8889a2
...
...
@@ -247,6 +247,7 @@ int htp_hdrs_completecb(http_parser *htp) {
}
auto
downstream
=
upstream
->
get_downstream
();
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
req
.
http_major
=
htp
->
http_major
;
req
.
http_minor
=
htp
->
http_minor
;
...
...
@@ -325,7 +326,7 @@ int htp_hdrs_completecb(http_parser *htp) {
auto
mruby_ctx
=
worker
->
get_mruby_context
();
if
(
mruby_ctx
->
run_on_request_proc
(
downstream
)
!=
0
)
{
downstream
->
set_response_http_status
(
500
)
;
resp
.
http_status
=
500
;
return
-
1
;
}
#endif // HAVE_MRUBY
...
...
@@ -514,7 +515,7 @@ int HttpsUpstream::on_read() {
if
(
htperr
==
HPE_INVALID_METHOD
)
{
status_code
=
501
;
}
else
if
(
downstream
)
{
status_code
=
downstream
->
get_response_http_status
()
;
status_code
=
downstream
->
response
().
http_status
;
if
(
status_code
==
0
)
{
if
(
downstream
->
get_request_state
()
==
Downstream
::
CONNECT_FAIL
)
{
status_code
=
503
;
...
...
@@ -558,6 +559,7 @@ int HttpsUpstream::on_write() {
auto
dconn
=
downstream
->
get_downstream_connection
();
auto
output
=
downstream
->
get_response_buf
();
const
auto
&
resp
=
downstream
->
response
();
if
(
output
->
rleft
()
==
0
&&
dconn
&&
downstream
->
get_response_state
()
!=
Downstream
::
MSG_COMPLETE
)
{
...
...
@@ -578,7 +580,7 @@ int HttpsUpstream::on_write() {
// We need to postpone detachment until all data are sent so that
// we can notify nghttp2 library all data consumed.
if
(
downstream
->
get_response_state
()
==
Downstream
::
MSG_COMPLETE
)
{
if
(
downstream
->
get_response_connection_close
()
||
if
(
resp
.
connection_close
||
downstream
->
get_request_state
()
!=
Downstream
::
MSG_COMPLETE
)
{
// Connection close
downstream
->
pop_downstream_connection
();
...
...
@@ -754,30 +756,30 @@ int HttpsUpstream::downstream_error(DownstreamConnection *dconn, int events) {
int
HttpsUpstream
::
send_reply
(
Downstream
*
downstream
,
const
uint8_t
*
body
,
size_t
bodylen
)
{
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
auto
connection_close
=
false
;
if
(
req
.
http_major
<=
0
||
(
req
.
http_major
==
1
&&
req
.
http_minor
==
0
))
{
connection_close
=
true
;
}
else
{
auto
c
=
downstream
->
get_response_
header
(
http2
::
HD_CONNECTION
);
auto
c
=
resp
.
fs
.
header
(
http2
::
HD_CONNECTION
);
if
(
c
&&
util
::
strieq_l
(
"close"
,
c
->
value
))
{
connection_close
=
true
;
}
}
if
(
connection_close
)
{
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
handler_
->
set_should_close_after_write
(
true
);
}
auto
output
=
downstream
->
get_response_buf
();
output
->
append
(
"HTTP/1.1 "
);
output
->
append
(
http2
::
get_status_string
(
downstream
->
get_response_http_status
()));
output
->
append
(
http2
::
get_status_string
(
resp
.
http_status
));
output
->
append
(
"
\r\n
"
);
for
(
auto
&
kv
:
downstream
->
get_response_
headers
())
{
for
(
auto
&
kv
:
resp
.
fs
.
headers
())
{
if
(
kv
.
name
.
empty
()
||
kv
.
name
[
0
]
==
':'
)
{
continue
;
}
...
...
@@ -787,7 +789,7 @@ int HttpsUpstream::send_reply(Downstream *downstream, const uint8_t *body,
output
->
append
(
"
\r\n
"
);
}
if
(
!
downstream
->
get_response_
header
(
http2
::
HD_SERVER
))
{
if
(
!
resp
.
fs
.
header
(
http2
::
HD_SERVER
))
{
output
->
append
(
"Server: "
);
output
->
append
(
get_config
()
->
server_name
,
strlen
(
get_config
()
->
server_name
));
...
...
@@ -814,10 +816,12 @@ void HttpsUpstream::error_reply(unsigned int status_code) {
downstream
=
get_downstream
();
}
downstream
->
set_response_http_status
(
status_code
);
auto
&
resp
=
downstream
->
response
();
resp
.
http_status
=
status_code
;
// we are going to close connection for both frontend and backend in
// error condition. This is safest option.
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
handler_
->
set_should_close_after_write
(
true
);
auto
output
=
downstream
->
get_response_buf
();
...
...
@@ -883,6 +887,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
#ifdef HAVE_MRUBY
if
(
!
downstream
->
get_non_final_response
())
{
...
...
@@ -909,7 +914,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf
->
append
(
"."
);
buf
->
append
(
util
::
utos
(
req
.
http_minor
));
buf
->
append
(
" "
);
buf
->
append
(
http2
::
get_status_string
(
downstream
->
get_response_http_status
()
));
buf
->
append
(
http2
::
get_status_string
(
resp
.
http_status
));
buf
->
append
(
"
\r\n
"
);
if
(
!
get_config
()
->
http2_proxy
&&
!
get_config
()
->
client_proxy
&&
...
...
@@ -918,8 +923,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
get_client_handler
()
->
get_upstream_scheme
());
}
http2
::
build_http1_headers_from_headers
(
buf
,
downstream
->
get_response_headers
());
http2
::
build_http1_headers_from_headers
(
buf
,
resp
.
fs
.
headers
());
if
(
downstream
->
get_non_final_response
())
{
buf
->
append
(
"
\r\n
"
);
...
...
@@ -928,7 +932,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
log_response_headers
(
buf
);
}
downstream
->
clear_response
_headers
();
resp
.
fs
.
clear
_headers
();
return
0
;
}
...
...
@@ -938,12 +942,12 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
// after graceful shutdown commenced, add connection: close header
// field.
if
(
worker
->
get_graceful_shutdown
())
{
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
}
// We check downstream->get_response_connection_close() in case when
// the Content-Length is not available.
if
(
!
req
.
connection_close
&&
!
downstream
->
get_response_connection_close
()
)
{
if
(
!
req
.
connection_close
&&
!
resp
.
connection_close
)
{
if
(
req
.
http_major
<=
0
||
req
.
http_minor
<=
0
)
{
// We add this header for HTTP/1.0 or HTTP/0.9 clients
buf
->
append
(
"Connection: Keep-Alive
\r\n
"
);
...
...
@@ -953,14 +957,14 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
if
(
!
connect_method
&&
downstream
->
get_upgraded
())
{
auto
connection
=
downstream
->
get_response_
header
(
http2
::
HD_CONNECTION
);
auto
connection
=
resp
.
fs
.
header
(
http2
::
HD_CONNECTION
);
if
(
connection
)
{
buf
->
append
(
"Connection: "
);
buf
->
append
((
*
connection
).
value
);
buf
->
append
(
"
\r\n
"
);
}
auto
upgrade
=
downstream
->
get_response_
header
(
http2
::
HD_UPGRADE
);
auto
upgrade
=
resp
.
fs
.
header
(
http2
::
HD_UPGRADE
);
if
(
upgrade
)
{
buf
->
append
(
"Upgrade: "
);
buf
->
append
((
*
upgrade
).
value
);
...
...
@@ -968,7 +972,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
}
if
(
!
downstream
->
get_response_
header
(
http2
::
HD_ALT_SVC
))
{
if
(
!
resp
.
fs
.
header
(
http2
::
HD_ALT_SVC
))
{
// We won't change or alter alt-svc from backend for now
if
(
!
get_config
()
->
altsvcs
.
empty
())
{
buf
->
append
(
"Alt-Svc: "
);
...
...
@@ -988,7 +992,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf
->
append
(
get_config
()
->
server_name
,
strlen
(
get_config
()
->
server_name
));
buf
->
append
(
"
\r\n
"
);
}
else
{
auto
server
=
downstream
->
get_response_
header
(
http2
::
HD_SERVER
);
auto
server
=
resp
.
fs
.
header
(
http2
::
HD_SERVER
);
if
(
server
)
{
buf
->
append
(
"Server: "
);
buf
->
append
((
*
server
).
value
);
...
...
@@ -996,7 +1000,7 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
}
}
auto
via
=
downstream
->
get_response_
header
(
http2
::
HD_VIA
);
auto
via
=
resp
.
fs
.
header
(
http2
::
HD_VIA
);
if
(
get_config
()
->
no_via
)
{
if
(
via
)
{
buf
->
append
(
"Via: "
);
...
...
@@ -1009,8 +1013,8 @@ int HttpsUpstream::on_downstream_header_complete(Downstream *downstream) {
buf
->
append
((
*
via
).
value
);
buf
->
append
(
", "
);
}
buf
->
append
(
http
::
create_via_header_value
(
downstream
->
get_response_major
(),
downstream
->
get_response_minor
()
));
buf
->
append
(
http
::
create_via_header_value
(
resp
.
http_major
,
resp
.
http_minor
));
buf
->
append
(
"
\r\n
"
);
}
...
...
@@ -1055,10 +1059,11 @@ int HttpsUpstream::on_downstream_body(Downstream *downstream,
int
HttpsUpstream
::
on_downstream_body_complete
(
Downstream
*
downstream
)
{
const
auto
&
req
=
downstream
->
request
();
auto
&
resp
=
downstream
->
response
();
if
(
downstream
->
get_chunked_response
())
{
auto
output
=
downstream
->
get_response_buf
();
auto
&
trailers
=
downstream
->
get_response_
trailers
();
const
auto
&
trailers
=
resp
.
fs
.
trailers
();
if
(
trailers
.
empty
())
{
output
->
append
(
"0
\r\n\r\n
"
);
}
else
{
...
...
@@ -1072,10 +1077,10 @@ int HttpsUpstream::on_downstream_body_complete(Downstream *downstream) {
}
if
(
!
downstream
->
validate_response_bodylen
())
{
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
}
if
(
req
.
connection_close
||
downstream
->
get_response_connection_close
()
)
{
if
(
req
.
connection_close
||
resp
.
connection_close
)
{
auto
handler
=
get_client_handler
();
handler
->
set_should_close_after_write
(
true
);
}
...
...
src/shrpx_mruby.cc
View file @
3b8889a2
...
...
@@ -100,7 +100,7 @@ int MRubyContext::run_app(Downstream *downstream, int phase) {
}
if
(
data
.
response_headers_dirty
)
{
downstream
->
index_response
_headers
();
downstream
->
response
().
fs
.
index
_headers
();
}
return
rv
;
...
...
src/shrpx_mruby_module_response.cc
View file @
3b8889a2
...
...
@@ -49,7 +49,8 @@ namespace {
mrb_value
response_get_http_version_major
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
return
mrb_fixnum_value
(
downstream
->
get_response_major
());
const
auto
&
resp
=
downstream
->
response
();
return
mrb_fixnum_value
(
resp
.
http_major
);
}
}
// namespace
...
...
@@ -57,7 +58,8 @@ namespace {
mrb_value
response_get_http_version_minor
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
return
mrb_fixnum_value
(
downstream
->
get_response_minor
());
const
auto
&
resp
=
downstream
->
response
();
return
mrb_fixnum_value
(
resp
.
http_minor
);
}
}
// namespace
...
...
@@ -65,8 +67,8 @@ namespace {
mrb_value
response_get_status
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
return
mrb_fixnum_value
(
downstream
->
get_response_http_status
()
);
const
auto
&
resp
=
downstream
->
response
();
return
mrb_fixnum_value
(
resp
.
http_status
);
}
}
// namespace
...
...
@@ -74,6 +76,7 @@ namespace {
mrb_value
response_set_status
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
auto
&
resp
=
downstream
->
response
();
mrb_int
status
;
mrb_get_args
(
mrb
,
"i"
,
&
status
);
...
...
@@ -83,7 +86,7 @@ mrb_value response_set_status(mrb_state *mrb, mrb_value self) {
"invalid status; it should be [200, 999], inclusive"
);
}
downstream
->
set_response_http_status
(
status
)
;
resp
.
http_status
=
status
;
return
self
;
}
...
...
@@ -93,7 +96,9 @@ namespace {
mrb_value
response_get_headers
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
return
create_headers_hash
(
mrb
,
downstream
->
get_response_headers
());
const
auto
&
resp
=
downstream
->
response
();
return
create_headers_hash
(
mrb
,
resp
.
fs
.
headers
());
}
}
// namespace
...
...
@@ -101,6 +106,7 @@ namespace {
mrb_value
response_mod_header
(
mrb_state
*
mrb
,
mrb_value
self
,
bool
repl
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
auto
&
resp
=
downstream
->
response
();
mrb_value
key
,
values
;
mrb_get_args
(
mrb
,
"oo"
,
&
key
,
&
values
);
...
...
@@ -113,7 +119,7 @@ mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) {
if
(
repl
)
{
size_t
p
=
0
;
auto
&
headers
=
downstream
->
get_response_
headers
();
auto
&
headers
=
resp
.
fs
.
headers
();
for
(
size_t
i
=
0
;
i
<
headers
.
size
();
++
i
)
{
auto
&
hd
=
headers
[
i
];
if
(
util
::
streq
(
std
::
begin
(
hd
.
name
),
hd
.
name
.
size
(),
RSTRING_PTR
(
key
),
...
...
@@ -131,14 +137,12 @@ mrb_value response_mod_header(mrb_state *mrb, mrb_value self, bool repl) {
auto
n
=
mrb_ary_len
(
mrb
,
values
);
for
(
int
i
=
0
;
i
<
n
;
++
i
)
{
auto
value
=
mrb_ary_entry
(
values
,
i
);
downstream
->
add_response_header
(
std
::
string
(
RSTRING_PTR
(
key
),
RSTRING_LEN
(
key
)),
std
::
string
(
RSTRING_PTR
(
value
),
RSTRING_LEN
(
value
)));
resp
.
fs
.
add_header
(
std
::
string
(
RSTRING_PTR
(
key
),
RSTRING_LEN
(
key
)),
std
::
string
(
RSTRING_PTR
(
value
),
RSTRING_LEN
(
value
)));
}
}
else
if
(
!
mrb_nil_p
(
values
))
{
downstream
->
add_response_header
(
std
::
string
(
RSTRING_PTR
(
key
),
RSTRING_LEN
(
key
)),
std
::
string
(
RSTRING_PTR
(
values
),
RSTRING_LEN
(
values
)));
resp
.
fs
.
add_header
(
std
::
string
(
RSTRING_PTR
(
key
),
RSTRING_LEN
(
key
)),
std
::
string
(
RSTRING_PTR
(
values
),
RSTRING_LEN
(
values
)));
}
data
->
response_headers_dirty
=
true
;
...
...
@@ -163,8 +167,9 @@ namespace {
mrb_value
response_clear_headers
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
auto
&
resp
=
downstream
->
response
();
downstream
->
clear_response
_headers
();
resp
.
fs
.
clear
_headers
();
return
mrb_nil_value
();
}
...
...
@@ -174,6 +179,7 @@ namespace {
mrb_value
response_return
(
mrb_state
*
mrb
,
mrb_value
self
)
{
auto
data
=
static_cast
<
MRubyAssocData
*>
(
mrb
->
ud
);
auto
downstream
=
data
->
downstream
;
auto
&
resp
=
downstream
->
response
();
int
rv
;
if
(
downstream
->
get_response_state
()
==
Downstream
::
MSG_COMPLETE
)
{
...
...
@@ -187,12 +193,12 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
const
uint8_t
*
body
=
nullptr
;
size_t
bodylen
=
0
;
if
(
downstream
->
get_response_http_status
()
==
0
)
{
downstream
->
set_response_http_status
(
200
)
;
if
(
resp
.
http_status
==
0
)
{
resp
.
http_status
=
200
;
}
if
(
data
->
response_headers_dirty
)
{
downstream
->
index_response
_headers
();
resp
.
fs
.
index
_headers
();
data
->
response_headers_dirty
=
false
;
}
...
...
@@ -201,21 +207,20 @@ mrb_value response_return(mrb_state *mrb, mrb_value self) {
bodylen
=
vallen
;
}
auto
cl
=
downstream
->
get_response_
header
(
http2
::
HD_CONTENT_LENGTH
);
auto
cl
=
resp
.
fs
.
header
(
http2
::
HD_CONTENT_LENGTH
);
if
(
cl
)
{
cl
->
value
=
util
::
utos
(
bodylen
);
}
else
{
downstream
->
add_response
_header
(
"content-length"
,
util
::
utos
(
bodylen
),
http2
::
HD_CONTENT_LENGTH
);
resp
.
fs
.
add
_header
(
"content-length"
,
util
::
utos
(
bodylen
),
http2
::
HD_CONTENT_LENGTH
);
}
downstream
->
set_response_content_length
(
bodylen
)
;
resp
.
fs
.
content_length
=
bodylen
;
auto
date
=
downstream
->
get_response_
header
(
http2
::
HD_DATE
);
auto
date
=
resp
.
fs
.
header
(
http2
::
HD_DATE
);
if
(
!
date
)
{
auto
lgconf
=
log_config
();
lgconf
->
update_tstamp
(
std
::
chrono
::
system_clock
::
now
());
downstream
->
add_response_header
(
"date"
,
lgconf
->
time_http_str
,
http2
::
HD_DATE
);
resp
.
fs
.
add_header
(
"date"
,
lgconf
->
time_http_str
,
http2
::
HD_DATE
);
}
auto
upstream
=
downstream
->
get_upstream
();
...
...
src/shrpx_spdy_upstream.cc
View file @
3b8889a2
...
...
@@ -820,10 +820,11 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
data_prd_ptr
=
&
data_prd
;
}
auto
status_string
=
http2
::
get_status_string
(
downstream
->
get_response_http_status
());
const
auto
&
resp
=
downstream
->
response
();
auto
&
headers
=
downstream
->
get_response_headers
();
auto
status_string
=
http2
::
get_status_string
(
resp
.
http_status
);
const
auto
&
headers
=
resp
.
fs
.
headers
();
auto
nva
=
std
::
vector
<
const
char
*>
();
// 3 for :status, :version and server
...
...
@@ -849,7 +850,7 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
nva
.
push_back
(
kv
.
value
.
c_str
());
}
if
(
!
downstream
->
get_response_
header
(
http2
::
HD_SERVER
))
{
if
(
!
resp
.
fs
.
header
(
http2
::
HD_SERVER
))
{
nva
.
push_back
(
"server"
);
nva
.
push_back
(
get_config
()
->
server_name
);
}
...
...
@@ -876,8 +877,10 @@ int SpdyUpstream::send_reply(Downstream *downstream, const uint8_t *body,
int
SpdyUpstream
::
error_reply
(
Downstream
*
downstream
,
unsigned
int
status_code
)
{
int
rv
;
auto
&
resp
=
downstream
->
response
();
auto
html
=
http
::
create_error_html
(
status_code
);
downstream
->
set_response_http_status
(
status_code
)
;
resp
.
http_status
=
status_code
;
auto
body
=
downstream
->
get_response_buf
();
body
->
append
(
html
.
c_str
(),
html
.
size
());
downstream
->
set_response_state
(
Downstream
::
MSG_COMPLETE
);
...
...
@@ -938,11 +941,13 @@ void SpdyUpstream::remove_downstream(Downstream *downstream) {
// WARNING: Never call directly or indirectly spdylay_session_send or
// spdylay_session_recv. These calls may delete downstream.
int
SpdyUpstream
::
on_downstream_header_complete
(
Downstream
*
downstream
)
{
auto
&
resp
=
downstream
->
response
();
if
(
downstream
->
get_non_final_response
())
{
// SPDY does not support non-final response. We could send it
// with HEADERS and final response in SYN_REPLY, but it is not
// official way.
downstream
->
clear_response
_headers
();
resp
.
fs
.
clear
_headers
();
return
0
;
}
...
...
@@ -974,20 +979,20 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
!
get_config
()
->
no_location_rewrite
)
{
downstream
->
rewrite_location_response_header
(
req
.
scheme
);
}
size_t
nheader
=
downstream
->
get_response_headers
().
size
();
// 8 means server, :status, :version and possible via header field.
auto
nv
=
make_unique
<
const
char
*
[]
>
(
nheader
*
2
+
8
+
get_config
()
->
add_response_headers
.
size
()
*
2
+
1
);
resp
.
fs
.
headers
().
size
()
*
2
+
8
+
get_config
()
->
add_response_headers
.
size
()
*
2
+
1
);
size_t
hdidx
=
0
;
std
::
string
via_value
;
std
::
string
status_string
=
http2
::
get_status_string
(
downstream
->
get_response_http_status
());
auto
status_string
=
http2
::
get_status_string
(
resp
.
http_status
);
nv
[
hdidx
++
]
=
":status"
;
nv
[
hdidx
++
]
=
status_string
.
c_str
();
nv
[
hdidx
++
]
=
":version"
;
nv
[
hdidx
++
]
=
"HTTP/1.1"
;
for
(
auto
&
hd
:
downstream
->
get_response_
headers
())
{
for
(
auto
&
hd
:
resp
.
fs
.
headers
())
{
if
(
hd
.
name
.
empty
()
||
hd
.
name
.
c_str
()[
0
]
==
':'
)
{
continue
;
}
...
...
@@ -1009,14 +1014,14 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
nv
[
hdidx
++
]
=
"server"
;
nv
[
hdidx
++
]
=
get_config
()
->
server_name
;
}
else
{
auto
server
=
downstream
->
get_response_
header
(
http2
::
HD_SERVER
);
auto
server
=
resp
.
fs
.
header
(
http2
::
HD_SERVER
);
if
(
server
)
{
nv
[
hdidx
++
]
=
"server"
;
nv
[
hdidx
++
]
=
server
->
value
.
c_str
();
}
}
auto
via
=
downstream
->
get_response_
header
(
http2
::
HD_VIA
);
auto
via
=
resp
.
fs
.
header
(
http2
::
HD_VIA
);
if
(
get_config
()
->
no_via
)
{
if
(
via
)
{
nv
[
hdidx
++
]
=
"via"
;
...
...
@@ -1027,8 +1032,8 @@ int SpdyUpstream::on_downstream_header_complete(Downstream *downstream) {
via_value
=
via
->
value
;
via_value
+=
", "
;
}
via_value
+=
http
::
create_via_header_value
(
downstream
->
get_response_major
(),
downstream
->
get_response_minor
()
);
via_value
+=
http
::
create_via_header_value
(
resp
.
http_major
,
resp
.
http_minor
);
nv
[
hdidx
++
]
=
"via"
;
nv
[
hdidx
++
]
=
via_value
.
c_str
();
}
...
...
@@ -1086,9 +1091,11 @@ int SpdyUpstream::on_downstream_body_complete(Downstream *downstream) {
DLOG
(
INFO
,
downstream
)
<<
"HTTP response completed"
;
}
auto
&
resp
=
downstream
->
response
();
if
(
!
downstream
->
validate_response_bodylen
())
{
rst_stream
(
downstream
,
SPDYLAY_PROTOCOL_ERROR
);
downstream
->
set_response_connection_close
(
true
)
;
resp
.
connection_close
=
true
;
return
0
;
}
...
...
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