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
5da49989
Commit
5da49989
authored
May 13, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttpd: Add --echo-upload option to send back request body
parent
26013196
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
95 additions
and
7 deletions
+95
-7
src/HttpServer.cc
src/HttpServer.cc
+86
-7
src/HttpServer.h
src/HttpServer.h
+2
-0
src/nghttpd.cc
src/nghttpd.cc
+7
-0
No files found.
src/HttpServer.cc
View file @
5da49989
...
...
@@ -91,7 +91,8 @@ Config::Config()
session_option
(
nullptr
),
data_ptr
(
nullptr
),
padding
(
0
),
num_worker
(
1
),
max_concurrent_streams
(
100
),
header_table_size
(
-
1
),
port
(
0
),
verbose
(
false
),
daemon
(
false
),
verify_client
(
false
),
no_tls
(
false
),
error_gzip
(
false
),
early_response
(
false
),
hexdump
(
false
)
{
error_gzip
(
false
),
early_response
(
false
),
hexdump
(
false
),
echo_upload
(
false
)
{
nghttp2_option_new
(
&
session_option
);
nghttp2_option_set_recv_client_preface
(
session_option
,
1
);
}
...
...
@@ -282,7 +283,7 @@ private:
Stream
::
Stream
(
Http2Handler
*
handler
,
int32_t
stream_id
)
:
handler
(
handler
),
file_ent
(
nullptr
),
body_length
(
0
),
body_offset
(
0
),
stream_id
(
stream_id
)
{
stream_id
(
stream_id
)
,
echo_upload
(
false
)
{
auto
config
=
handler
->
get_config
();
ev_timer_init
(
&
rtimer
,
stream_timeout_cb
,
0.
,
config
->
stream_read_timeout
);
ev_timer_init
(
&
wtimer
,
stream_timeout_cb
,
0.
,
config
->
stream_write_timeout
);
...
...
@@ -918,6 +919,49 @@ void prepare_status_response(Stream *stream, Http2Handler *hd, int status) {
}
}
// namespace
namespace
{
void
prepare_echo_response
(
Stream
*
stream
,
Http2Handler
*
hd
)
{
auto
length
=
lseek
(
stream
->
file_ent
->
fd
,
0
,
SEEK_END
);
if
(
length
==
-
1
)
{
hd
->
submit_rst_stream
(
stream
,
NGHTTP2_INTERNAL_ERROR
);
return
;
}
stream
->
body_length
=
length
;
if
(
lseek
(
stream
->
file_ent
->
fd
,
0
,
SEEK_SET
)
==
-
1
)
{
hd
->
submit_rst_stream
(
stream
,
NGHTTP2_INTERNAL_ERROR
);
return
;
}
nghttp2_data_provider
data_prd
;
data_prd
.
source
.
fd
=
stream
->
file_ent
->
fd
;
data_prd
.
read_callback
=
file_read_callback
;
Headers
headers
;
headers
.
emplace_back
(
"nghttpd-response"
,
"echo"
);
headers
.
emplace_back
(
"content-length"
,
util
::
utos
(
length
));
hd
->
submit_response
(
"200"
,
stream
->
stream_id
,
headers
,
&
data_prd
);
}
}
// namespace
namespace
{
bool
prepare_upload_temp_store
(
Stream
*
stream
,
Http2Handler
*
hd
)
{
auto
sessions
=
hd
->
get_sessions
();
char
tempfn
[]
=
"/tmp/nghttpd.temp.XXXXXX"
;
auto
fd
=
mkstemp
(
tempfn
);
if
(
fd
==
-
1
)
{
return
false
;
}
unlink
(
tempfn
);
// Ordinary request never start with "echo:". The length is 0 for
// now. We will update it when we get whole request body.
stream
->
file_ent
=
sessions
->
cache_fd
(
std
::
string
(
"echo:"
)
+
tempfn
,
FileEntry
(
tempfn
,
0
,
0
,
fd
));
stream
->
echo_upload
=
true
;
return
true
;
}
}
// namespace
namespace
{
void
prepare_redirect_response
(
Stream
*
stream
,
Http2Handler
*
hd
,
const
std
::
string
&
path
,
int
status
)
{
...
...
@@ -972,8 +1016,14 @@ void prepare_response(Stream *stream, Http2Handler *hd,
url
=
reqpath
;
}
url
=
util
::
percentDecode
(
url
.
begin
(),
url
.
end
());
auto
sessions
=
hd
->
get_sessions
();
url
=
util
::
percentDecode
(
std
::
begin
(
url
),
std
::
end
(
url
));
if
(
!
util
::
check_path
(
url
))
{
if
(
stream
->
file_ent
)
{
sessions
->
release_fd
(
stream
->
file_ent
->
path
);
stream
->
file_ent
=
nullptr
;
}
prepare_status_response
(
stream
,
hd
,
404
);
return
;
}
...
...
@@ -987,12 +1037,18 @@ void prepare_response(Stream *stream, Http2Handler *hd,
}
}
}
std
::
string
path
=
hd
->
get_config
()
->
htdocs
+
url
;
if
(
path
[
path
.
size
()
-
1
]
==
'/'
)
{
path
+=
DEFAULT_HTML
;
}
auto
sessions
=
hd
->
get_sessions
();
if
(
stream
->
echo_upload
)
{
assert
(
stream
->
file_ent
);
prepare_echo_response
(
stream
,
hd
);
return
;
}
auto
file_ent
=
sessions
->
get_cached_fd
(
path
);
if
(
file_ent
==
nullptr
)
{
...
...
@@ -1122,7 +1178,7 @@ int hd_on_frame_recv_callback(nghttp2_session *session,
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_END_STREAM
)
{
remove_stream_read_timeout
(
stream
);
if
(
!
hd
->
get_config
()
->
early_response
)
{
if
(
stream
->
echo_upload
||
!
hd
->
get_config
()
->
early_response
)
{
prepare_response
(
stream
,
hd
);
}
}
else
{
...
...
@@ -1146,14 +1202,22 @@ int hd_on_frame_recv_callback(nghttp2_session *session,
hd
->
submit_non_final_response
(
"100"
,
frame
->
hd
.
stream_id
);
}
if
(
hd
->
get_config
()
->
early_response
)
{
auto
&
method
=
http2
::
get_header
(
stream
->
hdidx
,
http2
::
HD__METHOD
,
stream
->
headers
)
->
value
;
if
(
hd
->
get_config
()
->
echo_upload
&&
(
method
==
"POST"
||
method
==
"PUT"
))
{
if
(
!
prepare_upload_temp_store
(
stream
,
hd
))
{
hd
->
submit_rst_stream
(
stream
,
NGHTTP2_INTERNAL_ERROR
);
return
0
;
}
}
else
if
(
hd
->
get_config
()
->
early_response
)
{
prepare_response
(
stream
,
hd
);
}
}
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_END_STREAM
)
{
remove_stream_read_timeout
(
stream
);
if
(
!
hd
->
get_config
()
->
early_response
)
{
if
(
stream
->
echo_upload
||
!
hd
->
get_config
()
->
early_response
)
{
prepare_response
(
stream
,
hd
);
}
}
else
{
...
...
@@ -1299,6 +1363,21 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
return
0
;
}
if
(
stream
->
echo_upload
)
{
assert
(
stream
->
file_ent
);
while
(
len
)
{
ssize_t
n
;
while
((
n
=
write
(
stream
->
file_ent
->
fd
,
data
,
len
))
==
-
1
&&
errno
==
EINTR
)
;
if
(
n
==
-
1
)
{
hd
->
submit_rst_stream
(
stream
,
NGHTTP2_INTERNAL_ERROR
);
return
0
;
}
len
-=
n
;
data
+=
n
;
}
}
// TODO Handle POST
add_stream_read_timeout
(
stream
);
...
...
src/HttpServer.h
View file @
5da49989
...
...
@@ -73,6 +73,7 @@ struct Config {
bool
error_gzip
;
bool
early_response
;
bool
hexdump
;
bool
echo_upload
;
Config
();
~
Config
();
};
...
...
@@ -101,6 +102,7 @@ struct Stream {
int64_t
body_offset
;
int32_t
stream_id
;
http2
::
HeaderIndex
hdidx
;
bool
echo_upload
;
Stream
(
Http2Handler
*
handler
,
int32_t
stream_id
);
~
Stream
();
};
...
...
src/nghttpd.cc
View file @
5da49989
...
...
@@ -153,6 +153,8 @@ Options:
--hexdump Display the incoming traffic in hexadecimal (Canonical
hex+ASCII display). If SSL/TLS is used, decrypted data
are used.
--echo-upload
Send back uploaded content if method is POST or PUT.
--version Display version information and exit.
-h, --help Display this help and exit.
...
...
@@ -188,6 +190,7 @@ int main(int argc, char **argv) {
{
"early-response"
,
no_argument
,
&
flag
,
5
},
{
"trailer"
,
required_argument
,
&
flag
,
6
},
{
"hexdump"
,
no_argument
,
&
flag
,
7
},
{
"echo-upload"
,
no_argument
,
&
flag
,
8
},
{
nullptr
,
0
,
nullptr
,
0
}};
int
option_index
=
0
;
int
c
=
getopt_long
(
argc
,
argv
,
"DVb:c:d:ehm:n:p:va:"
,
long_options
,
...
...
@@ -310,6 +313,10 @@ int main(int argc, char **argv) {
// hexdump option
config
.
hexdump
=
true
;
break
;
case
8
:
// echo-upload option
config
.
echo_upload
=
true
;
break
;
}
break
;
default:
...
...
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