Commit affe2004 authored by Wandenberg's avatar Wandenberg

add push_stream_header_template_file directive to be possible store the header...

add push_stream_header_template_file directive to be possible store the header template in a different file
parent 990acc30
......@@ -145,6 +145,7 @@ h1(#directives). Directives
| "push_stream_store_messages":push_stream_store_messages |   - |   - |   - |   x |   - |   x |
| "push_stream_channel_info_on_publish":push_stream_channel_info_on_publish |   - |   - |   - |   x |   - |   - |
| "push_stream_authorized_channels_only":push_stream_authorized_channels_only |   - |   - |   x |   - |   - |   x |
| "push_stream_header_template_file":push_stream_header_template_file |   - |   - |   x |   - |   - |   x |
| "push_stream_header_template":push_stream_header_template |   - |   - |   x |   - |   - |   x |
| "push_stream_message_template":push_stream_message_template |   - |   - |   x |   - |   - |   x |
| "push_stream_footer_template":push_stream_footer_template |   - |   - |   x |   - |   - |   x |
......@@ -247,6 +248,7 @@ h1(#contributors). Contributors
[push_stream_wildcard_channel_prefix]docs/directives/main.textile#push_stream_wildcard_channel_prefix
[push_stream_channels_path]docs/directives/subscribers.textile#push_stream_channels_path
[push_stream_authorized_channels_only]docs/directives/subscribers.textile#push_stream_authorized_channels_only
[push_stream_header_template_file]docs/directives/subscribers.textile#push_stream_header_template_file
[push_stream_header_template]docs/directives/subscribers.textile#push_stream_header_template
[push_stream_message_template]docs/directives/subscribers.textile#push_stream_message_template
[push_stream_footer_template]docs/directives/subscribers.textile#push_stream_footer_template
......
......@@ -99,6 +99,19 @@ All subscriber requests to nonexistent channels or channels without stored messa
This restriction is not applied to wildcard channels, but to connect to a wildcard channel is necessary to connect to at least one normal channel on the same request.
h2(#push_stream_header_template_file). push_stream_header_template_file <a name="push_stream_header_template_file" href="#">&nbsp;</a>
*syntax:* _push_stream_header_template_file string_
*default:* _none_
*context:* _location (push_stream_subscriber)_
The path of a file with the text that will be sent to subscribers when they arrive, except when long polling connections timed out.
The file is read only once on server startup.
Must not be used on the same level (http/server/location block) of push_stream_header_template directive.
h2(#push_stream_header_template). push_stream_header_template <a name="push_stream_header_template" href="#">&nbsp;</a>
*syntax:* _push_stream_header_template string_
......@@ -108,6 +121,7 @@ h2(#push_stream_header_template). push_stream_header_template <a name="push_stre
*context:* _location (push_stream_subscriber)_
The text that will be sent to subscribers when they arrive, except when long polling connections timed out.
Must not be used on the same level (http/server/location block) of push_stream_header_template_file directive.
h2(#push_stream_message_template). push_stream_message_template <a name="push_stream_message_template" href="#">&nbsp;</a>
......
......@@ -76,5 +76,6 @@ char * ngx_http_push_stream_set_shm_size_slot(ngx_conf_t *cf, ngx_c
ngx_int_t ngx_http_push_stream_init_shm_zone(ngx_shm_zone_t *shm_zone, void *data);
ngx_int_t ngx_http_push_stream_init_global_shm_zone(ngx_shm_zone_t *shm_zone, void *data);
char * ngx_http_push_stream_set_header_template_from_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
#endif /* NGX_HTTP_PUSH_STREAM_MODULE_SETUP_H_ */
......@@ -11,6 +11,7 @@ module NginxConfiguration
:keepalive_requests => nil,
:ping_message_interval => '10s',
:header_template_file => nil,
:header_template => %{<html><head><meta http-equiv=\\"Content-Type\\" content=\\"text/html; charset=utf-8\\">\\r\\n<meta http-equiv=\\"Cache-Control\\" content=\\"no-store\\">\\r\\n<meta http-equiv=\\"Cache-Control\\" content=\\"no-cache\\">\\r\\n<meta http-equiv=\\"Expires\\" content=\\"Thu, 1 Jan 1970 00:00:00 GMT\\">\\r\\n<script type=\\"text/javascript\\">\\r\\nwindow.onError = null;\\r\\ndocument.domain = \\'<%= nginx_host %>\\';\\r\\nparent.PushStream.register(this);\\r\\n</script>\\r\\n</head>\\r\\n<body onload=\\"try { parent.PushStream.reset(this) } catch (e) {}\\">},
:message_template => "<script>p(~id~,'~channel~','~text~');</script>",
:footer_template => "</body></html>",
......@@ -118,6 +119,7 @@ http {
<%= write_directive("push_stream_longpolling_connection_ttl", longpolling_connection_ttl, "timeout for long polling connections") %>
<%= write_directive("push_stream_timeout_with_body", timeout_with_body) %>
<%= write_directive("push_stream_header_template", header_template, "header to be sent when receiving new subscriber connection") %>
<%= write_directive("push_stream_header_template_file", header_template_file, "file with the header to be sent when receiving new subscriber connection") %>
<%= write_directive("push_stream_message_ttl", message_ttl, "message ttl") %>
<%= write_directive("push_stream_footer_template", footer_template, "footer to be sent when finishing subscriber connection") %>
......
......@@ -698,6 +698,119 @@ describe "Subscriber Properties" do
end
end
context "when header template file is set" do
before do
FileUtils.mkdir_p nginx_tests_tmp_dir
File.open(header_template_file, "w") {|f| f.write header_template_content }
end
after { File.delete(header_template_file) }
let(:header_template_file) { File.join(nginx_tests_tmp_dir, "header_template.txt") }
let(:header_template_content) { "Header\nTemplate\ninside a file" }
def assert_response_for(cfg, path, expected_response)
nginx_run_server(cfg) do |conf|
EventMachine.run do
sub = EventMachine::HttpRequest.new(nginx_address + path).get :head => headers
sub.stream do |chunk|
chunk.should eql(expected_response)
EventMachine.stop
end
end
end
end
it "should receive the file content" do
channel = 'ch_test_header_template_file'
merged_config = config.merge({
header_template: nil,
header_template_file: header_template_file
})
assert_response_for(merged_config, '/sub/' + channel.to_s, header_template_content)
end
it "should not accept header_template and header_template_file on same level" do
merged_config = config.merge({
:header_template => nil,
:extra_location => %{
location /sub2 {
push_stream_subscriber;
push_stream_header_template 'inline header template\\r\\n\\r\\n';
push_stream_header_template_file #{header_template_file};
}
}
})
nginx_test_configuration(merged_config).should include(%{"push_stream_header_template_file" directive is duplicate or template set by 'push_stream_header_template'})
end
it "should not accept header_template_file and header_template on same level" do
merged_config = config.merge({
:header_template => nil,
:extra_location => %{
location /sub2 {
push_stream_subscriber;
push_stream_header_template_file #{header_template_file};
push_stream_header_template 'inline header template\\r\\n\\r\\n';
}
}
})
nginx_test_configuration(merged_config).should include(%{"push_stream_header_template" directive is duplicate})
end
it "should accept header_template_file and header_template on different levels" do
channel = 'ch_test_override_header_template_file'
merged_config = config.merge({
:header_template_file => header_template_file,
:header_template => nil,
:extra_location => %{
location ~ /sub2/(.*) {
push_stream_subscriber;
push_stream_channels_path $1;
push_stream_header_template 'inline header template';
}
}
})
assert_response_for(merged_config, '/sub/' + channel.to_s, header_template_content)
assert_response_for(merged_config, '/sub2/' + channel.to_s, 'inline header template')
end
it "should accept header_template and header_template_file on different levels" do
channel = 'ch_test_override_header_template_file'
merged_config = config.merge({
:header_template => 'inline header template',
:extra_location => %{
location ~ /sub2/(.*) {
push_stream_subscriber;
push_stream_channels_path $1;
push_stream_header_template_file #{header_template_file};
}
}
})
assert_response_for(merged_config, '/sub/' + channel.to_s, 'inline header template')
assert_response_for(merged_config, '/sub2/' + channel.to_s, header_template_content)
end
it "should return error when could not open the file" do
merged_config = config.merge({
:header_template => nil,
:header_template_file => "/unexistent/path"
})
nginx_test_configuration(merged_config).should include(%{push stream module: unable to open file "/unexistent/path" for header template})
end
end
it "should receive the configured content type" do
channel = 'ch_test_content_type'
......
......@@ -147,6 +147,12 @@ static ngx_command_t ngx_http_push_stream_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, authorized_channels_only),
NULL },
{ ngx_string("push_stream_header_template_file"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_push_stream_set_header_template_from_file,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, header_template),
NULL },
{ ngx_string("push_stream_header_template"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
......@@ -913,6 +919,67 @@ ngx_http_push_stream_set_shm_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void
}
char *
ngx_http_push_stream_set_header_template_from_file(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
ngx_str_t *field = (ngx_str_t *) ((char *) conf + cmd->offset);
if (field->data != NULL) {
return "is duplicate or template set by 'push_stream_header_template'";
}
ngx_str_t *value = &(((ngx_str_t *) cf->args->elts)[1]);
ngx_file_t file;
ngx_file_info_t fi;
ssize_t n;
ngx_memzero(&file, sizeof(ngx_file_t));
file.name = *value;
file.log = cf->log;
file.fd = ngx_open_file(value->data, NGX_FILE_RDONLY, NGX_FILE_OPEN, 0);
if (file.fd == NGX_INVALID_FILE) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to open file \"%V\" for header template", value);
return NGX_CONF_ERROR;
}
if (ngx_fd_info(file.fd, &fi) == NGX_FILE_ERROR) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to stat file \"%V\" for header template", value);
ngx_close_file(file.fd);
return NGX_CONF_ERROR;
}
field->len = (size_t) ngx_file_size(&fi);
field->data = ngx_pcalloc(cf->pool, field->len);
if (field->data == NULL) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to allocate memory to read header template file", value);
ngx_close_file(file.fd);
return NGX_CONF_ERROR;
}
n = ngx_read_file(&file, field->data, field->len, 0);
if (n == NGX_ERROR) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to read data from file \"%V\" for header template", value);
ngx_close_file(file.fd);
return NGX_CONF_ERROR;
}
if ((size_t) n != field->len) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: returned only %z bytes instead of %z from file \"%V\"", n, field->len, value);
ngx_close_file(file.fd);
return NGX_CONF_ERROR;
}
if (ngx_close_file(file.fd) == NGX_FILE_ERROR) {
ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "push stream module: unable to close file \"%V\" for header template", value);
return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
}
// shared memory zone initializer
ngx_int_t
ngx_http_push_stream_init_global_shm_zone(ngx_shm_zone_t *shm_zone, void *data)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment