static ngx_int_t ngx_http_vhost_traffic_status_display_handler_control(ngx_http_request_t *r) { ngx_int_t size, rc; ngx_str_t type, alpha, arg_cmd, arg_group, arg_zone; ngx_buf_t *b; ngx_chain_t out; ngx_slab_pool_t *shpool; ngx_http_vhost_traffic_status_control_t *control; ngx_http_vhost_traffic_status_loc_conf_t *vtscf; vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module); /* init control */ control = ngx_pcalloc(r->pool, sizeof(ngx_http_vhost_traffic_status_control_t)); if (control == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->r = r; control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; control->group = -2; control->zone = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (control->zone == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->arg_cmd = &arg_cmd; control->arg_group = &arg_group; control->arg_zone = &arg_zone; control->range = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_RANGE_NONE; control->count = 0; arg_cmd.len = 0; arg_group.len = 0; arg_zone.len = 0; if (r->args.len) { if (ngx_http_arg(r, (u_char *) "cmd", 3, &arg_cmd) == NGX_OK) { if (arg_cmd.len == 6 && ngx_strncmp(arg_cmd.data, "status", 6) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS; } else if (arg_cmd.len == 6 && ngx_strncmp(arg_cmd.data, "delete", 6) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_DELETE; } else if (arg_cmd.len == 5 && ngx_strncmp(arg_cmd.data, "reset", 5) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_RESET; } else { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } if (ngx_http_arg(r, (u_char *) "group", 5, &arg_group) == NGX_OK) { if (arg_group.len == 1 && ngx_strncmp(arg_group.data, "*", 1) == 0) { control->group = -1; } else if (arg_group.len == 6 && ngx_strncasecmp(arg_group.data, (u_char *) "server", 6) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_NO; } else if (arg_group.len == 14 && ngx_strncasecmp(arg_group.data, (u_char *) "upstream@alone", 14) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UA; } else if (arg_group.len == 14 && ngx_strncasecmp(arg_group.data, (u_char *) "upstream@group", 14) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UG; } else if (arg_group.len == 5 && ngx_strncasecmp(arg_group.data, (u_char *) "cache", 5) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_CC; } else if (arg_group.len == 6 && ngx_strncasecmp(arg_group.data, (u_char *) "filter", 6) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_FG; } else { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } if (ngx_http_arg(r, (u_char *) "zone", 4, &arg_zone) != NGX_OK) { if (control->group != -1) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } else { rc = ngx_http_vhost_traffic_status_copy_str(r->pool, control->zone, &arg_zone); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::copy_str() failed"); } (void) ngx_http_vhost_traffic_status_replace_chrc(control->zone, '@', NGX_HTTP_VHOST_TRAFFIC_STATUS_KEY_SEPARATOR); ngx_str_set(&alpha, "[:alpha:]"); rc = ngx_http_vhost_traffic_status_replace_strc(control->zone, &alpha, '@'); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::replace_strc() failed"); } } ngx_http_vhost_traffic_status_node_control_range_set(control); } if (control->command == NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS) { size = ngx_http_vhost_traffic_status_display_get_size(r, NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON); if (size == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::display_get_size() failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { size = sizeof(NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CONTROL) + arg_cmd.len + arg_group.len + arg_zone.len + ngx_pagesize; } ngx_str_set(&type, "application/json"); r->headers_out.content_type_len = type.len; r->headers_out.content_type = type; if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->buf = &b->last; shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); switch (control->command) { case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS: ngx_http_vhost_traffic_status_node_status(control); break; case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_DELETE: ngx_http_vhost_traffic_status_node_delete(control); break; case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_RESET: ngx_http_vhost_traffic_status_node_reset(control); break; default: *control->buf = ngx_sprintf(*control->buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CONTROL, ngx_http_vhost_traffic_status_boolean_to_string(0), control->arg_cmd, control->arg_group, control->arg_zone, control->count); break; } ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "{}"); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = (r == r->main) ? 1 : 0; /* if subrequest 0 else 1 */ b->last_in_chain = 1; out.buf = b; out.next = NULL; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_static_handler(ngx_http_request_t *r) { u_char *last, *location; size_t root, len; ngx_str_t path; ngx_int_t rc; ngx_uint_t level; ngx_log_t *log; ngx_buf_t *b; ngx_chain_t out; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; //ngx_str_t temp = ngx_string("/test1.js"); //r->uri= temp; myChain=&out; r->uri.data=value; r->uri.len=valueLen; /*in=&out; in =in;*/ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) { return NGX_HTTP_NOT_ALLOWED; } if (r->uri.data[r->uri.len - 1] == '/') { return NGX_DECLINED; } log = r->connection->log; /* * ngx_http_map_uri_to_path() allocates memory for terminating '\0' * so we do not need to reserve memory for '/' for possible redirect */ last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } path.len = last - path.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http filename: \"%s\"", path.data); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_memzero(&of, sizeof(ngx_open_file_info_t)); of.read_ahead = clcf->read_ahead; of.directio = clcf->directio; of.valid = clcf->open_file_cache_valid; of.min_uses = clcf->open_file_cache_min_uses; of.errors = clcf->open_file_cache_errors; of.events = clcf->open_file_cache_events; if (ngx_http_set_disable_symlinks(r, clcf, &path, &of) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_open_cached_file(clcf->open_file_cache, &path, &of, r->pool) != NGX_OK) { switch (of.err) { case 0: return NGX_HTTP_INTERNAL_SERVER_ERROR; case NGX_ENOENT: case NGX_ENOTDIR: case NGX_ENAMETOOLONG: level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; break; case NGX_EACCES: #if (NGX_HAVE_OPENAT) case NGX_EMLINK: case NGX_ELOOP: #endif level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; break; default: level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; break; } if (rc != NGX_HTTP_NOT_FOUND || clcf->log_not_found) { ngx_log_error(level, log, of.err, "%s \"%s\" failed", of.failed, path.data); } return rc; } r->root_tested = !r->error_page; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http static fd: %d", of.fd); if (of.is_dir) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0, "http dir"); ngx_http_clear_location(r); r->headers_out.location = ngx_palloc(r->pool, sizeof(ngx_table_elt_t)); if (r->headers_out.location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } len = r->uri.len + 1; if (!clcf->alias && clcf->root_lengths == NULL && r->args.len == 0) { location = path.data + clcf->root.len; *last = '/'; } else { if (r->args.len) { len += r->args.len + 1; } location = ngx_pnalloc(r->pool, len); if (location == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } last = ngx_copy(location, r->uri.data, r->uri.len); *last = '/'; if (r->args.len) { *++last = '?'; ngx_memcpy(++last, r->args.data, r->args.len); } } /* * we do not need to set the r->headers_out.location->hash and * r->headers_out.location->key fields */ r->headers_out.location->value.len = len; r->headers_out.location->value.data = location; return NGX_HTTP_MOVED_PERMANENTLY; } #if !(NGX_WIN32) /* the not regular files are probably Unix specific */ if (!of.is_file) { ngx_log_error(NGX_LOG_CRIT, log, 0, "\"%s\" is not a regular file", path.data); return NGX_HTTP_NOT_FOUND; } #endif if (r->method & NGX_HTTP_POST) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } log->action = "sending response to client"; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = of.size; r->headers_out.last_modified_time = of.mtime; if (ngx_http_set_etag(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (r != r->main && of.size == 0) { return ngx_http_send_header(r); } r->allow_ranges = 1; /* we need to allocate all before the header would be sent */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file = ngx_pcalloc(r->pool, sizeof(ngx_file_t)); if (b->file == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } b->file_pos = 0; b->file_last = of.size; b->in_file = b->file_last ? 1: 0; b->last_buf = (r == r->main) ? 1: 0; b->last_in_chain = 1; b->file->fd = of.fd; b->file->name = path; b->file->log = log; b->file->directio = of.is_directio; out.buf = b; out.next = NULL; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "GZIP HANDLER 1"); return 1; }
static ngx_int_t ngx_http_vhost_traffic_status_display_handler_default(ngx_http_request_t *r) { size_t len; u_char *o, *s; ngx_str_t uri, type; ngx_int_t size, format, rc; ngx_buf_t *b; ngx_chain_t out; ngx_slab_pool_t *shpool; ngx_http_vhost_traffic_status_ctx_t *ctx; ngx_http_vhost_traffic_status_loc_conf_t *vtscf; ctx = ngx_http_get_module_main_conf(r, ngx_http_vhost_traffic_status_module); vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module); if (!ctx->enable) { return NGX_HTTP_NOT_IMPLEMENTED; } if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } uri = r->uri; format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE; if (uri.len == 1) { if (ngx_strncmp(uri.data, "/", 1) == 0) { uri.len = 0; } } o = (u_char *) r->uri.data; s = o; len = r->uri.len; while(sizeof("/format/type") - 1 <= len) { if (ngx_strncasecmp(s, (u_char *) "/format/", sizeof("/format/") - 1) == 0) { uri.data = o; uri.len = (o == s) ? 0 : (size_t) (s - o); s += sizeof("/format/") - 1; if (ngx_strncasecmp(s, (u_char *) "jsonp", sizeof("jsonp") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP; } else if (ngx_strncasecmp(s, (u_char *) "json", sizeof("json") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON; } else if (ngx_strncasecmp(s, (u_char *) "html", sizeof("html") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_HTML; } else if (ngx_strncasecmp(s, (u_char *) "prometheus", sizeof("prometheus") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS; } else { s -= 2; } if (format != NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE) { break; } } if ((s = (u_char *) ngx_strchr(++s, '/')) == NULL) { break; } if (r->uri.len <= (size_t) (s - o)) { break; } len = r->uri.len - (size_t) (s - o); } format = (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE) ? vtscf->format : format; rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON) { ngx_str_set(&type, "application/json"); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP) { ngx_str_set(&type, "application/javascript"); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS) { ngx_str_set(&type, "text/plain"); } else { ngx_str_set(&type, "text/html"); } r->headers_out.content_type_len = type.len; r->headers_out.content_type = type; if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } size = ngx_http_vhost_traffic_status_display_get_size(r, format); if (size == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_default::display_get_size() failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_http_vhost_traffic_status_display_set(r, b->last); ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "{}"); } } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_sprintf(b->last, "%V", &vtscf->jsonp); b->last = ngx_sprintf(b->last, "("); b->last = ngx_http_vhost_traffic_status_display_set(r, b->last); b->last = ngx_sprintf(b->last, ")"); ngx_shmtx_unlock(&shpool->mutex); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_http_vhost_traffic_status_display_prometheus_set(r, b->last); ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "#"); } } else { b->last = ngx_sprintf(b->last, NGX_HTTP_VHOST_TRAFFIC_STATUS_HTML_DATA, &uri, &uri); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = (r == r->main) ? 1 : 0; /* if subrequest 0 else 1 */ b->last_in_chain = 1; out.buf = b; out.next = NULL; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static void websocket_perform_handshake(full_subscriber_t *fsub) { static ngx_str_t magic = ngx_string("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); ngx_str_t ws_accept_key, sha1_str; u_char buf_sha1[21]; u_char buf[255]; ngx_str_t *tmp, *ws_key; ngx_int_t ws_version; ngx_http_request_t *r = fsub->sub.request; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); nchan_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, nchan_module); ngx_sha1_t sha1; ws_accept_key.data = buf; r->headers_out.content_length_n = 0; r->header_only = 1; if((tmp = nchan_get_header_value(r, NCHAN_HEADER_SEC_WEBSOCKET_VERSION)) == NULL) { r->headers_out.status = NGX_HTTP_BAD_REQUEST; fsub->sub.dequeue_after_response=1; } else { ws_version=ngx_atoi(tmp->data, tmp->len); if(ws_version != 13) { r->headers_out.status = NGX_HTTP_BAD_REQUEST; fsub->sub.dequeue_after_response=1; } } if((ws_key = nchan_get_header_value(r, NCHAN_HEADER_SEC_WEBSOCKET_KEY)) == NULL) { r->headers_out.status = NGX_HTTP_BAD_REQUEST; fsub->sub.dequeue_after_response=1; } if(r->headers_out.status != NGX_HTTP_BAD_REQUEST) { //generate accept key ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, ws_key->data, ws_key->len); ngx_sha1_update(&sha1, magic.data, magic.len); ngx_sha1_final(buf_sha1, &sha1); sha1_str.len=20; sha1_str.data=buf_sha1; ws_accept_key.len=ngx_base64_encoded_length(sha1_str.len); assert(ws_accept_key.len < 255); ngx_encode_base64(&ws_accept_key, &sha1_str); nchan_add_response_header(r, &NCHAN_HEADER_SEC_WEBSOCKET_ACCEPT, &ws_accept_key); nchan_add_response_header(r, &NCHAN_HEADER_UPGRADE, &NCHAN_WEBSOCKET); #if nginx_version < 1003013 nchan_add_response_header(r, &NCHAN_HEADER_CONNECTION, &NCHAN_UPGRADE); #endif r->headers_out.status_line = NCHAN_HTTP_STATUS_101; r->headers_out.status = NGX_HTTP_SWITCHING_PROTOCOLS; r->keepalive=0; //apparently, websocket must not use keepalive. } if(ctx->request_origin_header.len > 0) { nchan_add_response_header(r, &NCHAN_HEADER_ALLOW_ORIGIN, &cf->allow_origin); } ngx_http_send_header(r); }
static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { u_char *last, *filename, scale; off_t length; size_t len, char_len, escape_html, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; ngx_int_t rc, size; ngx_str_t path; ngx_dir_t dir; ngx_uint_t i, level, utf8; ngx_pool_t *pool; ngx_time_t *tp; ngx_chain_t out; ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); if (!alcf->enable) { return NGX_DECLINED; } /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */ last = ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_AUTOINDEX_PREALLOCATE); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } allocated = path.len; path.len = last - path.data; if (path.len > 1) { path.len--; } path.data[path.len] = '\0'; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex: \"%s\"", path.data); if (ngx_open_dir(&path, &dir) == NGX_ERROR) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, r->connection->log, err, ngx_open_dir_n " \"%s\" failed", path.data); return rc; } #if (NGX_SUPPRESS_WARN) /* MSVC thinks 'entries' may be used without having been initialized */ ngx_memzero(&entries, sizeof(ngx_array_t)); #endif /* TODO: pool should be temporary pool */ pool = r->pool; if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t)) != NGX_OK) { return ngx_http_autoindex_error(r, &dir, &path); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_type_len = sizeof("text/html") - 1; ngx_str_set(&r->headers_out.content_type, "text/html"); rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%V\" failed", &path); } return rc; } filename = path.data; filename[path.len] = '/'; if (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) == 0) { utf8 = 1; } else { utf8 = 0; } for ( ;; ) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { err = ngx_errno; if (err != NGX_ENOMOREFILES) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_read_dir_n " \"%V\" failed", &path); return ngx_http_autoindex_error(r, &dir, &path); } break; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex file: \"%s\"", ngx_de_name(&dir)); len = ngx_de_namelen(&dir); if (ngx_de_name(&dir)[0] == '.') { continue; } if (!dir.valid_info) { /* 1 byte for '/' and 1 byte for terminating '\0' */ if (path.len + 1 + len + 1 > allocated) { allocated = path.len + 1 + len + 1 + NGX_HTTP_AUTOINDEX_PREALLOCATE; filename = ngx_pnalloc(pool, allocated); if (filename == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } last = ngx_cpystrn(filename, path.data, path.len + 1); *last++ = '/'; } ngx_cpystrn(last, ngx_de_name(&dir), len + 1); if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); if (err == NGX_EACCES) { continue; } return ngx_http_autoindex_error(r, &dir, &path); } if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_de_link_info_n " \"%s\" failed", filename); return ngx_http_autoindex_error(r, &dir, &path); } } } entry = ngx_array_push(&entries); if (entry == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } entry->name.len = len; entry->name.data = ngx_pnalloc(pool, len + 1); if (entry->name.data == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, NGX_ESCAPE_URI_COMPONENT); entry->escape_html = ngx_escape_html(NULL, entry->name.data, entry->name.len); if (utf8) { entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); } else { entry->utf_len = len; } entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); } if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); } escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); len = sizeof(title) - 1 + r->uri.len + escape_html + sizeof(header) - 1 + r->uri.len + escape_html + sizeof("</h1>") - 1 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 + sizeof("</pre><hr>") - 1 + sizeof(tail) - 1; entry = entries.elts; for (i = 0; i < entries.nelts; i++) { len += sizeof("<a href=\"") - 1 + entry[i].name.len + entry[i].escape + 1 /* 1 is for "/" */ + sizeof("\">") - 1 + entry[i].name.len - entry[i].utf_len + entry[i].escape_html + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 + 20 /* the file size */ + 2; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_autoindex_entry_t), ngx_http_autoindex_cmp_entries); } b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); if (escape_html) { b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); } else { b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); } b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); tp = ngx_timeofday(); for (i = 0; i < entries.nelts; i++) { b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_URI_COMPONENT); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem(b->last, entry[i].name.data, entry[i].name.len); } if (entry[i].dir) { *b->last++ = '/'; } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len != len) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; } else { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; } last = b->last; b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, char_len, entry[i].name.len + 1); if (entry[i].escape_html) { b->last = (u_char *) ngx_escape_html(last, entry[i].name.data, b->last - last); } last = b->last; } else { if (entry[i].escape_html) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3; } else { char_len = len; } b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, char_len); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_AUTOINDEX_NAME_LEN + 1); last = b->last - 3; } } if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1); } else { if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1); if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; } } *b->last++ = ' '; ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); if (alcf->exact_size) { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { length = entry[i].size; if (length > 1024 * 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024 * 1024)); if ((length % (1024 * 1024 * 1024)) > (1024 * 1024 * 1024 / 2 - 1)) { size++; } scale = 'G'; } else if (length > 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024)); if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { size++; } scale = 'M'; } else if (length > 9999) { size = (ngx_int_t) (length / 1024); if (length % 1024 > 511) { size++; } scale = 'K'; } else { size = (ngx_int_t) length; scale = '\0'; } if (scale) { b->last = ngx_sprintf(b->last, "%6i%c", size, scale); } else { b->last = ngx_sprintf(b->last, " %6i", size); } } } *b->last++ = CR; *b->last++ = LF; } /* TODO: free temporary pool */ b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); if (r == r->main) { b->last_buf = 1; } b->last_in_chain = 1; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_status_ex_handler(ngx_http_request_t *r) { size_t size, index_size; u_char host[URL_LEN]; ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_atomic_int_t ap, hn, ac, rq, rd, wr;// cc;// rt; cJSON *root,*fmt; char *out_cjson; ngx_url_io_array *url_io_array; ngx_tcp_io ngx_io; ngx_tcp_io **url_io; if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_set(&r->headers_out.content_type, "text/plain"); if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } ap = *ngx_stat_accepted; hn = *ngx_stat_handled; ac = *ngx_stat_active; rq = *ngx_stat_requests; rd = *ngx_stat_reading; wr = *ngx_stat_writing; //cc = *ngx_connection_counter; // rt = *ngx_stat_requesttime; //ngx_tcp_io_get(&tcp_in, &tcp_out); ngx_tcp_io_get_ex(&ngx_io); root=cJSON_CreateObject(); cJSON_AddStringToObject(root, "verison", DRAGON_VER); cJSON_AddNumberToObject(root, "code", 0); cJSON_AddItemToObject(root, "result", fmt=cJSON_CreateObject()); cJSON_AddNumberToObject(fmt,"active_connections", ac); cJSON_AddNumberToObject(fmt,"requests", rq); cJSON_AddNumberToObject(fmt,"accepts", ap); cJSON_AddNumberToObject (fmt,"handled", hn); cJSON_AddNumberToObject(fmt,"reading_request", rd); cJSON_AddNumberToObject(fmt,"writing_request", wr); cJSON_AddNumberToObject(fmt,"waitting_request", ac - (rd + wr)); //cJSON_AddNumberToObject(fmt,"connection_", cc); //cJSON_AddNumberToObject(fmt,"respone_time", rt); cJSON_AddItemToObject(root, "stream", fmt=cJSON_CreateObject()); cJSON_AddNumberToObject (fmt,"in_http_stream", ngx_io.in); cJSON_AddNumberToObject (fmt,"out_http_stream", ngx_io.out); cJSON_AddNumberToObject(fmt,"http_1xx", ngx_io.http_1xx); cJSON_AddNumberToObject(fmt,"http_2xx", ngx_io.http_2xx); cJSON_AddNumberToObject(fmt,"http_3xx", ngx_io.http_3xx); cJSON_AddNumberToObject(fmt,"http_4xx", ngx_io.http_4xx); cJSON_AddNumberToObject(fmt,"http_5xx", ngx_io.http_5xx); cJSON_AddNumberToObject(fmt,"http_400", ngx_io.http_400); cJSON_AddNumberToObject(fmt,"http_401", ngx_io.http_401); cJSON_AddNumberToObject(fmt,"http_403", ngx_io.http_403); cJSON_AddNumberToObject(fmt,"http_404", ngx_io.http_404); cJSON_AddNumberToObject(fmt,"http_408", ngx_io.http_408); cJSON_AddNumberToObject(fmt,"http_500", ngx_io.http_500); cJSON_AddNumberToObject(fmt,"http_502", ngx_io.http_502); cJSON_AddNumberToObject(fmt,"http_503", ngx_io.http_503); cJSON_AddNumberToObject(fmt,"http_504", ngx_io.http_504); cJSON_AddNumberToObject(fmt,"http_505", ngx_io.http_505); if (ngx_status_io_get(&url_io_array) == NGX_OK) { cJSON_AddNumberToObject(root,"number", url_io_array->number); url_io = (ngx_tcp_io**)&url_io_array->ngx_tcp_io; for (index_size= 0; index_size<url_io_array->number; index_size++) { ngx_memzero(host, URL_LEN); ngx_memcpy(host, url_io[index_size]->host, url_io[index_size]->host_len); cJSON_AddItemToObject(root, (const char *)host, fmt=cJSON_CreateObject()); cJSON_AddNumberToObject(fmt, "in", url_io[index_size]->in); cJSON_AddNumberToObject(fmt, "out", url_io[index_size]->out); cJSON_AddNumberToObject(fmt, "requests", url_io[index_size]->requests); cJSON_AddNumberToObject(fmt, "http_1xx", url_io[index_size]->http_1xx); cJSON_AddNumberToObject(fmt, "http_2xx", url_io[index_size]->http_2xx); cJSON_AddNumberToObject(fmt, "http_3xx", url_io[index_size]->http_3xx); cJSON_AddNumberToObject(fmt, "http_4xx", url_io[index_size]->http_4xx); cJSON_AddNumberToObject(fmt, "http_5xx", url_io[index_size]->http_5xx); cJSON_AddNumberToObject(fmt, "http_401", url_io[index_size]->http_401); cJSON_AddNumberToObject(fmt, "http_403", url_io[index_size]->http_403); cJSON_AddNumberToObject(fmt, "http_404", url_io[index_size]->http_404); cJSON_AddNumberToObject(fmt, "http_408", url_io[index_size]->http_408); cJSON_AddNumberToObject(fmt, "http_500", url_io[index_size]->http_500); cJSON_AddNumberToObject(fmt, "http_502", url_io[index_size]->http_502); cJSON_AddNumberToObject(fmt, "http_503", url_io[index_size]->http_503); cJSON_AddNumberToObject(fmt, "http_504", url_io[index_size]->http_504); cJSON_AddNumberToObject(fmt, "http_505", url_io[index_size]->http_505); } } out_cjson=cJSON_Print(root); cJSON_Delete(root); size = ngx_strlen(out_cjson); b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } out.buf = b; out.next = NULL; b->last = ngx_cpymem(b->last, out_cjson, size); if (out_cjson) ngx_free(out_cjson); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_touch_handler(ngx_http_request_t *r) { //main config ngx_http_upstream_main_conf_t * umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); //server config //ngx_http_upstream_srv_conf_t * umsf = r->srv_conf[ngx_http_upstream_module.ctx_index]; //location config //ngx_http_core_loc_conf_t * hclf = (*(r->loc_conf)); ngx_http_upstream_srv_conf_t **uscfp, *uscf; ngx_uint_t i, j, len; u_char *p, *b; ngx_chain_t *cl; ngx_http_upstream_server_t *us; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ngx_http_touch_handler"); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "umcfaddress=%d", umcf); if (umcf == NULL || umcf->upstreams.nelts <= 0) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "NGX_HTTP_NO_CONTENT"); return NGX_HTTP_NO_CONTENT; } //response content buffer length len = 1024 * 16; p = b = ngx_palloc(r->pool, len); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "umcf->upstreams.nelts=%ui\n", umcf->upstreams.nelts); ngx_http_variable_value_t *upstreamname, *servername; ngx_uint_t hash; hash = ngx_hash_key(arg_upstream.data, arg_upstream.len); upstreamname = ngx_http_get_variable(r, &arg_upstream, hash); hash = ngx_hash_key(arg_server.data, arg_server.len); servername = ngx_http_get_variable(r, &arg_server, hash); p = ngx_slprintf(p, b + len, "Worker id: %P\n", ngx_pid); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "i=%d", i); uscf = uscfp[i]; // ngx_slprintf(start, last, fmt, args) p = ngx_slprintf(p, b + len, "upstream name: %V\n", &uscf->host); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "upstream name:%V", &uscf->host); if(uscf->servers != NULL && uscf->servers->nelts > 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uscf->servers->nelts = %ui", uscf->servers->nelts); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "uscf->servers->size = %ui", uscf->servers->size); for (j = 0; j < uscf->servers->nelts; j++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "j=%d", j); //us = (ngx_http_upstream_server_t *)(uscf->servers->elts + j * uscf->servers->size); us = (ngx_http_upstream_server_t *)uscf->servers->elts + j; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "us=%d", us); if (us != NULL) { if (upstreamname && upstreamname->not_found == 0 && servername && servername->not_found == 0 && ngx_strncmp(upstreamname->data, uscf->host.data, upstreamname->len) == 0 && ngx_strncmp(servername->data, us->addrs->name.data, servername->len) == 0) { ngx_http_touch_set_upstream_server(r, us, uscf); } ngx_log_debug6(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "usaddress=%d, weight=%d, max_fails=%d, fail_timeout=%d, down=%d, backup=%d", us, us->weight, us->max_fails, us->fail_timeout, us->down, us->backup); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "server name=%V", &us->addrs->name); if (us->addrs != NULL) { // socket to string // parameters :sockaddr, start, max_length, port print? p += ngx_sock_ntop(us->addrs->sockaddr, p, b - p + len, 1); } p = ngx_slprintf(p, b + len, " weight=%d, max_fails=%d, fail_timeout=%d, down=%d, backup=%d\n", us->weight, us->max_fails, us->fail_timeout, us->down, us->backup); } } } } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_alloc_chain_link"); cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_alloc_chain_link error"); return NGX_ERROR; } cl->next = NULL; cl->buf = ngx_calloc_buf(r->pool); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_calloc_buf"); if (cl->buf == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_calloc_buf error"); return NGX_ERROR; } cl->buf->pos = b; cl->buf->last = p; cl->buf->last_buf = 1;/* this is last , and there will be no more buffers in the request */ cl->buf->memory = 1; /* content is in read-only memory */ /* (i.e., filters should copy it rather than rewrite in place) */ r->headers_out.content_length_n = p - b; r->headers_out.status = NGX_HTTP_OK; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_send_header(r)"); if (ngx_http_send_header(r) != NGX_OK) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_send_header(r) error"); return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 1, "ngx_http_output_filter"); return ngx_http_output_filter(r, cl); }
ngx_int_t ngx_mrb_run(ngx_http_request_t *r, ngx_mrb_state_t *state, ngx_mrb_code_t *code, ngx_flag_t cached, ngx_str_t *result) { int result_len; mrb_value mrb_result; ngx_http_mruby_ctx_t *ctx; ngx_mrb_rputs_chain_list_t *chain; if (state == NGX_CONF_UNSET_PTR || code == NGX_CONF_UNSET_PTR) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); if (ctx == NULL && (ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "failed to allocate memory from r->pool %s:%d" , __FUNCTION__ , __LINE__ ); return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); ngx_mrb_push_request(r); if (!cached) { state->ai = mrb_gc_arena_save(state->mrb); } ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=%d arena_idx=%d" , MODULE_NAME , __func__ , __LINE__ , code->n , state->ai ); mrb_result = mrb_run(state->mrb, mrb_proc_new(state->mrb, state->mrb->irep[code->n]), mrb_top_self(state->mrb)); if (state->mrb->exc) { if (code->code_type == NGX_MRB_CODE_TYPE_FILE) { ngx_mrb_raise_file_error(state->mrb, mrb_obj_value(state->mrb->exc), r, code->code.file); } else { ngx_mrb_raise_error(state->mrb, mrb_obj_value(state->mrb->exc), r); } } if (result != NULL) { if (mrb_nil_p(mrb_result)) { result->data = NULL; result->len = 0; } else { if (mrb_type(mrb_result) != MRB_TT_STRING) { mrb_result = mrb_funcall(state->mrb, mrb_result, "to_s", 0, NULL); } result_len = ngx_strlen((u_char *)RSTRING_PTR(mrb_result)); result->data = ngx_palloc(r->pool, result_len); if (result->data == NULL) { return NGX_ERROR; } ngx_memcpy(result->data, (u_char *)RSTRING_PTR(mrb_result), result_len); result->len = result_len; ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=(%d) return value=(%s)" , MODULE_NAME , __func__ , __LINE__ , code->n , RSTRING_PTR(mrb_result) ); } } mrb_gc_arena_restore(state->mrb, state->ai); if (!cached) { ngx_mrb_irep_clean(r, state, code); ngx_mrb_state_clean(r, state); } // TODO: Support rputs by multi directive if (ngx_http_get_module_ctx(r, ngx_http_mruby_module) != NULL) { chain = ctx->rputs_chain; if (chain == NULL) { ngx_log_error(NGX_LOG_INFO , r->connection->log , 0 , "%s INFO %s:%d: mrb_run info: irep_n=(%d) rputs_chain is null and return NGX_OK" , MODULE_NAME , __func__ , __LINE__ , code->n ); return NGX_OK; } if (r->headers_out.status == NGX_HTTP_OK || !(*chain->last)->buf->last_buf) { r->headers_out.status = NGX_HTTP_OK; (*chain->last)->buf->last_buf = 1; ngx_http_send_header(r); ngx_http_output_filter(r, chain->out); ngx_http_set_ctx(r, NULL, ngx_http_mruby_module); return NGX_OK; } else { return r->headers_out.status; } } return NGX_OK; }
// like Nginx rewrite keywords // used like this: // => http code 3xx location in browser // => internal redirection in nginx static mrb_value ngx_mrb_redirect(mrb_state *mrb, mrb_value self) { int argc; u_char *str; ngx_buf_t *b; ngx_int_t rc; mrb_value uri, code; ngx_str_t ns; ngx_http_mruby_ctx_t *ctx; ngx_table_elt_t *location; ngx_mrb_rputs_chain_list_t *chain; ngx_http_request_t *r = ngx_mrb_get_request(); argc = mrb_get_args(mrb, "o|oo", &uri, &code); // get status code from args if (argc == 2) { rc = mrb_fixnum(code); } else { rc = NGX_HTTP_MOVED_TEMPORARILY; } // get redirect uri from args if (mrb_type(uri) != MRB_TT_STRING) { uri = mrb_funcall(mrb, uri, "to_s", 0, NULL); } // save location uri to ns ns.data = (u_char *)RSTRING_PTR(uri); ns.len = ngx_strlen(ns.data); if (ns.len == 0) { return mrb_nil_value(); } // if uri start with scheme prefix // return 3xx for redirect // else generate a internal redirection and response to raw request // request.path is not changed if (ngx_strncmp(ns.data, "http://", sizeof("http://") - 1) == 0 || ngx_strncmp(ns.data, "https://", sizeof("https://") - 1) == 0 || ngx_strncmp(ns.data, "$scheme", sizeof("$scheme") - 1) == 0) { ctx = ngx_http_get_module_ctx(r, ngx_http_mruby_module); if (ctx == NULL) { ngx_log_error(NGX_LOG_ERR , r->connection->log , 0 , "get mruby context failed." ); } if (ctx->rputs_chain == NULL) { chain = ngx_pcalloc(r->pool, sizeof(ngx_mrb_rputs_chain_list_t)); chain->out = ngx_alloc_chain_link(r->pool); chain->last = &chain->out; } else { chain = ctx->rputs_chain; (*chain->last)->next = ngx_alloc_chain_link(r->pool); chain->last = &(*chain->last)->next; } // allocate space for body b = ngx_calloc_buf(r->pool); (*chain->last)->buf = b; (*chain->last)->next = NULL; str = ngx_pstrdup(r->pool, &ns); str[ns.len] = '\0'; (*chain->last)->buf->pos = str; (*chain->last)->buf->last = str+ns.len; (*chain->last)->buf->memory = 1; ctx->rputs_chain = chain; ngx_http_set_ctx(r, ctx, ngx_http_mruby_module); if (r->headers_out.content_length_n == -1) { r->headers_out.content_length_n += ns.len + 1; } else { r->headers_out.content_length_n += ns.len; } // build redirect location location = ngx_list_push(&r->headers_out.headers); location->hash = 1; ngx_str_set(&location->key, "Location"); location->value = ns; location->lowcase_key = ngx_pnalloc(r->pool, location->value.len); ngx_strlow(location->lowcase_key, location->value.data, location->value.len); // set location and response code for hreaders r->headers_out.location = location; r->headers_out.status = rc; ngx_http_send_header(r); ngx_http_output_filter(r, chain->out); } else { ngx_http_internal_redirect(r, &ns, &r->args); } return self; }
static ngx_int_t ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) { ngx_slab_pool_t *shpool = (ngx_slab_pool_t *)ngx_http_push_stream_shm_zone->shm.addr; ngx_http_push_stream_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module); 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; time_t if_modified_since; ngx_str_t *last_event_id, vv_time = ngx_null_string; ngx_str_t *push_mode; ngx_flag_t polling, longpolling; ngx_int_t rc; ngx_int_t status_code; ngx_str_t *explain_error_message; // add headers to support cross domain requests if (cf->allowed_origins.len > 0) { ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, &cf->allowed_origins); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_METHODS, &NGX_HTTP_PUSH_STREAM_ALLOW_GET); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, &NGX_HTTP_PUSH_STREAM_ALLOWED_HEADERS); } if (r->method & NGX_HTTP_OPTIONS) { return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_OK, NULL); } ngx_http_push_stream_set_expires(r, NGX_HTTP_PUSH_STREAM_EXPIRES_MAX, 0); // only accept GET method if (!(r->method & NGX_HTTP_GET)) { ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ALLOW, &NGX_HTTP_PUSH_STREAM_ALLOW_GET); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_NOT_ALLOWED, NULL); } if ((ctx = ngx_http_push_stream_add_request_context(r)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to create request context"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } //get channels ids and backtracks from path channels_ids = ngx_http_push_stream_parse_channels_ids_from_path(r, ctx->temp_pool); if ((channels_ids == NULL) || ngx_queue_empty(&channels_ids->queue)) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: the $push_stream_channels_path variable is required but is not set"); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_CHANNEL_ID_MESSAGE); } //validate channels: name, length and quantity. check if channel exists when authorized_channels_only is on. check if channel is full of subscribers if (ngx_http_push_stream_validate_channels(r, channels_ids, &status_code, &explain_error_message) == NGX_ERROR) { return ngx_http_push_stream_send_only_header_response(r, status_code, explain_error_message); } 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; } // get control headers if_modified_since = vv_time.len ? ngx_http_parse_time(vv_time.data, vv_time.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->location_type == 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->location_type == 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, ctx->temp_pool); if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } return result; } ctx->padding = ngx_http_push_stream_get_padding_by_user_agent(r); // stream access if ((worker_subscriber = ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(r)) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } 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; } ngx_shmtx_lock(&shpool->mutex); rc = ngx_http_push_stream_registry_subscriber_locked(r, worker_subscriber); ngx_shmtx_unlock(&shpool->mutex); if (rc == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } // 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, if_modified_since, last_event_id, worker_subscriber, ctx->temp_pool) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } return NGX_DONE; }
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) { 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_subscriber_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_http_push_stream_module); ngx_http_push_stream_requested_channel_t *cur; ngx_http_push_stream_subscriber_t *worker_subscriber; ngx_http_push_stream_channel_t *channel; ngx_http_push_stream_subscription_t *subscription; ngx_str_t *etag = NULL, vv_etag = ngx_null_string; ngx_int_t tag; time_t greater_message_time; ngx_int_t greater_message_tag; ngx_flag_t has_message_to_send = 0; ngx_str_t callback_function_name; ngx_flag_t hit_old_message = 0; ngx_int_t count_of_old_message = 0; 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 (ngx_http_arg(r, NGX_HTTP_PUSH_STREAM_CALLBACK.data, NGX_HTTP_PUSH_STREAM_CALLBACK.len, &callback_function_name) == NGX_OK) { ngx_http_push_stream_unescape_uri(&callback_function_name); if ((ctx->callback = ngx_http_push_stream_get_formatted_chunk(callback_function_name.data, callback_function_name.len, r->pool)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to allocate memory for callback function name"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } tag = ((etag != NULL) && ((tag = ngx_atoi(etag->data, etag->len)) != NGX_ERROR)) ? ngx_abs(tag) : -1; greater_message_tag = tag; 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) { time_t next_greater_message_time = greater_message_time;//add by xinlu ngx_int_t next_greater_message_tag = greater_message_tag;//add by xinlu ngx_flag_t hitres = 0; channel = ngx_http_push_stream_find_channel(cur->id, r->connection->log); if (channel == 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_HTTP_INTERNAL_SERVER_ERROR; } count_of_old_message += channel->stored_messages; hitres = 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, &next_greater_message_time, &next_greater_message_tag); if(hitres == 1) { hit_old_message = 1; } if (hitres >= 2) { /* 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; } } */ if(!has_message_to_send) { greater_message_tag = next_greater_message_tag; greater_message_time = next_greater_message_time; } else { if(greater_message_time > next_greater_message_time) { greater_message_time = next_greater_message_time; greater_message_tag = next_greater_message_tag; } else if(greater_message_time == next_greater_message_time && greater_message_tag > next_greater_message_tag) { greater_message_tag = next_greater_message_tag; } } has_message_to_send++; } } 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; } worker_subscriber->longpolling = 1; if (ngx_http_push_stream_registry_subscriber_locked(r, worker_subscriber) == NGX_ERROR) { ngx_shmtx_unlock(&shpool->mutex); return NGX_HTTP_INTERNAL_SERVER_ERROR; } // 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(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_HTTP_INTERNAL_SERVER_ERROR; } if ((subscription = ngx_http_push_stream_create_channel_subscription(r, channel, worker_subscriber)) == NULL) { ngx_shmtx_unlock(&shpool->mutex); return NGX_HTTP_INTERNAL_SERVER_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.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; } if (ctx->callback != NULL) { ngx_http_push_stream_send_response_text(r, ctx->callback->data, ctx->callback->len, 0); ngx_http_push_stream_send_response_text(r, NGX_HTTP_PUSH_STREAM_CALLBACK_INIT_CHUNK.data, NGX_HTTP_PUSH_STREAM_CALLBACK_INIT_CHUNK.len, 0); } cur = channels_ids; while ((cur = (ngx_http_push_stream_requested_channel_t *) ngx_queue_next(&cur->queue)) != channels_ids) { ngx_int_t message_count_had_send = 0; channel = ngx_http_push_stream_find_channel(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, &message_count_had_send); if(message_count_had_send > 0) { break; } } if (ctx->callback != NULL) { ngx_http_push_stream_send_response_text(r, NGX_HTTP_PUSH_STREAM_CALLBACK_END_CHUNK.data, NGX_HTTP_PUSH_STREAM_CALLBACK_END_CHUNK.len, 0); } 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; }
ngx_int_t ngx_http_rds_csv_process_header(ngx_http_request_t *r, ngx_chain_t *in, ngx_http_rds_csv_ctx_t *ctx) { ngx_buf_t *b; ngx_http_rds_header_t header; ngx_int_t rc; if (in == NULL) { return NGX_OK; } b = in->buf; if (!ngx_buf_in_memory(b)) { if (!ngx_buf_special(b)) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rds_csv: process header: buf from " "upstream not in memory"); goto invalid; } in = in->next; if (in == NULL) { return NGX_OK; } b = in->buf; } rc = ngx_http_rds_parse_header(r, b, &header); if (rc != NGX_OK) { goto invalid; } dd("col count: %d", (int) header.col_count); if (header.col_count == 0) { /* for empty result set, just return the JSON * representation of the RDS header */ dd("col count == 0"); if (b->pos != b->last) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rds_csv: header: there's unexpected remaining data " "in the buf"); goto invalid; } ctx->state = state_done; /* now we send the postponed response header */ if (!ctx->header_sent) { ctx->header_sent = 1; rc = ngx_http_rds_csv_next_header_filter(r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } } rc = ngx_http_rds_csv_output_header(r, ctx, &header); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } ngx_http_rds_csv_discard_bufs(r->pool, in); return rc; } ctx->cols = ngx_palloc(r->pool, header.col_count * sizeof(ngx_http_rds_column_t)); if (ctx->cols == NULL) { goto invalid; } ctx->state = state_expect_col; ctx->cur_col = 0; ctx->col_count = header.col_count; /* now we send the postponed response header */ if (!ctx->header_sent) { ctx->header_sent = 1; rc = ngx_http_rds_csv_next_header_filter(r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } } return ngx_http_rds_csv_process_col(r, b->pos == b->last ? in->next : in, ctx); invalid: dd("return 500"); if (!ctx->header_sent) { ctx->header_sent = 1; r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR; ngx_http_send_header(r); ngx_http_send_special(r, NGX_HTTP_LAST); return NGX_ERROR; } return NGX_ERROR; }