Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
N
nginx-push-stream-module
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
nginx-push-stream-module
Commits
f0f2b472
Commit
f0f2b472
authored
Sep 10, 2011
by
Wandenberg Peixoto
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
adding polling and long-polling support
parent
78409d82
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
1248 additions
and
53 deletions
+1248
-53
CHANGELOG.textile
CHANGELOG.textile
+3
-0
README.textile
README.textile
+37
-2
ngx_http_push_stream_module.h
include/ngx_http_push_stream_module.h
+19
-0
ngx_http_push_stream_module_subscriber.h
include/ngx_http_push_stream_module_subscriber.h
+0
-3
ngx_http_push_stream_module_utils.h
include/ngx_http_push_stream_module_utils.h
+3
-2
ngx_http_push_stream_module_ipc.c
src/ngx_http_push_stream_module_ipc.c
+14
-1
ngx_http_push_stream_module_publisher.c
src/ngx_http_push_stream_module_publisher.c
+5
-0
ngx_http_push_stream_module_setup.c
src/ngx_http_push_stream_module_setup.c
+23
-2
ngx_http_push_stream_module_subscriber.c
src/ngx_http_push_stream_module_subscriber.c
+214
-42
ngx_http_push_stream_module_utils.c
src/ngx_http_push_stream_module_utils.c
+17
-0
ngx_http_push_stream_rbtree_util.c
src/ngx_http_push_stream_rbtree_util.c
+2
-0
base_test_case.rb
test/base_test_case.rb
+2
-1
test_setup_parameters.rb
test/test_setup_parameters.rb
+45
-0
test_subscriber_long_polling.rb
test/test_subscriber_long_polling.rb
+317
-0
test_subscriber_polling.rb
test/test_subscriber_polling.rb
+547
-0
No files found.
CHANGELOG.textile
View file @
f0f2b472
* Adding Polling support
* Adding Long Polling support
h2. Version 0.2.7
* Adding uptime information for server and workers on statistics
...
...
README.textile
View file @
f0f2b472
...
...
@@ -174,7 +174,7 @@ h3(#directives). Directives
(head). | directive | default value | values | context | location |
|push_stream_channels_statistics|-|-|location|-|
|push_stream_publisher|-|-|location|-|
|push_stream_subscriber|
-|-
|location|-|
|push_stream_subscriber|
streaming|streaming, polling, long-polling
|location|-|
|push_stream_max_reserved_memory|16 * ngx_pagesize|size greater than 16 * ngx_pagesize|http|main nginx configuration|
|push_stream_memory_cleanup_timeout|30 seconds|time constant|http|main nginx configuration|
|push_stream_channel_deleted_message_text|"Channel deleted"|any string|http|main nginx configuration|
...
...
@@ -247,10 +247,45 @@ POST, publish a message to the channel
h4(#push_stream_subscriber). push_stream_subscriber
default: streaming
context: location
values: streaming, polling, long-polling
Defines a location as a subscriber. This location represents a subscriber's interface to a channel's message queue.
This location only supports GET http method to receive published messages in a stream.
This location only supports GET http method to receive published messages.
And has three possible values to set push mode: streaming, polling, long-polling. The default values is streaming.
The polling and long-polling modes could be set by the request header *X-Nginx-PushStream-Mode* overriding push_stream_subscriber directive.
<pre>
<code>
location /sub/(.*) {
push_stream_subscriber;
# positional channel path
set $push_stream_channels_path $1;
}
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:polling' #polling request on a streaming location
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a streaming location
location /sub/(.*) {
push_stream_subscriber polling;
# positional channel path
set $push_stream_channels_path $1;
}
curl localhost/sub/ch1 #polling request
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:long-polling' #long-polling request on a polling location
location /sub/(.*) {
push_stream_subscriber long-polling;
# positional channel path
set $push_stream_channels_path $1;
}
curl localhost/sub/ch1 #long-polling request
curl localhost/sub/ch1 -H 'X-Nginx-PushStream-Mode:polling' #polling request on a logn-polling location
</code>
</pre>
h3(#functionality). Functionality
...
...
include/ngx_http_push_stream_module.h
View file @
f0f2b472
...
...
@@ -73,6 +73,7 @@ typedef struct {
ngx_uint_t
keepalive
;
ngx_uint_t
publisher_admin
;
ngx_flag_t
subscriber_eventsource
;
ngx_uint_t
subscriber_mode
;
}
ngx_http_push_stream_loc_conf_t
;
// shared memory segment name
...
...
@@ -86,6 +87,7 @@ typedef struct {
ngx_flag_t
deleted
;
ngx_int_t
id
;
ngx_str_t
*
raw
;
ngx_int_t
tag
;
ngx_str_t
*
event_id
;
ngx_str_t
*
event_id_message
;
ngx_str_t
*
formatted_messages
;
...
...
@@ -97,6 +99,7 @@ typedef struct ngx_http_push_stream_subscriber_cleanup_s ngx_http_push_stream_su
typedef
struct
{
ngx_queue_t
queue
;
// this MUST be first
ngx_http_request_t
*
request
;
ngx_flag_t
longpolling
;
}
ngx_http_push_stream_subscriber_t
;
typedef
struct
{
...
...
@@ -111,6 +114,8 @@ typedef struct {
ngx_rbtree_node_t
node
;
// this MUST be first
ngx_str_t
id
;
ngx_uint_t
last_message_id
;
time_t
last_message_time
;
ngx_int_t
last_message_tag
;
ngx_uint_t
stored_messages
;
ngx_uint_t
subscribers
;
ngx_http_push_stream_pid_queue_t
workers_with_subscribers
;
...
...
@@ -219,8 +224,22 @@ static const ngx_str_t NGX_HTTP_PUSH_STREAM_HEADER_EVENT_ID = ngx_string("Event
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_LAST_EVENT_ID
=
ngx_string
(
"Last-Event-Id"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_ALLOW
=
ngx_string
(
"Allow"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_EXPLAIN
=
ngx_string
(
"X-Nginx-PushStream-Explain"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_MODE
=
ngx_string
(
"X-Nginx-PushStream-Mode"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_TRANSFER_ENCODING
=
ngx_string
(
"Transfer-Encoding"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_CHUNCKED
=
ngx_string
(
"chunked"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_ETAG
=
ngx_string
(
"Etag"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_IF_NONE_MATCH
=
ngx_string
(
"If-None-Match"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_HEADER_VARY
=
ngx_string
(
"Vary"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_MODE_STREAMING
=
ngx_string
(
"streaming"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_MODE_POLLING
=
ngx_string
(
"polling"
);
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
=
ngx_string
(
"long-polling"
);
#define NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_STREAMING 0
#define NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_POLLING 1
#define NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_LONGPOLLING 2
// other stuff
static
const
ngx_str_t
NGX_HTTP_PUSH_STREAM_ALLOW_GET_POST_DELETE_METHODS
=
ngx_string
(
"GET, POST, DELETE"
);
...
...
include/ngx_http_push_stream_module_subscriber.h
View file @
f0f2b472
...
...
@@ -37,7 +37,4 @@ ngx_http_push_stream_requested_channel_t * ngx_http_push_stream_parse_channels_i
static
void
ngx_http_push_stream_subscriber_cleanup
(
ngx_http_push_stream_subscriber_cleanup_t
*
data
);
static
ngx_int_t
ngx_http_push_stream_subscriber_assign_channel
(
ngx_slab_pool_t
*
shpool
,
ngx_http_push_stream_loc_conf_t
*
cf
,
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
requested_channel
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_pool_t
*
temp_pool
);
#endif
/* NGX_HTTP_PUSH_STREAM_MODULE_SUBSCRIBER_H_ */
include/ngx_http_push_stream_module_utils.h
View file @
f0f2b472
...
...
@@ -215,6 +215,7 @@ ngx_http_push_stream_msg_t *ngx_http_push_stream_ping_msg = NULL;
// general request handling
ngx_http_push_stream_msg_t
*
ngx_http_push_stream_convert_buffer_to_msg_on_shared_locked
(
ngx_buf_t
*
buf
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_int_t
id
,
ngx_str_t
*
event_id
,
ngx_pool_t
*
temp_pool
);
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_pool_t
*
temp_pool
);
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
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
);
...
...
src/ngx_http_push_stream_module_ipc.c
View file @
f0f2b472
...
...
@@ -449,7 +449,20 @@ ngx_http_push_stream_respond_to_subscribers(ngx_http_push_stream_channel_t *chan
// now let's respond to some requests!
while
((
cur
=
(
ngx_http_push_stream_subscriber_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
sentinel
)
{
if
(
cur
->
longpolling
)
{
ngx_http_push_stream_subscriber_t
*
prev
=
(
ngx_http_push_stream_subscriber_t
*
)
ngx_queue_prev
(
&
cur
->
queue
);
ngx_http_push_stream_add_polling_headers
(
cur
->
request
,
msg
->
time
,
msg
->
tag
,
cur
->
request
->
pool
);
ngx_http_send_header
(
cur
->
request
);
ngx_http_push_stream_send_response_content_header
(
cur
->
request
,
ngx_http_get_module_loc_conf
(
cur
->
request
,
ngx_http_push_stream_module
));
ngx_http_push_stream_send_response_message
(
cur
->
request
,
channel
,
msg
);
ngx_http_push_stream_send_response_finalize
(
cur
->
request
);
cur
=
prev
;
}
else
{
ngx_http_push_stream_send_response_message
(
cur
->
request
,
channel
,
msg
);
}
}
}
...
...
src/ngx_http_push_stream_module_publisher.c
View file @
f0f2b472
...
...
@@ -207,7 +207,9 @@ ngx_http_push_stream_publisher_body_handler(ngx_http_request_t *r)
// put messages on the queue
if
(
cf
->
store_messages
)
{
// tag message with time stamp and a sequence tag
msg
->
time
=
ngx_time
();
msg
->
tag
=
(
msg
->
time
==
channel
->
last_message_time
)
?
(
channel
->
last_message_tag
+
1
)
:
0
;
// set message expiration time
msg
->
expires
=
(
cf
->
buffer_timeout
==
NGX_CONF_UNSET
?
0
:
(
ngx_time
()
+
cf
->
buffer_timeout
));
ngx_queue_insert_tail
(
&
channel
->
message_queue
.
queue
,
&
msg
->
queue
);
...
...
@@ -215,6 +217,9 @@ ngx_http_push_stream_publisher_body_handler(ngx_http_request_t *r)
// now see if the queue is too big
ngx_http_push_stream_ensure_qtd_of_messages_locked
(
channel
,
cf
->
max_messages
,
0
);
channel
->
last_message_time
=
msg
->
time
;
channel
->
last_message_tag
=
msg
->
tag
;
}
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
...
...
src/ngx_http_push_stream_module_setup.c
View file @
f0f2b472
...
...
@@ -39,10 +39,10 @@ static ngx_command_t ngx_http_push_stream_commands[] = {
0
,
NULL
},
{
ngx_string
(
"push_stream_subscriber"
),
NGX_HTTP_SRV_CONF
|
NGX_HTTP_LOC_CONF
|
NGX_CONF_NOARGS
,
NGX_HTTP_SRV_CONF
|
NGX_HTTP_LOC_CONF
|
NGX_CONF_NOARGS
|
NGX_CONF_TAKE1
,
ngx_http_push_stream_subscriber
,
NGX_HTTP_LOC_CONF_OFFSET
,
0
,
offsetof
(
ngx_http_push_stream_loc_conf_t
,
subscriber_mode
)
,
NULL
},
{
ngx_string
(
"push_stream_max_reserved_memory"
),
NGX_HTTP_MAIN_CONF
|
NGX_CONF_TAKE1
,
...
...
@@ -404,6 +404,7 @@ ngx_http_push_stream_create_loc_conf(ngx_conf_t *cf)
lcf
->
keepalive
=
NGX_CONF_UNSET_UINT
;
lcf
->
publisher_admin
=
NGX_CONF_UNSET_UINT
;
lcf
->
subscriber_eventsource
=
NGX_CONF_UNSET_UINT
;
lcf
->
subscriber_mode
=
NGX_CONF_UNSET_UINT
;
return
lcf
;
}
...
...
@@ -650,6 +651,26 @@ ngx_http_push_stream_publisher(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static
char
*
ngx_http_push_stream_subscriber
(
ngx_conf_t
*
cf
,
ngx_command_t
*
cmd
,
void
*
conf
)
{
ngx_int_t
*
field
=
(
ngx_int_t
*
)
((
char
*
)
conf
+
cmd
->
offset
);
if
(
*
field
!=
NGX_CONF_UNSET
)
{
return
"is duplicate"
;
}
*
field
=
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_STREAMING
;
//default
if
(
cf
->
args
->
nelts
>
1
)
{
ngx_str_t
value
=
(((
ngx_str_t
*
)
cf
->
args
->
elts
)[
1
]);
if
((
value
.
len
==
NGX_HTTP_PUSH_STREAM_MODE_STREAMING
.
len
)
&&
(
ngx_strncasecmp
(
value
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_STREAMING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_STREAMING
.
len
)
==
0
))
{
*
field
=
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_STREAMING
;
}
else
if
((
value
.
len
==
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
len
)
&&
(
ngx_strncasecmp
(
value
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
len
)
==
0
))
{
*
field
=
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_POLLING
;
}
else
if
((
value
.
len
==
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
len
)
&&
(
ngx_strncasecmp
(
value
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
len
)
==
0
))
{
*
field
=
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_LONGPOLLING
;
}
else
{
ngx_conf_log_error
(
NGX_LOG_ERR
,
cf
,
0
,
"invalid push_stream_subscriber mode value: %V, accepted values (%s, %s, %s)"
,
&
value
,
NGX_HTTP_PUSH_STREAM_MODE_STREAMING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
data
);
return
NGX_CONF_ERROR
;
}
}
char
*
rc
=
ngx_http_push_stream_setup_handler
(
cf
,
conf
,
&
ngx_http_push_stream_subscriber_handler
);
if
(
rc
==
NGX_CONF_OK
)
{
...
...
src/ngx_http_push_stream_module_subscriber.c
View file @
f0f2b472
...
...
@@ -25,12 +25,15 @@
#include <ngx_http_push_stream_module_subscriber.h>
static
ngx_int_t
ngx_http_push_stream_subscriber_assign_channel
(
ngx_slab_pool_t
*
shpool
,
ngx_http_push_stream_loc_conf_t
*
cf
,
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
requested_channel
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_pool_t
*
temp_pool
);
static
ngx_http_push_stream_worker_subscriber_t
*
ngx_http_push_stream_subscriber_prepare_request_to_keep_connected
(
ngx_http_request_t
*
r
);
static
void
ngx_http_push_stream_registry_subscriber_locked
(
ngx_http_push_stream_worker_subscriber_t
*
worker_subscriber
);
static
void
ngx_http_push_stream_send_old_messages
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
);
static
ngx_flag_t
ngx_http_push_stream_has_old_messages_to_send
(
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_int_t
tag
,
time_t
greater_message_time
,
ngx_int_t
greater_message_tag
,
ngx_str_t
*
last_event_id
);
static
void
ngx_http_push_stream_send_old_messages
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_int_t
tag
,
time_t
greater_message_time
,
ngx_int_t
greater_message_tag
,
ngx_str_t
*
last_event_id
);
static
ngx_http_push_stream_pid_queue_t
*
ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked
(
ngx_slab_pool_t
*
shpool
,
ngx_str_t
*
channel_id
,
ngx_log_t
*
log
);
static
ngx_http_push_stream_subscription_t
*
ngx_http_push_stream_create_channel_subscription
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
);
static
ngx_int_t
ngx_http_push_stream_assing_subscription_to_channel_locked
(
ngx_str_t
*
channel_id
,
ngx_http_push_stream_subscription_t
*
subscription
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_http_push_stream_pid_queue_t
*
worker_subscribers_sentinel
,
ngx_log_t
*
log
);
static
ngx_http_push_stream_subscription_t
*
ngx_http_push_stream_create_channel_subscription
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_flag_t
longpolling
);
static
ngx_int_t
ngx_http_push_stream_assing_subscription_to_channel_locked
(
ngx_slab_pool_t
*
shpool
,
ngx_str_t
*
channel_id
,
ngx_http_push_stream_subscription_t
*
subscription
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_log_t
*
log
);
static
ngx_int_t
ngx_http_push_stream_subscriber_polling_handler
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
channels_ids
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_flag_t
longpolling
,
ngx_pool_t
*
temp_pool
);
static
ngx_int_t
ngx_http_push_stream_subscriber_handler
(
ngx_http_request_t
*
r
)
...
...
@@ -46,6 +49,8 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
ngx_http_push_stream_channel_t
*
channel
;
time_t
if_modified_since
;
ngx_str_t
*
last_event_id
;
ngx_str_t
*
push_mode
;
ngx_flag_t
polling
,
longpolling
;
// only accept GET method
if
(
!
(
r
->
method
&
NGX_HTTP_GET
))
{
...
...
@@ -122,9 +127,21 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
}
}
if_modified_since
=
(
r
->
headers_in
.
if_modified_since
!=
NULL
)
?
ngx_http_parse_time
(
r
->
headers_in
.
if_modified_since
->
value
.
data
,
r
->
headers_in
.
if_modified_since
->
value
.
len
)
:
0
;
// get control headers
if_modified_since
=
(
r
->
headers_in
.
if_modified_since
!=
NULL
)
?
ngx_http_parse_time
(
r
->
headers_in
.
if_modified_since
->
value
.
data
,
r
->
headers_in
.
if_modified_since
->
value
.
len
)
:
-
1
;
last_event_id
=
ngx_http_push_stream_get_header
(
r
,
&
NGX_HTTP_PUSH_STREAM_HEADER_LAST_EVENT_ID
);
push_mode
=
ngx_http_push_stream_get_header
(
r
,
&
NGX_HTTP_PUSH_STREAM_HEADER_MODE
);
polling
=
((
cf
->
subscriber_mode
==
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_POLLING
)
||
((
push_mode
!=
NULL
)
&&
(
push_mode
->
len
==
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
len
)
&&
(
ngx_strncasecmp
(
push_mode
->
data
,
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_POLLING
.
len
)
==
0
)));
longpolling
=
((
cf
->
subscriber_mode
==
NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_LONGPOLLING
)
||
((
push_mode
!=
NULL
)
&&
(
push_mode
->
len
==
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
len
)
&&
(
ngx_strncasecmp
(
push_mode
->
data
,
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
data
,
NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING
.
len
)
==
0
)));
if
(
polling
||
longpolling
)
{
ngx_int_t
result
=
ngx_http_push_stream_subscriber_polling_handler
(
r
,
channels_ids
,
if_modified_since
,
last_event_id
,
longpolling
,
temp_pool
);
ngx_destroy_pool
(
temp_pool
);
return
result
;
}
// stream access
if
((
worker_subscriber
=
ngx_http_push_stream_subscriber_prepare_request_to_keep_connected
(
r
))
==
NULL
)
{
ngx_destroy_pool
(
temp_pool
);
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
...
...
@@ -139,7 +156,6 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
}
ngx_shmtx_lock
(
&
shpool
->
mutex
);
ngx_http_push_stream_registry_subscriber_locked
(
worker_subscriber
);
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
...
...
@@ -162,46 +178,148 @@ ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r)
}
static
ngx_int_t
ngx_http_push_stream_subscriber_
assign_channel
(
ngx_slab_pool_t
*
shpool
,
ngx_http_push_stream_loc_conf_t
*
cf
,
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
requested_channel
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_pool_t
*
temp_pool
)
ngx_http_push_stream_subscriber_
polling_handler
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
channels_ids
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_flag_t
longpolling
,
ngx_pool_t
*
temp_pool
)
{
ngx_http_push_stream_pid_queue_t
*
cur
,
*
worker_subscribers_sentinel
=
NULL
;
ngx_http_push_stream_loc_conf_t
*
cf
=
ngx_http_get_module_loc_conf
(
r
,
ngx_http_push_stream_module
);
ngx_slab_pool_t
*
shpool
=
(
ngx_slab_pool_t
*
)
ngx_http_push_stream_shm_zone
->
shm
.
addr
;
ngx_http_push_stream_requested_channel_t
*
cur
;
ngx_http_push_stream_worker_subscriber_t
*
worker_subscriber
;
ngx_http_push_stream_channel_t
*
channel
;
ngx_http_push_stream_subscription_t
*
subscription
;
ngx_int_t
result
;
ngx_str_t
*
etag
=
ngx_http_push_stream_get_header
(
r
,
&
NGX_HTTP_PUSH_STREAM_HEADER_IF_NONE_MATCH
);
ngx_int_t
tag
=
((
etag
!=
NULL
)
&&
((
tag
=
ngx_atoi
(
etag
->
data
,
etag
->
len
))
!=
NGX_ERROR
))
?
ngx_abs
(
tag
)
:
-
1
;
time_t
greater_message_time
;
ngx_int_t
greater_message_tag
=
tag
;
ngx_flag_t
has_message_to_send
=
0
;
if
((
channel
=
ngx_http_push_stream_find_channel
(
requested_channel
->
id
,
r
->
connection
->
log
))
==
NULL
)
{
greater_message_time
=
if_modified_since
=
(
if_modified_since
<
0
)
?
0
:
if_modified_since
;
ngx_shmtx_lock
(
&
shpool
->
mutex
);
// check if has any message to send
cur
=
channels_ids
;
while
((
cur
=
(
ngx_http_push_stream_requested_channel_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
channels_ids
)
{
channel
=
ngx_http_push_stream_find_channel_locked
(
cur
->
id
,
r
->
connection
->
log
);
if
(
channel
==
NULL
)
{
// channel not found
ngx_log_error
(
NGX_LOG_ERR
,
r
->
connection
->
log
,
0
,
"push stream module: unable to allocate shared memory for channel %s"
,
requested_channel
->
id
->
data
);
return
NGX_ERROR
;
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
ngx_log_error
(
NGX_LOG_ERR
,
r
->
connection
->
log
,
0
,
"push stream module: unable to allocate shared memory for channel %s"
,
cur
->
id
->
data
);
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
}
cur
=
&
channel
->
workers_with_subscribers
;
if
(
ngx_http_push_stream_has_old_messages_to_send
(
channel
,
cur
->
backtrack_messages
,
if_modified_since
,
tag
,
greater_message_time
,
greater_message_tag
,
last_event_id
))
{
has_message_to_send
=
1
;
if
(
channel
->
last_message_time
>
greater_message_time
)
{
greater_message_time
=
channel
->
last_message_time
;
greater_message_tag
=
channel
->
last_message_tag
;
}
else
{
if
((
channel
->
last_message_time
==
greater_message_time
)
&&
(
channel
->
last_message_tag
>
greater_message_tag
)
)
{
greater_message_tag
=
channel
->
last_message_tag
;
}
}
}
}
while
((
cur
=
(
ngx_http_push_stream_pid_queue_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
&
channel
->
workers_with_subscribers
)
{
if
(
cur
->
pid
==
ngx_pid
)
{
worker_subscribers_sentinel
=
cur
;
break
;
if
(
longpolling
&&
!
has_message_to_send
)
{
// long polling mode without messages
if
((
worker_subscriber
=
ngx_http_push_stream_subscriber_prepare_request_to_keep_connected
(
r
))
==
NULL
)
{
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
}
ngx_http_push_stream_registry_subscriber_locked
(
worker_subscriber
);
// adding subscriber to channel(s)
cur
=
channels_ids
;
while
((
cur
=
(
ngx_http_push_stream_requested_channel_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
channels_ids
)
{
if
((
channel
=
ngx_http_push_stream_find_channel_locked
(
cur
->
id
,
r
->
connection
->
log
))
==
NULL
)
{
// channel not found
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
ngx_log_error
(
NGX_LOG_ERR
,
r
->
connection
->
log
,
0
,
"push stream module: unable to allocate shared memory for channel %s"
,
cur
->
id
->
data
);
return
NGX_ERROR
;
}
if
(
worker_subscribers_sentinel
==
NULL
)
{
// found nothing
ngx_shmtx_lock
(
&
shpool
->
mutex
);
worker_subscribers_sentinel
=
ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked
(
shpool
,
requested_channel
->
id
,
r
->
connection
->
log
);
if
((
subscription
=
ngx_http_push_stream_create_channel_subscription
(
r
,
channel
,
longpolling
))
==
NULL
)
{
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
if
(
worker_subscribers_sentinel
==
NULL
)
{
return
NGX_ERROR
;
}
ngx_http_push_stream_assing_subscription_to_channel_locked
(
shpool
,
cur
->
id
,
subscription
,
&
worker_subscriber
->
subscriptions_sentinel
,
r
->
connection
->
log
);
}
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
return
NGX_DONE
;
}
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
// polling or long polling without messages to send
ngx_http_push_stream_add_polling_headers
(
r
,
greater_message_time
,
greater_message_tag
,
temp_pool
);
if
(
!
has_message_to_send
)
{
// polling subscriber requests get a 304 with their entity tags preserved if don't have new messages.
return
ngx_http_push_stream_send_only_header_response
(
r
,
NGX_HTTP_NOT_MODIFIED
,
NULL
);
}
// polling with messages or long polling without messages to send
r
->
headers_out
.
content_type
=
cf
->
content_type
;
r
->
headers_out
.
status
=
NGX_HTTP_OK
;
r
->
headers_out
.
content_length_n
=
-
1
;
ngx_http_push_stream_add_response_header
(
r
,
&
NGX_HTTP_PUSH_STREAM_HEADER_TRANSFER_ENCODING
,
&
NGX_HTTP_PUSH_STREAM_HEADER_CHUNCKED
);
ngx_http_send_header
(
r
);
// sending response content header
if
(
ngx_http_push_stream_send_response_content_header
(
r
,
cf
)
==
NGX_ERROR
)
{
ngx_log_error
(
NGX_LOG_ERR
,
(
r
)
->
connection
->
log
,
0
,
"push stream module: could not send content header to subscriber"
);
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
}
cur
=
channels_ids
;
while
((
cur
=
(
ngx_http_push_stream_requested_channel_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
channels_ids
)
{
channel
=
ngx_http_push_stream_find_channel_locked
(
cur
->
id
,
r
->
connection
->
log
);
if
(
channel
==
NULL
)
{
// channel not found
ngx_log_error
(
NGX_LOG_ERR
,
r
->
connection
->
log
,
0
,
"push stream module: unable to allocate shared memory for channel %s"
,
cur
->
id
->
data
);
return
NGX_HTTP_INTERNAL_SERVER_ERROR
;
}
ngx_http_push_stream_send_old_messages
(
r
,
channel
,
cur
->
backtrack_messages
,
if_modified_since
,
tag
,
greater_message_time
,
greater_message_tag
,
last_event_id
);
}
if
(
cf
->
footer_template
.
len
>
0
)
{
ngx_http_push_stream_send_response_text
(
r
,
cf
->
footer_template
.
data
,
cf
->
footer_template
.
len
,
0
);
}
ngx_http_push_stream_send_response_text
(
r
,
NGX_HTTP_PUSH_STREAM_LAST_CHUNK
.
data
,
NGX_HTTP_PUSH_STREAM_LAST_CHUNK
.
len
,
1
);
return
NGX_OK
;
}
static
ngx_int_t
ngx_http_push_stream_subscriber_assign_channel
(
ngx_slab_pool_t
*
shpool
,
ngx_http_push_stream_loc_conf_t
*
cf
,
ngx_http_request_t
*
r
,
ngx_http_push_stream_requested_channel_t
*
requested_channel
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_pool_t
*
temp_pool
)
{
ngx_http_push_stream_channel_t
*
channel
;
ngx_http_push_stream_subscription_t
*
subscription
;
ngx_int_t
result
;
if
((
channel
=
ngx_http_push_stream_find_channel
(
requested_channel
->
id
,
r
->
connection
->
log
))
==
NULL
)
{
// channel not found
ngx_log_error
(
NGX_LOG_ERR
,
r
->
connection
->
log
,
0
,
"push stream module: unable to allocate shared memory for channel %s"
,
requested_channel
->
id
->
data
);
return
NGX_ERROR
;
}
if
((
subscription
=
ngx_http_push_stream_create_channel_subscription
(
r
,
channel
))
==
NULL
)
{
if
((
subscription
=
ngx_http_push_stream_create_channel_subscription
(
r
,
channel
,
0
))
==
NULL
)
{
return
NGX_ERROR
;
}
// send old messages to new subscriber
ngx_http_push_stream_send_old_messages
(
r
,
channel
,
requested_channel
->
backtrack_messages
,
if_modified_since
,
last_event_id
);
ngx_http_push_stream_send_old_messages
(
r
,
channel
,
requested_channel
->
backtrack_messages
,
if_modified_since
,
0
,
0
,
-
1
,
last_event_id
);
ngx_shmtx_lock
(
&
shpool
->
mutex
);
result
=
ngx_http_push_stream_assing_subscription_to_channel_locked
(
requested_channel
->
id
,
subscription
,
subscriptions_sentinel
,
worker_subscriber
s_sentinel
,
r
->
connection
->
log
);
result
=
ngx_http_push_stream_assing_subscription_to_channel_locked
(
shpool
,
requested_channel
->
id
,
subscription
,
subscription
s_sentinel
,
r
->
connection
->
log
);
ngx_shmtx_unlock
(
&
shpool
->
mutex
);
return
result
;
...
...
@@ -365,27 +483,52 @@ ngx_http_push_stream_registry_subscriber_locked(ngx_http_push_stream_worker_subs
thisworker_data
->
subscribers
++
;
}
static
void
ngx_http_push_stream_
send_old_messages
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_str_t
*
last_event_id
)
static
ngx_flag_t
ngx_http_push_stream_
has_old_messages_to_send
(
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_int_t
tag
,
time_t
greater_message_time
,
ngx_int_t
greater_message_tag
,
ngx_str_t
*
last_event_id
)
{
ngx_flag_t
old_messages
=
0
;
ngx_http_push_stream_msg_t
*
message
,
*
message_sentinel
;
if
(
channel
->
stored_messages
>
0
)
{
message_sentinel
=
&
channel
->
message_queue
;
message
=
message_sentinel
;
if
(
last_event_id
!=
NULL
)
{
if
(
channel
->
stored_messages
>
0
)
{
if
(
backtrack
>
0
)
{
old_messages
=
1
;
}
else
if
((
last_event_id
!=
NULL
)
||
(
if_modified_since
>=
0
))
{
ngx_flag_t
found
=
0
;
while
((
!
message
->
deleted
)
&&
((
message
=
(
ngx_http_push_stream_msg_t
*
)
ngx_queue_next
(
&
message
->
queue
))
!=
message_sentinel
))
{
if
((
!
found
)
&&
(
message
->
event_id
!=
NULL
)
&&
(
ngx_memn2cmp
(
message
->
event_id
->
data
,
last_event_id
->
data
,
message
->
event_id
->
len
,
last_event_id
->
len
)
==
0
))
{
if
((
!
found
)
&&
(
last_event_id
!=
NULL
)
&&
(
message
->
event_id
!=
NULL
)
&&
(
ngx_memn2cmp
(
message
->
event_id
->
data
,
last_event_id
->
data
,
message
->
event_id
->
len
,
last_event_id
->
len
)
==
0
))
{
found
=
1
;
continue
;
}
if
((
!
found
)
&&
(
last_event_id
==
NULL
)
&&
(
if_modified_since
>=
0
)
&&
((
message
->
time
>
if_modified_since
)
||
((
message
->
time
==
if_modified_since
)
&&
(
tag
>=
0
)
&&
(
message
->
tag
>=
tag
))))
{
found
=
1
;
if
((
message
->
time
==
if_modified_since
)
&&
(
message
->
tag
==
tag
))
{
continue
;
}
}
if
(
found
)
{
ngx_http_push_stream_send_response_message
(
r
,
channel
,
message
);
old_messages
=
1
;
break
;
}
}
}
else
{
}
}
return
old_messages
;
}
static
void
ngx_http_push_stream_send_old_messages
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_uint_t
backtrack
,
time_t
if_modified_since
,
ngx_int_t
tag
,
time_t
greater_message_time
,
ngx_int_t
greater_message_tag
,
ngx_str_t
*
last_event_id
)
{
ngx_http_push_stream_msg_t
*
message
,
*
message_sentinel
;
if
(
ngx_http_push_stream_has_old_messages_to_send
(
channel
,
backtrack
,
if_modified_since
,
tag
,
greater_message_time
,
greater_message_tag
,
last_event_id
))
{
message_sentinel
=
&
channel
->
message_queue
;
message
=
message_sentinel
;
if
(
backtrack
>
0
)
{
ngx_uint_t
qtd
=
(
backtrack
>
channel
->
stored_messages
)
?
channel
->
stored_messages
:
backtrack
;
ngx_uint_t
start
=
channel
->
stored_messages
-
qtd
;
// positioning at first message, and send the others
...
...
@@ -397,12 +540,23 @@ ngx_http_push_stream_send_old_messages(ngx_http_request_t *r, ngx_http_push_stre
start
--
;
}
}
if
((
backtrack
==
0
)
&&
(
if_modified_since
!=
0
))
{
}
else
if
((
last_event_id
!=
NULL
)
||
(
if_modified_since
>=
0
))
{
ngx_flag_t
found
=
0
;
while
((
!
message
->
deleted
)
&&
((
message
=
(
ngx_http_push_stream_msg_t
*
)
ngx_queue_next
(
&
message
->
queue
))
!=
message_sentinel
))
{
if
(
message
->
time
>
if_modified_since
)
{
ngx_http_push_stream_send_response_message
(
r
,
channel
,
message
);
if
((
!
found
)
&&
(
last_event_id
!=
NULL
)
&&
(
message
->
event_id
!=
NULL
)
&&
(
ngx_memn2cmp
(
message
->
event_id
->
data
,
last_event_id
->
data
,
message
->
event_id
->
len
,
last_event_id
->
len
)
==
0
))
{
found
=
1
;
continue
;
}
if
((
!
found
)
&&
(
last_event_id
==
NULL
)
&&
(
if_modified_since
>=
0
)
&&
((
message
->
time
>
if_modified_since
)
||
((
message
->
time
==
if_modified_since
)
&&
(
tag
>=
0
)
&&
(
message
->
tag
>=
tag
))))
{
found
=
1
;
if
((
message
->
time
==
if_modified_since
)
&&
(
message
->
tag
==
tag
))
{
continue
;
}
}
if
(
found
&&
(((
greater_message_time
==
0
)
&&
(
greater_message_tag
==
-
1
))
||
((
greater_message_time
>=
message
->
time
)
&&
(
greater_message_tag
>=
message
->
tag
))))
{
ngx_http_push_stream_send_response_message
(
r
,
channel
,
message
);
}
}
}
...
...
@@ -437,7 +591,7 @@ ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked(ngx_slab_p
}
static
ngx_http_push_stream_subscription_t
*
ngx_http_push_stream_create_channel_subscription
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
)
ngx_http_push_stream_create_channel_subscription
(
ngx_http_request_t
*
r
,
ngx_http_push_stream_channel_t
*
channel
,
ngx_flag_t
longpolling
)
{
ngx_http_push_stream_subscription_t
*
subscription
;
ngx_http_push_stream_subscriber_t
*
subscriber
;
...
...
@@ -453,6 +607,7 @@ ngx_http_push_stream_create_channel_subscription(ngx_http_request_t *r, ngx_http
}
subscriber
->
request
=
r
;
subscriber
->
longpolling
=
longpolling
;
subscription
->
channel
=
channel
;
subscription
->
subscriber
=
subscriber
;
...
...
@@ -461,8 +616,9 @@ ngx_http_push_stream_create_channel_subscription(ngx_http_request_t *r, ngx_http
}
static
ngx_int_t
ngx_http_push_stream_assing_subscription_to_channel_locked
(
ngx_s
tr_t
*
channel_id
,
ngx_http_push_stream_subscription_t
*
subscription
,
ngx_http_push_stream_subscription_t
*
subscriptions_sentinel
,
ngx_http_push_stream_pid_queue_t
*
worker_subscriber
s_sentinel
,
ngx_log_t
*
log
)
ngx_http_push_stream_assing_subscription_to_channel_locked
(
ngx_s
lab_pool_t
*
shpool
,
ngx_str_t
*
channel_id
,
ngx_http_push_stream_subscription_t
*
subscription
,
ngx_http_push_stream_subscription_t
*
subscription
s_sentinel
,
ngx_log_t
*
log
)
{
ngx_http_push_stream_pid_queue_t
*
cur
,
*
worker_subscribers_sentinel
=
NULL
;
ngx_http_push_stream_channel_t
*
channel
;
// check if channel still exists
...
...
@@ -470,6 +626,22 @@ ngx_http_push_stream_assing_subscription_to_channel_locked(ngx_str_t *channel_id
ngx_log_error
(
NGX_LOG_ERR
,
log
,
0
,
"push stream module: something goes very wrong, arrived on ngx_http_push_stream_subscriber_assign_channel without created channel %s"
,
channel_id
->
data
);
return
NGX_ERROR
;
}
cur
=
&
channel
->
workers_with_subscribers
;
while
((
cur
=
(
ngx_http_push_stream_pid_queue_t
*
)
ngx_queue_next
(
&
cur
->
queue
))
!=
&
channel
->
workers_with_subscribers
)
{
if
(
cur
->
pid
==
ngx_pid
)
{
worker_subscribers_sentinel
=
cur
;
break
;
}
}
if
(
worker_subscribers_sentinel
==
NULL
)
{
// found nothing
worker_subscribers_sentinel
=
ngx_http_push_stream_create_worker_subscriber_channel_sentinel_locked
(
shpool
,
channel_id
,
log
);
if
(
worker_subscribers_sentinel
==
NULL
)
{
return
NGX_ERROR
;
}
}
channel
->
subscribers
++
;
// do this only when we know everything went okay
ngx_queue_insert_tail
(
&
subscriptions_sentinel
->
queue
,
&
subscription
->
queue
);
ngx_queue_insert_tail
(
&
worker_subscribers_sentinel
->
subscriber_sentinel
.
queue
,
&
subscription
->
subscriber
->
queue
);
...
...
src/ngx_http_push_stream_module_utils.c
View file @
f0f2b472
...
...
@@ -1113,3 +1113,20 @@ ngx_http_push_stream_apply_template_to_each_line(ngx_str_t *text, const ngx_str_
return
result
;
}
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
)
{
if
(
last_modified_time
>
0
)
{
r
->
headers_out
.
last_modified_time
=
last_modified_time
;
}
if
(
tag
>=
0
)
{
ngx_str_t
*
etag
=
ngx_http_push_stream_create_str
(
temp_pool
,
NGX_INT_T_LEN
);
if
(
etag
!=
NULL
)
{
ngx_sprintf
(
etag
->
data
,
"%ui"
,
tag
);
etag
->
len
=
ngx_strlen
(
etag
->
data
);
r
->
headers_out
.
etag
=
ngx_http_push_stream_add_response_header
(
r
,
&
NGX_HTTP_PUSH_STREAM_HEADER_ETAG
,
etag
);
}
}
}
src/ngx_http_push_stream_rbtree_util.c
View file @
f0f2b472
...
...
@@ -83,6 +83,8 @@ ngx_http_push_stream_initialize_channel(ngx_http_push_stream_channel_t *channel)
ngx_http_push_stream_shm_data_t
*
data
=
(
ngx_http_push_stream_shm_data_t
*
)
ngx_http_push_stream_shm_zone
->
data
;
channel
->
last_message_id
=
0
;
channel
->
last_message_time
=
0
;
channel
->
last_message_tag
=
0
;
channel
->
stored_messages
=
0
;
channel
->
subscribers
=
0
;
channel
->
deleted
=
0
;
...
...
test/base_test_case.rb
View file @
f0f2b472
...
...
@@ -155,6 +155,7 @@ module BaseTestCase
@channel_deleted_message_text
=
nil
@ping_message_text
=
nil
@subscriber_eventsource
=
'off'
@subscriber_mode
=
nil
self
.
send
(
:global_configuration
)
if
self
.
respond_to?
(
:global_configuration
)
end
...
...
@@ -285,7 +286,7 @@ http {
location ~ /sub/(.*)? {
# activate subscriber mode for this location
push_stream_subscriber;
push_stream_subscriber
<%= @subscriber_mode unless @subscriber_mode.nil? || @subscriber_mode == "streaming" %>
;
# activate event source support for this location
<%= "push_stream_subscriber_eventsource #{@subscriber_eventsource};" unless @subscriber_eventsource.nil? %>
...
...
test/test_setup_parameters.rb
View file @
f0f2b472
...
...
@@ -176,4 +176,49 @@ class TestSetuParameters < Test::Unit::TestCase
ensure
self
.
stop_server
end
def
test_invalid_push_mode
expected_error_message
=
"invalid push_stream_subscriber mode value: unknown, accepted values (streaming, polling, long-polling)"
@subscriber_mode
=
"unknown"
self
.
create_config_file
stderr_msg
=
self
.
start_server
assert
(
stderr_msg
.
include?
(
expected_error_message
),
"Message error not founded: '
#{
expected_error_message
}
' recieved '
#{
stderr_msg
}
'"
)
end
def
test_valid_push_mode
expected_error_message
=
"invalid push_stream_subscriber mode value"
@subscriber_mode
=
""
self
.
create_config_file
stderr_msg
=
self
.
start_server
assert
(
!
stderr_msg
.
include?
(
expected_error_message
),
"Message error founded: '
#{
stderr_msg
}
'"
)
self
.
stop_server
@subscriber_mode
=
"streaming"
self
.
create_config_file
stderr_msg
=
self
.
start_server
assert
(
!
stderr_msg
.
include?
(
expected_error_message
),
"Message error founded: '
#{
stderr_msg
}
'"
)
self
.
stop_server
@subscriber_mode
=
"polling"
self
.
create_config_file
stderr_msg
=
self
.
start_server
assert
(
!
stderr_msg
.
include?
(
expected_error_message
),
"Message error founded: '
#{
stderr_msg
}
'"
)
self
.
stop_server
@subscriber_mode
=
"long-polling"
self
.
create_config_file
stderr_msg
=
self
.
start_server
assert
(
!
stderr_msg
.
include?
(
expected_error_message
),
"Message error founded: '
#{
stderr_msg
}
'"
)
self
.
stop_server
end
end
test/test_subscriber_long_polling.rb
0 → 100644
View file @
f0f2b472
require
File
.
expand_path
(
'base_test_case'
,
File
.
dirname
(
__FILE__
))
class
TestSubscriberLongPolling
<
Test
::
Unit
::
TestCase
include
BaseTestCase
def
global_configuration
@ping_message_interval
=
nil
@header_template
=
nil
@footer_template
=
nil
@message_template
=
nil
@subscriber_mode
=
'long-polling'
end
def
test_disconnect_after_receive_a_message_when_longpolling_is_on
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_disconnect_after_receive_a_message_when_longpolling_is_on'
body
=
'body'
response
=
""
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_1
.
callback
{
|
chunk
|
assert_equal
(
"
#{
body
}
\r\n
"
,
response
,
"Wrong message"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_1
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_1
.
response_header
[
'ETAG'
]})
response
=
""
sub_2
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_2
.
callback
{
|
chunk
|
assert_equal
(
"
#{
body
}
1
\r\n
"
,
response
,
"Wrong message"
)
EventMachine
.
stop
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
" 1"
)
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
add_test_timeout
}
end
def
test_disconnect_after_receive_old_messages_by_backtrack_when_longpolling_is_on
channel
=
'ch_test_disconnect_after_receive_old_messages_by_backtrack_when_longpolling_is_on'
response
=
''
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 4'
)
sub
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
+
'.b2'
).
get
sub
.
stream
{
|
chunk
|
response
+=
chunk
}
sub
.
callback
{
|
chunk
|
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
response
,
"The published message was not received correctly"
)
response
=
''
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
{
'If-Modified-Since'
=>
sub
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub
.
response_header
[
'ETAG'
]}
sub_1
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_1
.
callback
{
|
chunk
|
assert_equal
(
"msg 5
\r\n
"
,
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 5'
)
}
add_test_timeout
}
end
def
test_disconnect_after_receive_old_messages_by_last_event_id_when_longpolling_is_on
channel
=
'ch_test_disconnect_after_receive_old_messages_by_last_event_id_when_longpolling_is_on'
response
=
''
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 1'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 2'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'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
{
|
chunk
|
response
+=
chunk
}
sub
.
callback
{
|
chunk
|
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
test_receive_old_messages_from_different_channels
headers
=
{
'accept'
=>
'application/json'
}
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
=
''
EventMachine
.
run
{
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"_1"
)
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"_2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
_2
\r\n
#{
body
}
_1
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
200
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_1
\r\n
"
,
sub_2
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_2
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"1_2"
)
}
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"1_1"
)
}
add_test_timeout
}
end
def
config_test_disconnect_after_receive_a_message_when_has_header_mode_longpolling
@subscriber_mode
=
nil
end
def
test_disconnect_after_receive_a_message_when_has_header_mode_longpolling
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'long-polling'
}
channel
=
'ch_test_disconnect_after_receive_a_message_when_has_header_mode_longpolling'
body
=
'body'
response
=
""
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_1
.
callback
{
|
chunk
|
assert_equal
(
"
#{
body
}
\r\n
"
,
response
,
"Wrong message"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_1
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_1
.
response_header
[
'ETAG'
]})
response
=
""
sub_2
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_2
.
callback
{
|
chunk
|
assert_equal
(
"
#{
body
}
1
\r\n
"
,
response
,
"Wrong message"
)
EventMachine
.
stop
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
" 1"
)
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
add_test_timeout
}
end
def
config_test_disconnect_after_receive_old_messages_by_backtrack_when_has_header_mode_longpolling
@subscriber_mode
=
nil
end
def
test_disconnect_after_receive_old_messages_by_backtrack_when_has_header_mode_longpolling
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'long-polling'
}
channel
=
'ch_test_disconnect_after_receive_old_messages_by_backtrack_when_has_header_mode_longpolling'
response
=
''
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 4'
)
sub
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
+
'.b2'
).
get
:head
=>
headers
sub
.
stream
{
|
chunk
|
response
+=
chunk
}
sub
.
callback
{
|
chunk
|
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
response
,
"The published message was not received correctly"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub
.
response_header
[
'ETAG'
]})
response
=
''
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
sub_1
.
stream
{
|
chunk
|
response
+=
chunk
}
sub_1
.
callback
{
|
chunk
|
assert_equal
(
"msg 5
\r\n
"
,
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 5'
)
}
add_test_timeout
}
end
def
config_test_disconnect_after_receive_old_messages_by_last_event_id_when_has_header_mode_longpolling
@subscriber_mode
=
nil
end
def
test_disconnect_after_receive_old_messages_by_last_event_id_when_has_header_mode_longpolling
channel
=
'ch_test_disconnect_after_receive_old_messages_by_last_event_id_when_has_header_mode_longpolling'
response
=
''
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 1'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 2'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 3'
},
'msg 4'
)
sub
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
{
'Last-Event-Id'
=>
'event 2'
,
'X-Nginx-PushStream-Mode'
=>
'long-polling'
}
sub
.
stream
{
|
chunk
|
response
+=
chunk
}
sub
.
callback
{
|
chunk
|
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
config_test_receive_old_messages_from_different_channels_when_has_header_mode_longpolling
@subscriber_mode
=
nil
end
def
test_receive_old_messages_from_different_channels_when_has_header_mode_longpolling
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'long-polling'
}
channel_1
=
'ch_test_receive_old_messages_from_different_channels_when_has_header_mode_longpolling_1'
channel_2
=
'ch_test_receive_old_messages_from_different_channels_when_has_header_mode_longpolling_2'
body
=
'body'
response
=
''
EventMachine
.
run
{
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"_1"
)
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"_2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
_2
\r\n
#{
body
}
_1
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
200
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_1
\r\n
"
,
sub_2
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_2
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"1_2"
)
}
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"1_1"
)
}
add_test_timeout
}
end
end
test/test_subscriber_polling.rb
0 → 100644
View file @
f0f2b472
require
File
.
expand_path
(
'base_test_case'
,
File
.
dirname
(
__FILE__
))
class
TestSubscriberPolling
<
Test
::
Unit
::
TestCase
include
BaseTestCase
def
global_configuration
@ping_message_interval
=
nil
@header_template
=
nil
@footer_template
=
nil
@message_template
=
nil
@subscriber_mode
=
'polling'
end
def
test_receive_a_304_when_has_no_messages
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_receive_a_304_when_has_no_messages'
body
=
'body'
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
304
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
test_receive_a_304_when_has_no_messages_keeping_headers
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_receive_a_304_when_has_no_messages_keeping_headers'
body
=
'body'
headers
=
headers
.
merge
({
'If-Modified-Since'
=>
Time
.
now
.
utc
.
strftime
(
"%a, %d %b %Y %T %Z"
),
'If-None-Match'
=>
'3'
})
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
304
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
headers
[
'If-Modified-Since'
],
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
headers
[
'If-None-Match'
],
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
test_receive_specific_headers_when_has_messages
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_receive_specific_headers_when_has_messages'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
test_receive_old_messages_by_if_modified_since_header
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_getting_messages_by_if_modified_since_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"1"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
test_receive_old_messages_by_backtrack
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_getting_messages_by_if_modified_since_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"1"
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
+
'.b1'
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"2"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
2
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"3"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
3
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
test_receive_old_messages_by_last_event_id
headers
=
{
'accept'
=>
'application/json'
}
channel
=
'ch_test_receive_old_messages_by_last_event_id'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 1'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 2'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 3'
},
'msg 4'
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
{
'Last-Event-Id'
=>
'event 2'
}
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"3"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"3"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
3
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
test_receive_old_messages_from_different_channels
headers
=
{
'accept'
=>
'application/json'
}
channel_1
=
'ch_test_receive_old_messages_from_different_channels_1'
channel_2
=
'ch_test_receive_old_messages_from_different_channels_2'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"_1"
)
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"_2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
_2
\r\n
#{
body
}
_1
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"1_1"
)
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
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_1
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_3
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_3
.
response_header
[
'ETAG'
]})
sub_4
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_4
.
callback
{
assert_equal
(
304
,
sub_4
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_3
.
response_header
[
'LAST_MODIFIED'
],
sub_4
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_3
.
response_header
[
'ETAG'
],
sub_4
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"1_2"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_4
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_4
.
response_header
[
'ETAG'
]})
sub_5
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_5
.
callback
{
assert_equal
(
200
,
sub_5
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_4
.
response_header
[
'LAST_MODIFIED'
],
sub_5
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_5
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_2
\r\n
"
,
sub_5
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
}
}
add_test_timeout
}
end
def
conf_test_receive_a_304_when_has_no_messages_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_a_304_when_has_no_messages_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_receive_a_304_when_has_no_messages_using_push_mode_header'
body
=
'body'
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
304
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
conf_test_receive_a_304_when_has_no_messages_keeping_headers_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_a_304_when_has_no_messages_keeping_headers_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_receive_a_304_when_has_no_messages_keeping_headers_using_push_mode_header'
body
=
'body'
headers
=
headers
.
merge
({
'If-Modified-Since'
=>
Time
.
now
.
utc
.
strftime
(
"%a, %d %b %Y %T %Z"
),
'If-None-Match'
=>
'3'
})
EventMachine
.
run
{
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
304
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
headers
[
'If-Modified-Since'
],
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
headers
[
'If-None-Match'
],
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
conf_test_receive_specific_headers_when_has_messages_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_specific_headers_when_has_messages_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_receive_specific_headers_when_has_messages_using_push_mode_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
add_test_timeout
}
end
def
conf_test_receive_old_messages_by_if_modified_since_header_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_old_messages_by_if_modified_since_header_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_getting_messages_by_if_modified_since_header_using_push_mode_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"1"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
conf_test_receive_old_messages_by_backtrack_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_old_messages_by_backtrack_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_getting_messages_by_if_modified_since_header_using_push_mode_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"1"
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
+
'.b1'
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"2"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
2
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"3"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
3
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
conf_test_receive_old_messages_by_last_event_id_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_old_messages_by_last_event_id_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel
=
'ch_test_receive_old_messages_by_last_event_id_using_push_mode_header'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 1'
},
'msg 1'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 2'
},
'msg 2'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
'msg 3'
)
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
,
'Event-Id'
=>
'event 3'
},
'msg 4'
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel
.
to_s
).
get
:head
=>
headers
.
merge
({
'Last-Event-Id'
=>
'event 2'
})
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"3"
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"msg 3
\r\n
msg 4
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel
,
{
'accept'
=>
'text/html'
},
body
+
"3"
)
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
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
3
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
add_test_timeout
}
end
def
conf_test_receive_old_messages_from_different_channels_using_push_mode_header
@subscriber_mode
=
nil
end
def
test_receive_old_messages_from_different_channels_using_push_mode_header
headers
=
{
'accept'
=>
'application/json'
,
'X-Nginx-PushStream-Mode'
=>
'polling'
}
channel_1
=
'ch_test_receive_old_messages_from_different_channels_using_push_mode_header_1'
channel_2
=
'ch_test_receive_old_messages_from_different_channels_using_push_mode_header_2'
body
=
'body'
EventMachine
.
run
{
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"_1"
)
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"_2"
)
sub_1
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_1
.
callback
{
assert_equal
(
200
,
sub_1
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_not_equal
(
""
,
sub_1
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
_2
\r\n
#{
body
}
_1
\r\n
"
,
sub_1
.
response
,
"The published message was not received correctly"
)
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
=>
headers
,
:timeout
=>
30
sub_2
.
callback
{
assert_equal
(
304
,
sub_2
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_1
.
response_header
[
'LAST_MODIFIED'
],
sub_2
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_1
.
response_header
[
'ETAG'
],
sub_2
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_1
,
{
'accept'
=>
'text/html'
},
body
+
"1_1"
)
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
=>
headers
,
:timeout
=>
30
sub_3
.
callback
{
assert_equal
(
200
,
sub_3
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_2
.
response_header
[
'LAST_MODIFIED'
],
sub_3
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_3
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_1
\r\n
"
,
sub_3
.
response
,
"The published message was not received correctly"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_3
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_3
.
response_header
[
'ETAG'
]})
sub_4
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_4
.
callback
{
assert_equal
(
304
,
sub_4
.
response_header
.
status
,
"Wrong status"
)
assert_equal
(
sub_3
.
response_header
[
'LAST_MODIFIED'
],
sub_4
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
sub_3
.
response_header
[
'ETAG'
],
sub_4
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
sleep
(
1
)
# to publish the second message in a different second from the first
publish_message_inline
(
channel_2
,
{
'accept'
=>
'text/html'
},
body
+
"1_2"
)
headers
.
merge!
({
'If-Modified-Since'
=>
sub_4
.
response_header
[
'LAST_MODIFIED'
],
'If-None-Match'
=>
sub_4
.
response_header
[
'ETAG'
]})
sub_5
=
EventMachine
::
HttpRequest
.
new
(
nginx_address
+
'/sub/'
+
channel_2
.
to_s
+
'/'
+
channel_1
.
to_s
).
get
:head
=>
headers
,
:timeout
=>
30
sub_5
.
callback
{
assert_equal
(
200
,
sub_5
.
response_header
.
status
,
"Wrong status"
)
assert_not_equal
(
sub_4
.
response_header
[
'LAST_MODIFIED'
],
sub_5
.
response_header
[
'LAST_MODIFIED'
].
to_s
,
"Wrong header"
)
assert_equal
(
"0"
,
sub_5
.
response_header
[
'ETAG'
].
to_s
,
"Wrong header"
)
assert_equal
(
"
#{
body
}
1_2
\r\n
"
,
sub_5
.
response
,
"The published message was not received correctly"
)
EventMachine
.
stop
}
}
}
}
}
add_test_timeout
}
end
end
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