Commit a3bf3446 authored by Wandenberg's avatar Wandenberg

normalize use of backtrack, last_event_id and if_modified_since/if_none_match...

normalize use of backtrack, last_event_id and if_modified_since/if_none_match values to get old messages on all subscriber modes
parent ff405e3c
h1(#changelog). Changelog
* Normalize use of backtrack, last_event_id and if_modified_since/if_none_match values to get old messages on all subscriber modes
* Added push_stream_last_event_id directive to make possible pass the Last-Event-Id value without set header
* Changed push_stream_store_messages directive to make possible set it inside an if block
* Renamed broadcast feature to wildcard, more adequate with the way it works
** push_stream_broadcast_channel_prefix -> push_stream_wildcard_channel_prefix
......
......@@ -128,6 +128,7 @@ h1(#directives). Directives
| "push_stream_longpolling_connection_ttl":push_stream_longpolling_connection_ttl |   - |   - |   x |   - |   - |   - |
| "push_stream_last_received_message_time":push_stream_last_received_message_time |   - |   - |   x |   - |   - |   - |
| "push_stream_last_received_message_tag":push_stream_last_received_message_tag |   - |   - |   x |   - |   - |   - |
| "push_stream_last_event_id":push_stream_last_event_id |   - |   - |   x |   - |   - |   - |
| "push_stream_user_agent":push_stream_user_agent |   - |   - |   x |   - |   - |   - |
| "push_stream_padding_by_user_agent":push_stream_padding_by_user_agent |   - |   - |   x |   - |   - |   - |
| "push_stream_allowed_origins":push_stream_allowed_origins |   - |   - |   x |   - |   - |   - |
......@@ -231,6 +232,7 @@ h1(#contributors). Contributors
[push_stream_longpolling_connection_ttl]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_longpolling_connection_ttl
[push_stream_last_received_message_time]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_last_received_message_time
[push_stream_last_received_message_tag]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_last_received_message_tag
[push_stream_last_event_id]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_last_event_id
[push_stream_user_agent]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_user_agent
[push_stream_padding_by_user_agent]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/subscribers.textile#push_stream_padding_by_user_agent
[push_stream_store_messages]https://github.com/wandenberg/nginx-push-stream-module/blob/master/docs/directives/publishers.textile#push_stream_store_messages
......
......@@ -222,6 +222,19 @@ h2(#push_stream_last_received_message_tag). push_stream_last_received_message_ta
Set the tag of the last message received to the server knows which messages has to be sent to subscriber. Is a replacement for If-None-Match header. Example, $arg_tag indicate that the value will be take from tag argument.
h2(#push_stream_last_event_id). push_stream_last_event_id <a name="push_stream_last_event_id" href="#">&nbsp;</a>
*syntax:* _push_stream_last_event_id string_
*default:* _none_
*context:* _location_
*release version:* _0.4.0_
Set the last event id of a message to the server knows which messages has to be sent to subscriber. Is a replacement for Last-Event-Id header. Example, $arg_last_event indicate that the value will be take from last_event argument.
h2(#push_stream_user_agent). push_stream_user_agent <a name="push_stream_user_agent" href="#">&nbsp;</a>
*syntax:* _push_stream_user_agent string_
......
......@@ -83,6 +83,7 @@ typedef struct {
ngx_flag_t channel_info_on_publish;
ngx_http_complex_value_t *last_received_message_time;
ngx_http_complex_value_t *last_received_message_tag;
ngx_http_complex_value_t *last_event_id;
ngx_http_complex_value_t *user_agent;
ngx_str_t padding_by_user_agent;
ngx_http_push_stream_padding_t *paddings;
......
......@@ -227,6 +227,7 @@ ngx_http_push_stream_msg_t *ngx_http_push_stream_ping_msg = NULL;
ngx_http_push_stream_msg_t *ngx_http_push_stream_convert_char_to_msg_on_shared_locked(u_char *data, size_t len, ngx_http_push_stream_channel_t *channel, ngx_int_t id, ngx_str_t *event_id, ngx_str_t *event_type, ngx_pool_t *temp_pool);
static ngx_int_t ngx_http_push_stream_send_only_added_headers(ngx_http_request_t *r);
static void ngx_http_push_stream_add_polling_headers(ngx_http_request_t *r, time_t last_modified_time, ngx_int_t tag, ngx_pool_t *temp_pool);
static void ngx_http_push_stream_get_last_received_message_values(ngx_http_request_t *r, time_t *if_modified_since, ngx_int_t *tag, ngx_str_t **last_event_id);
static ngx_table_elt_t * ngx_http_push_stream_add_response_header(ngx_http_request_t *r, const ngx_str_t *header_name, const ngx_str_t *header_value);
static ngx_str_t * ngx_http_push_stream_get_header(ngx_http_request_t *r, const ngx_str_t *header_name);
static ngx_int_t ngx_http_push_stream_send_only_header_response(ngx_http_request_t *r, ngx_int_t status, const ngx_str_t *explain_error_message);
......
......@@ -40,6 +40,7 @@ module NginxConfiguration
:ping_message_text => nil,
:last_received_message_time => nil,
:last_received_message_tag => nil,
:last_event_id => nil,
:user_agent => nil,
:authorized_channels_only => 'off',
......@@ -136,6 +137,7 @@ http {
<%= write_directive("push_stream_last_received_message_time", last_received_message_time) %>
<%= write_directive("push_stream_last_received_message_tag", last_received_message_tag) %>
<%= write_directive("push_stream_last_event_id", last_event_id) %>
<%= write_directive("push_stream_channel_deleted_message_text", channel_deleted_message_text) %>
......
......@@ -314,49 +314,4 @@ describe "Subscriber Event Source" do
end
end
end
it "should get old messages by last event id" do
channel = 'ch_test_get_old_messages_by_last_event_id'
response = ''
nginx_run_server(config) do |conf|
EventMachine.run do
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 1'}), 'msg 1')
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 2'}), 'msg 2')
publish_message_inline(channel, headers, 'msg 3')
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 3'}), 'msg 4')
sub = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s).get :head => {'Last-Event-Id' => 'event 2' }
sub.stream do |chunk|
response += chunk
if response.include?("msg 4")
response.should eql("data: msg 3\r\n\r\nid: event 3\r\ndata: msg 4\r\n\r\n")
EventMachine.stop
end
end
end
end
end
it "should get old messages by last event id without found an event" do
channel = 'ch_test_get_old_messages_by_last_event_id_without_found_event'
response = ''
nginx_run_server(config.merge(:ping_message_interval => '1s')) do |conf|
EventMachine.run do
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 1'}), 'msg 1')
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 2'}), 'msg 2')
publish_message_inline(channel, headers, 'msg 3')
publish_message_inline(channel, headers.merge({'Event-Id' => 'event 3'}), 'msg 4')
sub = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s).get :head => {'Last-Event-Id' => 'event_not_found' }
sub.stream do |chunk|
if chunk.include?("-1")
chunk.should eql(": -1\r\n")
EventMachine.stop
end
end
end
end
end
end
......@@ -37,42 +37,7 @@ describe "Subscriber Properties" do
end
end
it "should disconnect after receive old messages by backtrack" do
channel = 'ch_test_disconnect_after_receive_old_messages_by_backtrack_when_longpolling_is_on'
response = ""
nginx_run_server(config) do |conf|
EventMachine.run do
publish_message_inline(channel, {}, 'msg 1')
publish_message_inline(channel, {}, 'msg 2')
publish_message_inline(channel, {}, 'msg 3')
publish_message_inline(channel, {}, 'msg 4')
sub = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s + '.b2').get :head => headers
sub.stream do |chunk|
response += chunk
end
sub.callback do |chunk|
response.should eql("msg 3\r\nmsg 4\r\n")
response = ''
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s).get :head => headers.merge({'If-Modified-Since' => sub.response_header['LAST_MODIFIED'], 'If-None-Match' => sub.response_header['ETAG']})
sub_1.stream do |chunk2|
response += chunk2
end
sub_1.callback do
response.should eql("msg 5\r\n")
EventMachine.stop
end
publish_message_inline(channel, {}, 'msg 5')
end
end
end
end
it "should disconnect after receive old messages by 'last_event_id'" do
it "should disconnect after receive old messages" do
channel = 'ch_test_disconnect_after_receive_old_messages_by_last_event_id_when_longpolling_is_on'
response = ""
......@@ -95,54 +60,6 @@ describe "Subscriber Properties" do
end
end
it "should disconnect after receive old messages from different channels" do
channel_1 = 'ch_test_receive_old_messages_from_different_channels_1'
channel_2 = 'ch_test_receive_old_messages_from_different_channels_2'
body = 'body'
response = ""
nginx_run_server(config) do |conf|
EventMachine.run do
publish_message_inline(channel_1, {}, body + "_1")
publish_message_inline(channel_2, {}, body + "_2")
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_2.to_s + '/' + channel_1.to_s).get :head => headers
sub_1.callback do
sub_1.should be_http_status(200)
sub_1.response_header['LAST_MODIFIED'].to_s.should_not eql("")
sub_1.response_header['ETAG'].to_s.should_not eql("")
sub_1.response.should eql("#{body}_2\r\n#{body}_1\r\n")
sent_headers = headers.merge({'If-Modified-Since' => sub_1.response_header['LAST_MODIFIED'], 'If-None-Match' => sub_1.response_header['ETAG']})
sub_2 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_2.to_s + '/' + channel_1.to_s).get :head => sent_headers
sub_2.callback do
sub_2.should be_http_status(200)
sub_2.response_header['LAST_MODIFIED'].to_s.should_not eql(sub_1.response_header['LAST_MODIFIED'])
sub_2.response_header['ETAG'].to_s.should eql("0")
sub_2.response.should eql("#{body}1_1\r\n")
sent_headers = headers.merge({'If-Modified-Since' => sub_2.response_header['LAST_MODIFIED'], 'If-None-Match' => sub_2.response_header['ETAG']})
sub_3 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_2.to_s + '/' + channel_1.to_s).get :head => sent_headers
sub_3.callback do
sub_3.should be_http_status(200)
sub_3.response_header['LAST_MODIFIED'].to_s.should_not eql(sub_2.response_header['LAST_MODIFIED'])
sub_3.response_header['ETAG'].to_s.should eql("0")
sub_3.response.should eql("#{body}1_2\r\n")
EventMachine.stop
end
sleep(1) # to publish the second message in a different second from the first
publish_message_inline(channel_2, {}, body + "1_2")
end
sleep(1) # to publish the second message in a different second from the first
publish_message_inline(channel_1, {}, body + "1_1")
end
end
end
end
it "should disconnect after timeout is reached" do
channel = 'ch_test_disconnect_long_polling_subscriber_when_longpolling_timeout_is_set'
......@@ -217,49 +134,6 @@ describe "Subscriber Properties" do
end
end
it "should receive messages with etag greather than recent message" do
channel = 'ch_test_receiving_messages_with_etag_greather_than_recent_message'
body_prefix = 'published message '
messagens_to_publish = 10
nginx_run_server(config.merge(:store_messages => "on", :message_template => '{\"id\":\"~id~\", \"message\":\"~text~\"}')) do |conf|
EventMachine.run do
i = 0
stored_messages = 0
EM.add_periodic_timer(0.001) do
if i < messagens_to_publish
i += 1
publish_message_inline(channel.to_s, headers, body_prefix + i.to_s)
else
end
end
EM.add_timer(1) do
pub = EventMachine::HttpRequest.new(nginx_address + '/pub?id=' + channel.to_s ).post :head => headers, :body => body_prefix + i.to_s
pub.callback do
response = JSON.parse(pub.response)
stored_messages = response["stored_messages"].to_i
end
end
EM.add_timer(2) do
sub = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s).get :head => headers.merge({'If-Modified-Since' => 'Thu, 1 Jan 1970 00:00:00 GMT', 'If-None-Match' => 0})
sub.callback do
sub.should be_http_status(200)
stored_messages.should eql(messagens_to_publish + 1)
messages = sub.response.split("\r\n")
messages.count.should eql(messagens_to_publish + 1)
messages.each_with_index do |content, index|
message = JSON.parse(content)
message["id"].to_i.should eql(index + 1)
end
EventMachine.stop
end
end
end
end
end
it "should receive messages when connected in more than one channel" do
channel_1 = 'ch_test_receiving_messages_when_connected_in_more_then_one_channel_1'
channel_2 = 'ch_test_receiving_messages_when_connected_in_more_then_one_channel_2'
......@@ -315,41 +189,6 @@ describe "Subscriber Properties" do
end
end
it "should accept send modified since and none match values without using header" do
channel = 'ch_test_send_modified_since_and_none_match_values_not_using_headers'
body = 'body'
response = ""
nginx_run_server(config.merge(:last_received_message_time => "$arg_time", :last_received_message_tag => "$arg_tag")) do |conf|
EventMachine.run do
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s).get :head => headers
sub_1.stream do |chunk|
response += chunk
end
sub_1.callback do |chunk|
response.should eql("#{body}\r\n")
time = sub_1.response_header['LAST_MODIFIED']
tag = sub_1.response_header['ETAG']
response = ""
sub_2 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel.to_s + '?time=' + time + '&tag=' + tag).get :head => headers
sub_2.stream do |chunk2|
response += chunk2
end
sub_2.callback do
response.should eql("#{body} 1\r\n")
EventMachine.stop
end
publish_message_inline(channel, {}, body + " 1")
end
publish_message_inline(channel, {}, body)
end
end
end
it "should accept a callback parameter to be used with JSONP" do
channel = 'ch_test_return_message_using_function_name_specified_in_callback_parameter'
body = 'body'
......@@ -423,7 +262,7 @@ describe "Subscriber Properties" do
end
end
it "should accpet return content gzipped" do
it "should accept return content gzipped" do
channel = 'ch_test_get_content_gzipped'
body = 'body'
actual_response = ''
......
This diff is collapsed.
......@@ -311,62 +311,6 @@ describe "Subscriber Properties" do
end
end
it "should receive old messages in multi channel subscriber" do
channel_1 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_1'
channel_2 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_2'
channel_3 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_3'
body = 'body'
response = ""
nginx_run_server(config.merge(:header_template => 'HEADER', :message_template => '{\"channel\":\"~channel~\", \"id\":\"~id~\", \"message\":\"~text~\"}')) do |conf|
#create channels with some messages
1.upto(3) do |i|
publish_message(channel_1, headers, body + i.to_s)
publish_message(channel_2, headers, body + i.to_s)
publish_message(channel_3, headers, body + i.to_s)
end
EventMachine.run do
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_1.to_s + '/' + channel_2.to_s + '.b5' + '/' + channel_3.to_s + '.b2').get :head => headers
sub_1.stream do |chunk|
response += chunk
lines = response.split("\r\n")
if lines.length >= 6
lines[0].should eql('HEADER')
line = JSON.parse(lines[1])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body1')
line['id'].to_i.should eql(1)
line = JSON.parse(lines[2])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body2')
line['id'].to_i.should eql(2)
line = JSON.parse(lines[3])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
line = JSON.parse(lines[4])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body2')
line['id'].to_i.should eql(2)
line = JSON.parse(lines[5])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
EventMachine.stop
end
end
end
end
end
it "should receive new messages in a multi channel subscriber" do
channel_1 = 'test_retreive_new_messages_in_multichannel_subscribe_1'
channel_2 = 'test_retreive_new_messages_in_multich_subscribe_2'
......@@ -430,138 +374,6 @@ describe "Subscriber Properties" do
end
end
it "should receive old messages in a multi channel subscriber using 'if_modified_since' header" do
channel_1 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_1'
channel_2 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_2'
channel_3 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_3'
body = 'body'
nginx_run_server(config.merge(:header_template => 'HEADER', :message_template => '{\"channel\":\"~channel~\", \"id\":\"~id~\", \"message\":\"~text~\"}'), :timeout => 40) do |conf|
#create channels with some messages with progressive interval (2,4,6,10,14,18,24,30,36 seconds)
1.upto(3) do |i|
sleep(i * 2)
publish_message(channel_1, headers, body + i.to_s)
sleep(i * 2)
publish_message(channel_2, headers, body + i.to_s)
sleep(i * 2)
publish_message(channel_3, headers, body + i.to_s)
end
#get messages published less then 20 seconds ago
t = Time.now
t = t - 20
sent_headers = headers.merge({'If-Modified-Since' => t.utc.strftime("%a, %d %b %Y %T %Z")})
response = ""
EventMachine.run do
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_1.to_s + '/' + channel_2.to_s + '/' + channel_3.to_s).get :head => sent_headers
sub_1.stream do |chunk|
response += chunk
lines = response.split("\r\n")
if lines.length >= 5
lines[0].should eql('HEADER')
line = JSON.parse(lines[1])
line['channel'].should eql(channel_1.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
line = JSON.parse(lines[2])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
line = JSON.parse(lines[3])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body2')
line['id'].to_i.should eql(2)
line = JSON.parse(lines[4])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
EventMachine.stop
end
end
end
end
end
it "should receive old messages in a multi channel subscriber using 'if_modified_since' header and backtrack mixed" do
channel_1 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_and_backtrack_mixed_1'
channel_2 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_and_backtrack_mixed_2'
channel_3 = 'ch_test_retreive_old_messages_in_multichannel_subscribe_using_if_modified_since_header_and_backtrack_mixed_3'
body = 'body'
nginx_run_server(config.merge(:header_template => 'HEADER', :message_template => '{\"channel\":\"~channel~\", \"id\":\"~id~\", \"message\":\"~text~\"}'), :timeout => 40) do |conf|
#create channels with some messages with progressive interval (2,4,6,10,14,18,24,30,36 seconds)
1.upto(3) do |i|
sleep(i * 2)
publish_message(channel_1, headers, body + i.to_s)
sleep(i * 2)
publish_message(channel_2, headers, body + i.to_s)
sleep(i * 2)
publish_message(channel_3, headers, body + i.to_s)
end
#get messages published less then 20 seconds ago
t = Time.now
t = t - 20
sent_headers = headers.merge({'If-Modified-Since' => t.utc.strftime("%a, %d %b %Y %T %Z")})
response = ""
EventMachine.run do
sub_1 = EventMachine::HttpRequest.new(nginx_address + '/sub/' + channel_1.to_s + '/' + channel_2.to_s + '.b5' + '/' + channel_3.to_s).get :head => sent_headers
sub_1.stream do |chunk|
response += chunk
lines = response.split("\r\n")
if lines.length >= 7
lines[0].should eql('HEADER')
line = JSON.parse(lines[1])
line['channel'].should eql(channel_1.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
line = JSON.parse(lines[2])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body1')
line['id'].to_i.should eql(1)
line = JSON.parse(lines[3])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body2')
line['id'].to_i.should eql(2)
line = JSON.parse(lines[4])
line['channel'].should eql(channel_2.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
line = JSON.parse(lines[5])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body2')
line['id'].to_i.should eql(2)
line = JSON.parse(lines[6])
line['channel'].should eql(channel_3.to_s)
line['message'].should eql('body3')
line['id'].to_i.should eql(3)
EventMachine.stop
end
end
end
end
end
it "should limit the number of channels" do
channel = 'ch_test_max_number_of_channels_'
......@@ -974,7 +786,7 @@ describe "Subscriber Properties" do
end
end
it "should accpet return content gzipped" do
it "should accept return content gzipped" do
channel = 'ch_test_get_content_gzipped'
body = 'body'
actual_response = ''
......
This diff is collapsed.
......@@ -206,6 +206,12 @@ static ngx_command_t ngx_http_push_stream_commands[] = {
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, last_received_message_tag),
NULL },
{ ngx_string("push_stream_last_event_id"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_set_complex_value_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_push_stream_loc_conf_t, last_event_id),
NULL },
{ ngx_string("push_stream_user_agent"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_http_set_complex_value_slot,
......@@ -522,6 +528,7 @@ ngx_http_push_stream_create_loc_conf(ngx_conf_t *cf)
lcf->channel_info_on_publish = NGX_CONF_UNSET_UINT;
lcf->last_received_message_time = NULL;
lcf->last_received_message_tag = NULL;
lcf->last_event_id = NULL;
lcf->user_agent = NULL;
lcf->padding_by_user_agent.data = NULL;
lcf->paddings = NULL;
......@@ -567,6 +574,10 @@ ngx_http_push_stream_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
conf->last_received_message_tag = prev->last_received_message_tag;
}
if (conf->last_event_id == NULL) {
conf->last_event_id = prev->last_event_id;
}
if (conf->user_agent == NULL) {
conf->user_agent = prev->user_agent;
}
......
......@@ -1454,6 +1454,43 @@ ngx_http_push_stream_add_polling_headers(ngx_http_request_t *r, time_t last_modi
}
}
static void
ngx_http_push_stream_get_last_received_message_values(ngx_http_request_t *r, time_t *if_modified_since, ngx_int_t *tag, ngx_str_t **last_event_id)
{
ngx_http_push_stream_subscriber_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_push_stream_module);
ngx_http_push_stream_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module);
ngx_str_t *etag = NULL, vv_etag = ngx_null_string;
ngx_str_t vv_event_id = ngx_null_string, vv_time = ngx_null_string;
if (cf->last_received_message_time != NULL) {
ngx_http_push_stream_complex_value(r, cf->last_received_message_time, &vv_time);
} else if (r->headers_in.if_modified_since != NULL) {
vv_time = r->headers_in.if_modified_since->value;
}
if (cf->last_received_message_tag != NULL) {
ngx_http_push_stream_complex_value(r, cf->last_received_message_tag, &vv_etag);
etag = vv_etag.len ? &vv_etag : NULL;
} else {
etag = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_IF_NONE_MATCH);
}
if (cf->last_event_id != NULL) {
ngx_http_push_stream_complex_value(r, cf->last_event_id, &vv_event_id);
if (vv_event_id.len) {
*last_event_id = ngx_http_push_stream_create_str(ctx->temp_pool, vv_event_id.len);
ngx_memcpy(((ngx_str_t *)*last_event_id)->data, vv_event_id.data, vv_event_id.len);
}
} else {
*last_event_id = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_LAST_EVENT_ID);
}
*if_modified_since = vv_time.len ? ngx_http_parse_time(vv_time.data, vv_time.len) : -1;
*tag = ((etag != NULL) && ((*tag = ngx_atoi(etag->data, etag->len)) != NGX_ERROR)) ? ngx_abs(*tag) : -1;
}
/**
* Copied from nginx code to only send headers added on this module code
* */
......
......@@ -40,6 +40,9 @@ ngx_http_push_stream_websocket_handler(ngx_http_request_t *r)
ngx_http_push_stream_subscriber_t *worker_subscriber;
ngx_http_push_stream_requested_channel_t *channels_ids, *cur;
ngx_http_push_stream_subscriber_ctx_t *ctx;
ngx_int_t tag;
time_t if_modified_since;
ngx_str_t *last_event_id = NULL;
ngx_int_t rc;
ngx_int_t status_code;
ngx_str_t *explain_error_message;
......@@ -88,6 +91,9 @@ ngx_http_push_stream_websocket_handler(ngx_http_request_t *r)
return ngx_http_push_stream_send_only_header_response(r, status_code, explain_error_message);
}
// get control values
ngx_http_push_stream_get_last_received_message_values(r, &if_modified_since, &tag, &last_event_id);
// stream access
if ((worker_subscriber = ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(r)) == NULL) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
......@@ -123,7 +129,7 @@ ngx_http_push_stream_websocket_handler(ngx_http_request_t *r)
// adding subscriber to channel(s) and send backtrack messages
cur = channels_ids;
while ((cur = (ngx_http_push_stream_requested_channel_t *) ngx_queue_next(&cur->queue)) != channels_ids) {
if (ngx_http_push_stream_subscriber_assign_channel(shpool, cf, r, cur, -1, NULL, worker_subscriber, ctx->temp_pool) != NGX_OK) {
if (ngx_http_push_stream_subscriber_assign_channel(shpool, cf, r, cur, if_modified_since, tag, last_event_id, worker_subscriber, ctx->temp_pool) != NGX_OK) {
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
}
......
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