static char *nchan_publisher_directive_parse(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_int_t fail) { nchan_loc_conf_t *lcf = conf; ngx_str_t *val; ngx_int_t i; nchan_conf_publisher_types_t *pubt = &lcf->pub; if(cf->args->nelts == 1){ //no arguments pubt->http=1; pubt->websocket=1; } else { for(i=1; i < cf->args->nelts; i++) { val = &((ngx_str_t *) cf->args->elts)[i]; if(nchan_strmatch(val, 1, "http")) { pubt->http=1; } else if(nchan_strmatch(val, WEBSOCKET_STRINGS_N, WEBSOCKET_STRINGS)) { pubt->websocket=1; } else{ if(fail) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "invalid %V value: %V", &cmd->name, val); } return NGX_CONF_ERROR; } } } return nchan_setup_handler(cf, conf, &nchan_pubsub_handler); }
static char *nchan_subscriber_directive_parse(ngx_conf_t *cf, ngx_command_t *cmd, void *conf, ngx_int_t fail) { nchan_loc_conf_t *lcf = conf; ngx_str_t *val; ngx_int_t i; nchan_conf_subscriber_types_t *subt = &lcf->sub; if(cf->args->nelts == 1){ //no arguments subt->poll=0; subt->longpoll=1; subt->websocket=1; subt->eventsource=1; } else { for(i=1; i < cf->args->nelts; i++) { val = &((ngx_str_t *) cf->args->elts)[i]; if(nchan_strmatch(val, LONGPOLL_STRINGS_N, LONGPOLL_STRINGS)) { subt->longpoll=1; } else if(nchan_strmatch(val, INTERVALPOLL_STRINGS_N, INTERVALPOLL_STRINGS)) { subt->poll=1; } else if(nchan_strmatch(val, WEBSOCKET_STRINGS_N, WEBSOCKET_STRINGS)) { subt->websocket=1; } else if(nchan_strmatch(val, EVENTSOURCE_STRINGS_N, EVENTSOURCE_STRINGS)) { subt->eventsource=1; } else if(nchan_strmatch(val, DISABLED_STRINGS_N, DISABLED_STRINGS)) { subt->poll=0; subt->longpoll=0; subt->websocket=0; subt->eventsource=0; } else { if(fail) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "invalid %V value: %V", &cmd->name, val); } return NGX_CONF_ERROR; } } } return nchan_setup_handler(cf, conf, &nchan_pubsub_handler); }
static char *nchan_pubsub_directive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *val; ngx_int_t i; nchan_publisher_directive_parse(cf, cmd, conf, 0); nchan_subscriber_directive_parse(cf, cmd, conf, 0); for(i=1; i < cf->args->nelts; i++) { val = &((ngx_str_t *) cf->args->elts)[i]; if(! nchan_strmatch(val, WEBSOCKET_STRINGS_N + EVENTSOURCE_STRINGS_N + LONGPOLL_STRINGS_N + INTERVALPOLL_STRINGS_N + DISABLED_STRINGS_N, WEBSOCKET_STRINGS, EVENTSOURCE_STRINGS, LONGPOLL_STRINGS, INTERVALPOLL_STRINGS, DISABLED_STRINGS)) { ngx_conf_log_error(NGX_LOG_ERR, cf, 0, "invalid %V value: %V", &cmd->name, val); return NGX_CONF_ERROR; } } return nchan_setup_handler(cf, conf, &nchan_pubsub_handler); }
static ngx_int_t subscriber_authorize_callback(ngx_int_t rc, ngx_http_request_t *sr, void *data) { nchan_subscribe_auth_request_data_t *d = data; subscriber_t *sub = d->sub; if(sub->status == DEAD) { nchan_requestmachine_request_cleanup_manual(d->subrequest); sub->fn->release(d->sub, 0); } else if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) { //this shouldn't happen, but if it does, no big deal nchan_requestmachine_request_cleanup_manual(d->subrequest); sub->fn->release(d->sub, 1); sub->fn->respond_status(sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL, NULL); //couldn't reach upstream } else if(rc == NGX_OK) { ngx_int_t code = sr->headers_out.status; sub->fn->release(sub, 1); if(code >= 200 && code <299) { nchan_requestmachine_request_cleanup_manual(d->subrequest); nchan_subscriber_subscribe(sub, d->ch_id); } else { //forbidden, but with some data to forward to the subscriber ngx_http_request_t *r = d->sub->request; ngx_str_t *content_type; ngx_int_t content_length; ngx_chain_t *request_chain = NULL; content_type = (sr->upstream->headers_in.content_type ? &sr->upstream->headers_in.content_type->value : NULL); content_length = nchan_subrequest_content_length(sr); if(content_length > 0) { #if nginx_version >= 1013010 request_chain = sr->out; #else request_chain = sr->upstream->out_bufs; #endif } //copy headers ngx_uint_t i; ngx_list_part_t *part = &sr->headers_out.headers.part; ngx_table_elt_t *header= part->elts; for (i = 0; /* void */ ; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (!nchan_strmatch(&header[i].key, 4, "Content-Type", "Server", "Content-Length", "Connection")) { //copy header to main request's response nchan_add_response_header(r, &header[i].key, &header[i].value); } } if(content_type) { r->headers_out.content_type = *content_type; } r->headers_out.content_length_n = content_length; nchan_requestmachine_request_cleanup_on_request_finalize(d->subrequest, r); sub->fn->respond_status(sub, code, NULL, request_chain); //auto-closes subscriber } } else if(rc >= 500 && rc < 600) { nchan_requestmachine_request_cleanup_manual(d->subrequest); sub->fn->release(d->sub, 1); sub->fn->respond_status(sub, rc, NULL, NULL); //auto-closes subscriber } else { nchan_requestmachine_request_cleanup_manual(d->subrequest); sub->fn->release(d->sub, 1); d->sub->fn->respond_status(d->sub, NGX_HTTP_INTERNAL_SERVER_ERROR, NULL, NULL); //auto-closes subscriber } return NGX_OK; }