static ngx_int_t ngx_http_shmtest_counter_inc_int(ngx_http_request_t *r) { ngx_int_t rc = NGX_HTTP_OK; ngx_str_t key = ngx_null_string; ngx_str_t szn = ngx_null_string; ngx_int_t n = 1; int64_t cur = 0; if(ngx_http_arg(r, (u_char*)"key", 3, &key)!=NGX_OK){ NLOG_ERROR("get arg 'key' failed!"); return NGX_HTTP_BAD_REQUEST; } if(ngx_http_arg(r, (u_char*)"n", 1, &szn)==NGX_OK){ n = ngx_atoi(szn.data, szn.len); } shmtest_main_conf_t* smcf; smcf = ngx_http_get_module_main_conf(r, ngx_http_shmtest_module); if(smcf == NULL){ NLOG_ERROR("get module ngx_http_shmtest_module's main conf failed!"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_shm_zone_t* zone = smcf->shmap; u_char* rsp = ngx_pcalloc(r->connection->pool, 256); int rsp_len = 0; rc = ngx_shmap_inc_int(zone, &key, n,0, &cur); if(rc == 0){ rsp_len = ngx_sprintf(rsp, "inc_int(key=%V,n=%l)=%l\n", &key,n, cur)-rsp; }else{ rsp_len = ngx_sprintf(rsp, "inc_int(key=%V,n=%l) failed!\n", &key,n)-rsp; } ngx_chain_t* chain = ngx_http_shmtest_resp(r, (char*)rsp, rsp_len); if(chain != NULL){ r->headers_out.content_length_n = rsp_len; }else{ r->headers_out.content_length_n = 0; } rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { }else{ rc = ngx_http_output_filter(r, chain); } return rc; }
static ngx_int_t ngx_http_calc_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; u_char ngx_string[1024]={0}; ngx_uint_t content_length = 0; ngx_str_t arg1; ngx_str_t arg2; ngx_int_t ans; ngx_http_arg(r,(u_char *)"arg1",4,&arg1); ngx_http_arg(r,(u_char *)"arg2",4,&arg2); ans = ngx_atoi(arg1.data,arg1.len)+ngx_atoi(arg2.data,arg2.len); ngx_sprintf(ngx_string,"%V + %V = %d",&arg1,&arg2,ans); content_length = ngx_strlen(ngx_string); if (!(r->method & (NGX_HTTP_GET | NGX_HTTP_HEAD))){ return NGX_HTTP_NOT_ALLOWED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } ngx_str_t type = ngx_string("text/html"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = content_length; r->headers_out.content_type = type; /* HTTP框架提供的发送HTTP头部的方法 */ /* 返回NGX_ERROR或返回值大于0就表示不正常 */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only){ return rc; } b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b==NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->pos = ngx_string; b->last = ngx_string+content_length; b->memory = 1; b->last_buf = 1; out.buf = b; out.next = NULL; return ngx_http_output_filter(r,&out); }
static ngx_int_t ngx_http_conhash_test_del(ngx_http_request_t *r, ngx_conhash_t *conhash, ngx_chain_t *out) { ngx_str_t value; ngx_int_t rc; ngx_buf_t *b; rc = ngx_http_arg(r, (u_char *) VALUE_STR, sizeof(VALUE_STR) - 1, &value); if (rc != NGX_OK) { return rc; } b = ngx_create_temp_buf(r->pool, 1024); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } rc = ngx_conhash_del_node(conhash, value.data, value.len); if (rc == NGX_OK) { b->last = ngx_sprintf(b->last, "Delete node successfully!" CRLF); } if (rc == NGX_DECLINED) { b->last = ngx_sprintf(b->last, "The node does not exists!" CRLF); rc = NGX_OK; } b->last_buf = 1; out->buf = b; return rc; }
static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t *name = (ngx_str_t *) data; u_char *arg; size_t len; ngx_str_t value; len = name->len - (sizeof("arg_") - 1); arg = name->data + sizeof("arg_") - 1; if (ngx_http_arg(r, arg, len, &value) != NGX_OK) { v->not_found = 1; return NGX_OK; } v->data = value.data; v->len = value.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; }
static const char * ngx_rtmp_control_walk_server(ngx_http_request_t *r, ngx_rtmp_core_srv_conf_t *cscf, ngx_rtmp_core_app_conf_t ***pcacf_rtrn) { ngx_str_t app; ngx_uint_t n; const char *s; ngx_rtmp_core_app_conf_t **pcacf; if (ngx_http_arg(r, (u_char *) "app", sizeof("app") - 1, &app) != NGX_OK) { app.len = 0; } pcacf = cscf->applications.elts; for (n = 0; n < cscf->applications.nelts; ++n, ++pcacf) { if (app.len && ((*pcacf)->name.len != app.len || ngx_strncmp((*pcacf)->name.data, app.data, app.len))) { continue; } *pcacf_rtrn = (ngx_rtmp_core_app_conf_t **)(*pcacf)->app_conf; s = ngx_rtmp_control_walk_app(r, *pcacf); if (s != NGX_CONF_OK) { return s; } } return NGX_CONF_OK; }
static ngx_int_t ngx_http_conhash_test_search(ngx_http_request_t *r, ngx_conhash_t *conhash, ngx_chain_t *out) { ngx_str_t value; ngx_int_t rc; size_t len; ngx_buf_t *b; ngx_rbtree_key_t key; ngx_http_conhash_test_node_name_t node; rc = ngx_http_arg(r, (u_char *) VALUE_STR, sizeof(VALUE_STR) - 1, &value); if (rc != NGX_OK) { return rc; } ngx_memzero(&node, sizeof(ngx_http_conhash_test_node_name_t)); node.pool = r->pool; rc = ngx_conhash_lookup_node(conhash, value.data, value.len, ngx_http_conhash_test_get_data, &node); if (rc != NGX_OK) { b = ngx_create_temp_buf(r->pool, 1024); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->last = ngx_sprintf(b->last, "The node tree is empty!" CRLF); goto done; } if (node.vname.data == NULL || node.name.data == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } len = value.len + sizeof(BRACKET_L) - 1 + NGX_OFF_T_LEN + sizeof(PROMPT_STR) - 1 + node.name.len + sizeof(BRACKET_L) - 1 + node.vname.len + sizeof(COMMA_STR) - 1 + NGX_OFF_T_LEN + sizeof(BRACKET_R) - 1 + sizeof(CRLF) - 1; b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } key = conhash->hash_func(value.data, value.len); b->last = ngx_sprintf(b->last, "%V" BRACKET_L "%ui" PROMPT_STR "%V" BRACKET_L "%V" COMMA_STR "%ui"\ BRACKET_R CRLF, &value, key, &node.name, &node.vname, node.key); done: b->last_buf = 1; out->buf = b; return NGX_OK; }
static ngx_int_t ngx_http_weixin_auth_handler(ngx_http_request_t *r) { ngx_buf_t *b; ngx_chain_t out; ngx_int_t rc; ngx_str_t echostr; if (!(r->method & NGX_HTTP_GET)) { return NGX_DECLINED; } if (!r->args.len) { return NGX_DECLINED; } if (ngx_http_arg(r, (u_char *) "echostr", 7, &echostr) != NGX_OK) { return NGX_DECLINED; } rc = ngx_http_weixin_auth(r); if (rc != NGX_OK && rc != NGX_DECLINED) { return rc; } if (rc == NGX_DECLINED) { return NGX_HTTP_FORBIDDEN; } b = ngx_create_temp_buf(r->pool, echostr.len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->last = ngx_cpymem(b->last, echostr.data, echostr.len); b->last_buf = 1; out.buf = b; out.next = NULL; r->headers_out.status = NGX_HTTP_OK; ngx_str_set(&r->headers_out.content_type, "text/plain"); r->headers_out.content_length_n = echostr.len; 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_trim_header_filter(ngx_http_request_t *r) { ngx_int_t rc; ngx_str_t flag; ngx_http_trim_ctx_t *ctx; ngx_http_trim_loc_conf_t *conf; conf = ngx_http_get_module_loc_conf(r, ngx_http_trim_filter_module); if (!conf->trim_enable || r->headers_out.status != NGX_HTTP_OK || (r->method & NGX_HTTP_HEAD) || r->headers_out.content_length_n == 0 || (r->headers_out.content_encoding && r->headers_out.content_encoding->value.len) || ngx_http_test_content_type(r, &conf->types) == NULL) { return ngx_http_next_header_filter(r); } rc = ngx_http_arg(r, (u_char *) NGX_HTTP_TRIM_FLAG, sizeof(NGX_HTTP_TRIM_FLAG) - 1, &flag); if(rc == NGX_OK && flag.len == sizeof("off") - 1 && ngx_strncmp(flag.data, "off", sizeof("off") - 1) == 0) { return ngx_http_next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_trim_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->prev = ' '; ctx->first_line = 1; ngx_http_set_ctx(r, ctx, ngx_http_trim_filter_module); r->main_filter_need_in_memory = 1; ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_next_header_filter(r); }
static const char * ngx_rtmp_control_walk(ngx_http_request_t *r, ngx_rtmp_control_handler_t h, ngx_flag_t per_session) { ngx_rtmp_core_main_conf_t *cmcf = ngx_rtmp_core_main_conf; ngx_str_t srv; ngx_uint_t sn, n; const char *msg; ngx_rtmp_session_t **s; ngx_rtmp_control_ctx_t *ctx; ngx_rtmp_core_srv_conf_t **pcscf; ngx_rtmp_core_app_conf_t **pcacf = NULL; sn = 0; if (ngx_http_arg(r, (u_char *) "srv", sizeof("srv") - 1, &srv) == NGX_OK) { sn = ngx_atoi(srv.data, srv.len); } if (sn >= cmcf->servers.nelts) { return "Server index out of range"; } pcscf = cmcf->servers.elts; pcscf += sn; msg = ngx_rtmp_control_walk_server(r, *pcscf, &pcacf); if (msg != NGX_CONF_OK) { return msg; } ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); if (!per_session) { return h(r, NULL, *pcscf, pcacf); } s = ctx->sessions.elts; for (n = 0; n < ctx->sessions.nelts; n++) { msg = h(r, s[n], *pcscf, pcacf); if (msg != NGX_CONF_OK) { return msg; } } return NGX_CONF_OK; }
static njs_ret_t ngx_http_js_ext_get_arg(njs_vm_t *vm, njs_value_t *value, void *obj, uintptr_t data) { nxt_str_t *v; ngx_str_t arg; ngx_http_request_t *r; r = (ngx_http_request_t *) obj; v = (nxt_str_t *) data; if (ngx_http_arg(r, v->start, v->length, &arg) == NGX_OK) { return njs_string_create(vm, value, arg.data, arg.len, 0); } return njs_string_create(vm, value, NULL, 0, 0); }
static const char * ngx_rtmp_control_record_handler(ngx_http_request_t *r, ngx_rtmp_session_t *s, ngx_rtmp_core_srv_conf_t *cscf, ngx_rtmp_core_app_conf_t **cacf) { ngx_int_t rc; ngx_str_t rec; ngx_uint_t rn; ngx_rtmp_control_ctx_t *ctx; ngx_rtmp_record_app_conf_t *racf; *cacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_core_module); racf = (*cacf)->app_conf[ngx_rtmp_record_module.ctx_index]; if (ngx_http_arg(r, (u_char *) "rec", sizeof("rec") - 1, &rec) != NGX_OK) { rec.len = 0; } rn = ngx_rtmp_record_find(racf, &rec); if (rn == NGX_CONF_UNSET_UINT) { return "Recorder not found"; } ctx = ngx_http_get_module_ctx(r, ngx_rtmp_control_module); if (ctx->method.len == sizeof("start") - 1 && ngx_strncmp(ctx->method.data, "start", ctx->method.len) == 0) { rc = ngx_rtmp_record_open(s, rn, &ctx->path); } else if (ctx->method.len == sizeof("stop") - 1 && ngx_strncmp(ctx->method.data, "stop", ctx->method.len) == 0) { rc = ngx_rtmp_record_close(s, rn, &ctx->path); } else { return "Undefined method"; } if (rc == NGX_ERROR) { return "Recorder error"; } return NGX_CONF_OK; }
static const char * ngx_rtmp_control_walk_app(ngx_http_request_t *r, ngx_rtmp_core_app_conf_t *cacf) { size_t len; ngx_str_t name; const char *s; ngx_uint_t n; ngx_rtmp_live_stream_t *ls; ngx_rtmp_live_app_conf_t *lacf; lacf = cacf->app_conf[ngx_rtmp_live_module.ctx_index]; if (ngx_http_arg(r, (u_char *) "name", sizeof("name") - 1, &name) != NGX_OK) { for (n = 0; n < (ngx_uint_t) lacf->nbuckets; ++n) { for (ls = lacf->streams[n]; ls; ls = ls->next) { s = ngx_rtmp_control_walk_stream(r, ls); if (s != NGX_CONF_OK) { return s; } } } return NGX_CONF_OK; } for (ls = lacf->streams[ngx_hash_key(name.data, name.len) % lacf->nbuckets]; ls; ls = ls->next) { len = ngx_strlen(ls->name); if (name.len != len || ngx_strncmp(name.data, ls->name, name.len)) { continue; } s = ngx_rtmp_control_walk_stream(r, ls); if (s != NGX_CONF_OK) { return s; } } return NGX_CONF_OK; }
//解析url中的参数,主要处理 http get 请求 inline ngx_str_t ngx_parser_http_request(ngx_http_request_t *r) { ngx_str_t value; // args is data=xxxxx // 第二个参数是HTTP GET的key名,key名的长度,第四个参数是想存这个value的变量的指针 if (NGX_OK != ngx_http_arg(r, (u_char*)"data", 4, &value)) { ngx_str_t res = ngx_null_string; return res; } ngx_str_t sentence; u_char* dst, *src; dst = (u_char*)ngx_pcalloc(r->pool, 1024);//解码后字词空间 src = value.data; sentence.data = dst; // 解析url 编码 ngx_unescape_uri(&dst, &src, value.len, 0); sentence.len = dst - sentence.data; //ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, " data=%s", sentence.data); return sentence; }
static ngx_int_t ngx_http_get_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_str_t *name = (ngx_str_t *) data; ngx_str_t value; if (ngx_http_arg(r, name->data, name->len, &value) != NGX_OK) { v->not_found = 1; return NGX_OK; } v->data = value.data; v->len = value.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; }
static ngx_int_t ngx_http_autoindex_jsonp_callback(ngx_http_request_t *r, ngx_str_t *callback) { u_char *p, c, ch; ngx_uint_t i; if (ngx_http_arg(r, (u_char *) "callback", 8, callback) != NGX_OK) { callback->len = 0; return NGX_OK; } if (callback->len > 128) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent too long callback name: \"%V\"", callback); return NGX_DECLINED; } p = callback->data; for (i = 0; i < callback->len; i++) { ch = p[i]; c = (u_char) (ch | 0x20); if (c >= 'a' && c <= 'z') { continue; } if ((ch >= '0' && ch <= '9') || ch == '_' || ch == '.') { continue; } ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client sent invalid callback name: \"%V\"", callback); return NGX_DECLINED; } return NGX_OK; }
static ngx_int_t ngx_http_pi_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; ngx_str_t aval; ngx_uint_t n; ngx_http_pi_loc_conf_t *plcf; ngx_uint_t k; u_char *pb, *buf; 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; } } plcf = ngx_http_get_module_loc_conf(r, ngx_http_pi_module); n = 2; /* first two digits "14" */ rc = ngx_http_arg(r, (u_char*) "n", 1, &aval); if (rc == NGX_OK) { rc = ngx_atoi(aval.data, aval.len); if (rc != NGX_ERROR) { n = (ngx_uint_t) rc; if (n > plcf->size) n = plcf->size; } } n += 2; buf = ngx_palloc(r->pool, n); buf[0] = '3', buf[1] = '.'; pb = buf + 2; for (k = 0; k < n/2+1; k++) { pb = ngx_sprintf(pb, "%d%d", (plcf->buf[k]&0xf0)>>4, plcf->buf[k]&0xf); } b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } out.buf = b; out.next = NULL; b->pos = buf; b->last = b->pos + n; b->memory = 1; b->last_buf = 1; b->last_in_chain = 1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; 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_xss_header_filter(ngx_http_request_t *r) { ngx_http_xss_ctx_t *ctx; ngx_http_xss_conf_t *conf; ngx_str_t callback; u_char *p, *src, *dst; if (r->headers_out.status != NGX_HTTP_OK || r != r->main) { dd("skipped: status not 200 or in subrequest"); return ngx_http_next_header_filter(r); } conf = ngx_http_get_module_loc_conf(r, ngx_http_xss_filter_module); if ( ! conf->get_enabled || r->method != NGX_HTTP_GET) { dd("skipped: get_enabled disabled or the current method is not GET"); return ngx_http_next_header_filter(r); } if (conf->callback_arg.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: xss_get is enabled but no xss_callback_arg specified"); return ngx_http_next_header_filter(r); } if (ngx_http_test_content_type(r, &conf->input_types) == NULL) { dd("skipped: content type test not passed"); return ngx_http_next_header_filter(r); } if (ngx_http_arg(r, conf->callback_arg.data, conf->callback_arg.len, &callback) != NGX_OK) { dd("skipped: no callback arg found in the current request: %.*s", conf->callback_arg.len, conf->callback_arg.data); return ngx_http_next_header_filter(r); } p = ngx_palloc(r->pool, callback.len); if (p == NULL) { return NGX_ERROR; } src = callback.data; dst = p; ngx_unescape_uri(&dst, &src, callback.len, NGX_UNESCAPE_URI_COMPONENT); if (src != callback.data + callback.len) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: unescape uri: input data not consumed completely"); return NGX_ERROR; } callback.data = p; callback.len = dst - p; if (ngx_http_xss_test_callback((char *) callback.data, callback.len) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: bad callback argument: \"%V\"", &callback); return ngx_http_next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_xss_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } /* * set by ngx_pcalloc(): * * ctx->callback = { 0, NULL }; * conf->before_body_sent = 0; */ ctx->callback = callback; ngx_http_set_ctx(r, ctx, ngx_http_xss_filter_module); r->headers_out.content_type = conf->output_type; r->headers_out.content_type_len = conf->output_type.len; ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); return ngx_http_next_header_filter(r); }
static ngx_int_t ngx_http_slice_handler(ngx_http_request_t *r) { u_char *last; off_t begin, end, len; size_t root; ngx_int_t rc; ngx_uint_t level, i; ngx_str_t path, value; ngx_log_t *log; ngx_buf_t *b; ngx_chain_t out[3]; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; ngx_http_slice_loc_conf_t *slcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } if (r->uri.data[r->uri.len - 1] == '/') { return NGX_DECLINED; } slcf = ngx_http_get_module_loc_conf(r, ngx_http_slice_module); rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } log = r->connection->log; path.len = last - path.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http slice filename: \"%V\"", &path); 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_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: 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; } if (!of.is_file) { if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", path.data); } return NGX_DECLINED; } r->root_tested = !r->error_page; begin = 0; end = of.size; if (r->args.len) { if (ngx_http_arg(r, slcf->begin.data, slcf->begin.len, &value) == NGX_OK) { begin = ngx_atoof(value.data, value.len); if (begin == NGX_ERROR || begin >= of.size) { begin = 0; } } if (ngx_http_arg(r, slcf->end.data, slcf->end.len, &value) == NGX_OK) { end = ngx_atoof(value.data, value.len); if (end == NGX_ERROR || end >= of.size) { end = of.size; } } } end = end < begin ? of.size : end; len = (end == begin) ? 0 : ((end - begin) + ((begin == 0 && slcf->header_first) ? slcf->header.len : 0) + ((end == of.size && slcf->footer_last) ? slcf->footer.len : 0)); log->action = "sending slice to client"; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = len; r->headers_out.last_modified_time = of.mtime; if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (len == 0) { r->header_only = 1; return ngx_http_send_header(r); } /* * add header when the first header is not denied */ if (slcf->header.len && !(begin == 0 && !slcf->header_first)) { b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->pos = slcf->header.data; b->last = slcf->header.data + slcf->header.len; b->memory = 1; out[0].buf = b; out[0].next = &out[1]; i = 0; } else { i = 1; } 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; } r->allow_ranges = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } b->file_pos = begin; b->file_last = end; b->in_file = b->file_last ? 1: 0; b->last_buf = 1; 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[1].buf = b; out[1].next = NULL; /* * add footer when the last footer is not denied */ if (slcf->footer.len && !(end == of.size && !slcf->footer_last)) { b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->pos = slcf->footer.data; b->last = slcf->footer.data + slcf->footer.len; b->memory = 1; b->last_buf = 1; b->last_in_chain = 1; out[2].buf = b; out[2].next = NULL; out[1].buf->last_buf = 0; out[1].buf->last_in_chain = 0; out[1].next = &out[2]; } return ngx_http_output_filter(r, &out[i]); }
static ngx_int_t ngx_http_weixin_auth(ngx_http_request_t *r) { u_char *p; ngx_int_t rc; ngx_str_t signature, str, array_str[3], tmp; ngx_sha1_t sha; u_char sha_buf[SHA_DIGEST_LENGTH]; u_char sha_buf_str[SHA_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; ngx_http_weixin_auth_loc_conf_t *auth_conf; auth_conf = ngx_http_get_module_loc_conf(r, ngx_http_weixin_auth_module); if (ngx_http_arg(r, (u_char *) "signature", 9, &signature) != NGX_OK) { return NGX_DECLINED; } if (ngx_http_arg(r, (u_char *) "timestamp", 9, &array_str[0]) != NGX_OK) { return NGX_DECLINED; } if (ngx_http_arg(r, (u_char *) "nonce", 5, &array_str[1]) != NGX_OK) { return NGX_DECLINED; } if (signature.len != SHA_DIGEST_LENGTH * 2) { return NGX_DECLINED; } array_str[2] = auth_conf->token; // token¡¢timestamp¡¢nonce if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) { tmp = array_str[0]; array_str[0] = array_str[1]; array_str[1] = tmp; } if (ngx_memn2cmp(array_str[1].data, array_str[2].data, array_str[1].len, array_str[2].len) > 0) { tmp = array_str[1]; array_str[1] = array_str[2]; array_str[2] = tmp; } if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) { tmp = array_str[0]; array_str[0] = array_str[1]; array_str[1] = tmp; } str.len = array_str[0].len + array_str[1].len + array_str[2].len; str.data = ngx_pcalloc(r->pool, str.len + 1); if (str.data == NULL) { return NGX_ERROR; } p = str.data; p = ngx_cpymem(p, array_str[0].data, array_str[0].len); p = ngx_cpymem(p, array_str[1].data, array_str[1].len); p = ngx_cpymem(p, array_str[2].data, array_str[2].len); p = '\0'; ngx_sha1_init(&sha); ngx_sha1_update(&sha, str.data, str.len); ngx_sha1_final(sha_buf, &sha); p = ngx_hex_dump(sha_buf_str, sha_buf, SHA_DIGEST_LENGTH); p = '\0'; rc = ngx_memcmp(sha_buf_str, signature.data, SHA_DIGEST_LENGTH * 2); if (rc != 0) { return NGX_DECLINED; } return NGX_OK; }
//----------------------------------------------------------------------------- static int ngx_c2h5oh_init_query_data(ngx_http_request_t *r, ngx_c2h5oh_ctx_t * ctx) { ngx_uint_t i; ngx_table_elt_t **h; ngx_c2h5oh_loc_conf_t * alcf = ngx_http_get_module_loc_conf(r, ngx_c2h5oh_module); h = r->headers_in.cookies.elts; ngx_c2h5oh_query_data_set_len(r, ctx); ctx->query.data = ngx_palloc(r->pool, ctx->query.len); ctx->query.len = 0; ngx_memcpy(ctx->query.data, k_ngx_c2h5oh_select, sizeof(k_ngx_c2h5oh_select));//}', '{}')"); ctx->query.len = sizeof(k_ngx_c2h5oh_select) - 1; if (alcf->route.len == 0) { u_char * p = r->uri.data + 1 + alcf->root.len; if (r->uri.len == 1) { ngx_memcpy(ctx->query.data + ctx->query.len, "index", sizeof("index") - 1); } else { while(p < r->uri.data + r->uri.len) { if ((*p >= 0x30 && *p <= 0x39) || (*p >= 0x61 && *p <= 0x7a)) { *(ctx->query.data + ctx->query.len++) = *p; } else if (*p >= 0x41 && *p <= 0x5a) { *(ctx->query.data + ctx->query.len++) = *p + 0x20; } else if (*p == '/') { *(ctx->query.data + ctx->query.len++) = '_'; } p++; } if (*(ctx->query.data + ctx->query.len - 1) == '_') { ctx->query.len--; } } strcpy((char *)ctx->query.data + ctx->query.len, "('{"); ctx->query.len += sizeof("('{") - 1; } else { ngx_memcpy(ctx->query.data + ctx->query.len, alcf->route.data, alcf->route.len); ctx->query.len += alcf->route.len; strcpy((char *)ctx->query.data + ctx->query.len, "('"); ctx->query.len += sizeof("('") - 1; u_char * p = r->uri.data + alcf->root.len; while(p < r->uri.data + r->uri.len) { *(ctx->query.data + ctx->query.len++) = *p; if (*p == '\'') { *(ctx->query.data + ctx->query.len++) = *p; } p++; } *(ctx->query.data + ctx->query.len++) = '\''; *(ctx->query.data + ctx->query.len++) = ','; *(ctx->query.data + ctx->query.len++) = '\''; *(ctx->query.data + ctx->query.len++) = '{'; } u_char * cookies_start = ctx->query.data + ctx->query.len; for(i = 0; i < r->headers_in.cookies.nelts; i++) { ngx_c2h5oh_parse_cookies(&ctx->query, &h[i]->value, cookies_start); } ngx_memcpy(ctx->query.data + ctx->query.len, "}','{", 5); ctx->query.len += sizeof("}','{") - 1; u_char * args_start = ctx->query.data + ctx->query.len; if (ngx_http_arg(r, (u_char*)"callback", sizeof("callback") - 1, &ctx->callback) != NGX_OK) { ctx->callback.len = 0; } if (ngx_c2h5oh_parse_args(r, &ctx->query, r->args.data, r->args.data + r->args.len, args_start) != 0) { return -1; } if (r->request_body && r->request_body->buf && r->headers_in.content_type && r->request_body_in_single_buf) { if (r->request_body_in_single_buf) { if (ngx_memcmp(r->headers_in.content_type->value.data, "application/x-www-form-urlencoded", sizeof("application/x-www-form-urlencoded") - 1) == 0) { if (r->request_body->buf) { if (ngx_c2h5oh_parse_args(r, &ctx->query, r->request_body->buf->pos, r->request_body->buf->last, args_start) != 0) { return -1; } } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] request_body is null"); } } else { // TODO: pass whole body as parameter } } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] request_body not in single buf"); } } // TODO ngx_memcpy(ctx->query.data + ctx->query.len, "}');", sizeof("}');")); ctx->query.len += sizeof("}');"); return 0; }
static ngx_int_t ngx_hls_handler(ngx_http_request_t *r) { //ngx_log_t *log = r->connection->log; if(!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))){ return NGX_HTTP_NOT_ALLOWED; } ngx_http_hls_loc_conf_t *elcf = ngx_http_get_module_loc_conf(r,ngx_http_hls_module); char* media_type = ngx_http_hls_convert_string(elcf->media_type); char* media_path = ngx_http_hls_convert_string(elcf->media_path); //char *media_type = (char*)elcf->media_type.data; //char *media_path = (char*)elcf->media_path.data; ngx_int_t rc = ngx_http_discard_request_body(r); if(rc != NGX_OK){ return rc; } if(strcmp(media_type,"live") == 0){ //TODO:Live media. } else{ ngx_str_t media_file; ngx_str_t media_start; ngx_str_t media_end; ngx_http_arg(r, (u_char *)"media", 5, &media_file); rc = ngx_http_arg(r,(u_char *)"start",5,&media_start); ngx_http_arg(r, (u_char *)"end", 3 , &media_end); if(rc == NGX_DECLINED || media_start.len == 0){ char filename[512]; bzero(filename,512); ngx_str_t type = ngx_string("application/x-mpegURL");//m3u8文件的content type ngx_snprintf((u_char*)filename,1024,"%s%V.m3u8",media_path,&media_file); //M3U8文件不存在,目前采用直接返回错误的方式,后期采用根据TS文件创建新的M3U8 if(access((char*)filename,F_OK) == -1){ ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); //r->headers_out.status = NGX_HTTP_NOT_FOUND; //rc = ngx_http_send_header(r); return NGX_HTTP_NOT_FOUND; } else{ ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b; //b = ngx_create_temp_buf(r->pool,sizeof(ngx_buf_t)); b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN, 0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename) -1; if(ngx_file_info(filename,&b->file->info) == NGX_FILE_ERROR){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->file->info.st_size; r->headers_out.content_type = type; b->file_pos = 0; b->file_last = b->file->info.st_size; b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 1; //清理文件句柄 /* ngx_pool_cleanup_t *cln = ngx_pool_cleanup_add(r->pool,sizeof(ngx_pool_cleanup_file_t)); if(cln == NULL){ return NGX_ERROR; } cln->handler = ngx_pool_cleanup_file; ngx_pool_cleanup_file_t *clnf = cln->data; clnf->fd = b->file->fd; clnf->name = b->file->name.data; clnf->log = r->pool->log; */ 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); } } else{ ngx_str_t type = ngx_string("video/mp2t"); //ts文件的content type //ngx_str_t type = ngx_string("application/octet-stream"); char filename[512]; bzero(filename,512); ngx_snprintf((u_char*)filename,512,"%s%V.ts",media_path,&media_file); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"File[%s] is not exist!media_path = %s,media_file=%V",filename,media_path,&media_file); r->allow_ranges = 1; //开启range选项 char *start = ngx_http_hls_convert_string(media_start); char *end = ngx_http_hls_convert_string(media_end); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"start=%s;end=%s",start,end); ngx_chain_t *out = ngx_pcalloc(r->pool,sizeof(ngx_chain_t)); ngx_buf_t *b = ngx_pcalloc(r->pool,sizeof(ngx_buf_t)); if(b == NULL){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->in_file = 1; b->file = ngx_pcalloc(r->pool,sizeof(ngx_file_t)); b->file->fd = ngx_open_file(filename,NGX_FILE_RDONLY|NGX_FILE_NONBLOCK, NGX_FILE_OPEN,0); if(b->file->fd == -1){ return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->file->name.data = (u_char*)filename; b->file->name.len = sizeof(filename)-1; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = atol(end)-atol(start); ngx_log_error(NGX_LOG_CRIT,r->connection->log,0,"%d",r->headers_out.content_length_n); r->headers_out.content_type = type; b->file_pos = atol(start); b->file_last= atol(end); b->last_in_chain = 1; b->file->log = r->connection->log; b->last_buf = 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); } } return NGX_OK; }
static ngx_int_t ngx_http_flv_handler(ngx_http_request_t *r) { u_char *last; off_t start, len; size_t root; ngx_int_t rc; ngx_uint_t level, i; ngx_str_t path, value; ngx_log_t *log; ngx_buf_t *b; ngx_chain_t out[2]; ngx_open_file_info_t of; ngx_http_core_loc_conf_t *clcf; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } if (r->uri.data[r->uri.len - 1] == '/') { return NGX_DECLINED; } rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } last = ngx_http_map_uri_to_path(r, &path, &root, 0); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } log = r->connection->log; path.len = last - path.data; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, "http flv filename: \"%V\"", &path); 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_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: 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; } if (!of.is_file) { if (ngx_close_file(of.fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", path.data); } return NGX_DECLINED; } r->root_tested = !r->error_page; start = 0; len = of.size; i = 1; if (r->args.len) { if (ngx_http_arg(r, (u_char *) "start", 5, &value) == NGX_OK) { start = ngx_atoof(value.data, value.len); if (start == NGX_ERROR || start >= len) { start = 0; } if (start) { len = sizeof(ngx_flv_header) - 1 + len - start; i = 0; } } } log->action = "sending flv to client"; r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = len; r->headers_out.last_modified_time = of.mtime; if (ngx_http_set_content_type(r) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (i == 0) { b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } b->pos = ngx_flv_header; b->last = ngx_flv_header + sizeof(ngx_flv_header) - 1; b->memory = 1; out[0].buf = b; out[0].next = &out[1]; } 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; } r->allow_ranges = 1; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } b->file_pos = start; b->file_last = of.size; b->in_file = b->file_last ? 1: 0; b->last_buf = 1; 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[1].buf = b; out[1].next = NULL; return ngx_http_output_filter(r, &out[i]); }
static ngx_int_t ngx_http_shmtest_get(ngx_http_request_t *r){ ngx_int_t rc = NGX_HTTP_OK; ngx_str_t key = ngx_null_string; ngx_str_t value = ngx_null_string; int32_t ikey = 0; uint8_t value_type = VT_BINARY; uint32_t exptime = 0; uint32_t user_flags = 0; if(ngx_http_arg(r, (u_char*)"key", 3, &key)!=NGX_OK){ NLOG_ERROR("get arg 'key' failed!"); return NGX_HTTP_BAD_REQUEST; } if(key.len > 2 && key.data[0] == '0' && key.data[1] == 'x'){ key.data += 2; key.len -= 2; ikey = ngx_hextoi(key.data, key.len); ngx_str_set_int32(&key, &ikey); NLOG_DEBUG("use int key ikey=%d", ikey); } shmtest_main_conf_t* smcf; smcf = ngx_http_get_module_main_conf(r, ngx_http_shmtest_module); if(smcf == NULL){ NLOG_ERROR("get module ngx_http_shmtest_module's main conf failed!"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_shm_zone_t* zone = smcf->shmap; u_char* rsp = ngx_pcalloc(r->connection->pool, 256); int rsp_len = 0; rc = ngx_shmap_get(zone, &key, &value, &value_type, &exptime, &user_flags); if(ikey != 0){ if(rc == 0){ rsp_len = ngx_sprintf(rsp, "get(%d)={value=%V,exptime=%d,user_flags=%d}!\n", ikey,&value,exptime,user_flags)-rsp; }else{ rsp_len = ngx_sprintf(rsp, "get(%d) failed!\n", ikey)-rsp; } }else{ if(rc == 0){ rsp_len = ngx_sprintf(rsp, "get(%V)={value=%V,exptime=%d,user_flags=%d}!\n", &key,&value,exptime,user_flags)-rsp; }else{ rsp_len = ngx_sprintf(rsp, "get(%V) failed!\n", &key)-rsp; } } ngx_chain_t* chain = ngx_http_shmtest_resp(r, (char*)rsp, rsp_len); if(chain != NULL){ r->headers_out.content_length_n = rsp_len; }else{ r->headers_out.content_length_n = 0; } rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { }else{ rc = ngx_http_output_filter(r, chain); } return rc; }
static ngx_int_t ngx_screenshot_handler(ngx_http_request_t *r) { size_t len; u_char *p; ngx_buf_t *b; ngx_chain_t cl; u_char path[1024]; ExceptionInfo *exception; Image *image = 0, *resized = 0; ImageInfo *image_info = 0; unsigned char *image_data; ngx_str_t size; ngx_int_t width = -1, height = -1; ngx_screenshot_sizes_conf_t *screenshot_sizes_conf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_screenshot_module); ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "TEST %d", screenshot_sizes_conf->sizes.nelts); //TODO: generate unique name system("avconv -analyzeduration 1000 -i \"rtmp://127.0.0.1:1935\" -vframes 1 -q:v 2 -f image2 /tmp/output.png -loglevel quiet"); MagickCoreGenesis("", MagickTrue); exception = AcquireExceptionInfo(); ngx_memzero(path, sizeof(path)); strcpy((char *)path, "/tmp/output.png"); image_info = CloneImageInfo((ImageInfo *)NULL); strcpy(image_info->filename, (const char*)path); image = ReadImage(image_info, exception); if (image == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to open screenshot file"); goto error; } if (ngx_http_arg(r, (u_char *) "size", sizeof("size") - 1, &size) == NGX_OK) { if (size.len > 0) { if (size.data[0] == 'l' && size.data[1] == 'o' && size.data[2] == 'w') { width = 320; height = 180; } else if (size.data[0] == 'm' && size.data[1] == 'e' && size.data[2] == 'd') { width = 640; height = 360; } else if (size.data[0] == 'h' && size.data[1] == 'i') { width = 960; height = 540; } else if (size.data[0] == 'h' && size.data[1] == 'd') { width = 1280; height = 720; } } } if (width < 1 || width > (ngx_int_t)image->columns) { width = image->columns; } if (height < 1 || height > (ngx_int_t)image->rows) { height = image->rows; } if (width == (ngx_int_t)image->columns && height == (ngx_int_t)image->rows) { resized = image; } else { resized = ResizeImage(image, width, height, SincFilter, 1.0, exception); } if (resized == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to resize screenshot file"); goto error; } image_data = ImageToBlob(image_info, resized, &len, exception); p = ngx_palloc(r->connection->pool, len); if (p == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate memory for response"); goto error; } ngx_memcpy(p, image_data, len); if (resized != image) { DestroyImage(resized); } DestroyImage(image); MagicComponentTerminus(); ngx_str_set(&r->headers_out.content_type, "image/png"); r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = len; b = ngx_calloc_buf(r->pool); if (b == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "Failed to allocate memory for response"); goto error; } b->start = b->pos = p; b->end = b->last = p + len; b->temporary = 1; b->last_buf = 1; ngx_memzero(&cl, sizeof(cl)); cl.buf = b; ngx_http_send_header(r); return ngx_http_output_filter(r, &cl); error: if (resized && resized != image) DestroyImage(resized); if (image) DestroyImage(image); MagicComponentTerminus(); return NGX_HTTP_INTERNAL_SERVER_ERROR; }
static ngx_int_t ngx_http_xss_header_filter(ngx_http_request_t *r) { ngx_http_xss_ctx_t *ctx; ngx_http_xss_loc_conf_t *xlcf; ngx_str_t callback; u_char *p, *src, *dst; if (r != r->main) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss skipped in subrequests"); return ngx_http_next_header_filter(r); } xlcf = ngx_http_get_module_loc_conf(r, ngx_http_xss_filter_module); if (!xlcf->get_enabled) { return ngx_http_next_header_filter(r); } if (r->method != NGX_HTTP_GET) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss skipped due to the unmatched request method: %V", &r->method_name); return ngx_http_next_header_filter(r); } if (xlcf->check_status) { if (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_CREATED) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss skipped due to unmatched response status " "\"%ui\"", r->headers_out.status); return ngx_http_next_header_filter(r); } } if (xlcf->callback_arg.len == 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: xss_get is enabled but no xss_callback_arg " "specified"); return ngx_http_next_header_filter(r); } if (ngx_http_test_content_type(r, &xlcf->input_types) == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss skipped due to unmatched Content-Type response " "header"); return ngx_http_next_header_filter(r); } if (ngx_http_arg(r, xlcf->callback_arg.data, xlcf->callback_arg.len, &callback) != NGX_OK) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss skipped: no GET argument \"%V\" specified in " "the request", &xlcf->callback_arg); return ngx_http_next_header_filter(r); } p = ngx_palloc(r->pool, callback.len); if (p == NULL) { return NGX_ERROR; } src = callback.data; dst = p; ngx_unescape_uri(&dst, &src, callback.len, NGX_UNESCAPE_URI_COMPONENT); if (src != callback.data + callback.len) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: unescape uri: input data not consumed completely"); return NGX_ERROR; } callback.data = p; callback.len = dst - p; if (ngx_http_xss_test_callback(callback.data, callback.len) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "xss: bad callback argument: \"%V\"", &callback); return ngx_http_next_header_filter(r); } ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_xss_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } /* * set by ngx_pcalloc(): * * ctx->callback = { 0, NULL }; * ctx->before_body_sent = 0; */ ctx->callback = callback; ngx_http_set_ctx(r, ctx, ngx_http_xss_filter_module); r->headers_out.content_type = xlcf->output_type; r->headers_out.content_type_len = xlcf->output_type.len; r->headers_out.content_type_lowcase = NULL; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "xss output Content-Type header \"%V\"", &xlcf->output_type); ngx_http_clear_content_length(r); ngx_http_clear_accept_ranges(r); if (xlcf->override_status && r->headers_out.status >= NGX_HTTP_SPECIAL_RESPONSE) { r->headers_out.status = NGX_HTTP_OK; } return ngx_http_next_header_filter(r); }
static ngx_int_t ngx_http_restful_parse_action_raw(ngx_http_request_t *r, ngx_http_tfs_restful_ctx_t *ctx) { ngx_int_t rc; ngx_str_t arg_value; switch(r->method) { case NGX_HTTP_GET: if (ngx_http_arg(r, (u_char *) "suffix", 6, &arg_value) == NGX_OK) { ctx->file_suffix = arg_value; } rc = ngx_http_tfs_raw_fsname_parse(&ctx->file_path_s, &ctx->file_suffix, &ctx->fsname); if (rc != NGX_OK) { return NGX_HTTP_BAD_REQUEST; } if (ngx_http_arg(r, (u_char *) "type", 4, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->read_stat_type = ngx_atoi(arg_value.data, arg_value.len); /* normal_read/stat(0) or force_read/stat(1) */ if (ctx->read_stat_type == NGX_ERROR || (ctx->read_stat_type != NGX_HTTP_TFS_READ_STAT_NORMAL && ctx->read_stat_type != NGX_HTTP_TFS_READ_STAT_FORCE)) { return NGX_HTTP_BAD_REQUEST; } } if (ctx->meta) { ctx->action.code = NGX_HTTP_TFS_ACTION_STAT_FILE; ngx_str_set(&ctx->action.msg, "stat_file"); } else { ctx->action.code = NGX_HTTP_TFS_ACTION_READ_FILE; ngx_str_set(&ctx->action.msg, "read_file"); if (ngx_http_arg(r, (u_char *) "offset", 6, &arg_value) == NGX_OK) { ctx->offset = ngx_http_tfs_atoll(arg_value.data, arg_value.len); if (ctx->offset == NGX_ERROR) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "size", 4, &arg_value) == NGX_OK) { rc = ngx_http_tfs_atoull(arg_value.data, arg_value.len, (unsigned long long *)&ctx->size); if (rc == NGX_ERROR) { return NGX_HTTP_BAD_REQUEST; } if (ctx->size == 0) { return NGX_HTTP_BAD_REQUEST; } return NGX_OK; } ctx->size = NGX_HTTP_TFS_MAX_SIZE; } break; case NGX_HTTP_POST: ctx->action.code = NGX_HTTP_TFS_ACTION_WRITE_FILE; if (ngx_http_arg(r, (u_char *) "suffix", 6, &arg_value) == NGX_OK) { ctx->file_suffix = arg_value; } if (ngx_http_arg(r, (u_char *) "simple_name", 11, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->simple_name = ngx_atoi(arg_value.data, arg_value.len); if (ctx->simple_name == NGX_ERROR || (ctx->simple_name != NGX_HTTP_TFS_NO && ctx->simple_name != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "large_file", 10, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->large_file = ngx_atoi(arg_value.data, arg_value.len); if (ctx->large_file == NGX_ERROR || (ctx->large_file != NGX_HTTP_TFS_NO && ctx->large_file != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "meta_segment", 12, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->write_meta_segment = ngx_atoi(arg_value.data, arg_value.len); if (ctx->write_meta_segment == NGX_ERROR || (ctx->write_meta_segment != NGX_HTTP_TFS_NO && ctx->write_meta_segment != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "no_dedup", 8, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->no_dedup = ngx_atoi(arg_value.data, arg_value.len); if (ctx->no_dedup == NGX_ERROR || (ctx->no_dedup != NGX_HTTP_TFS_NO && ctx->no_dedup != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } ngx_str_set(&ctx->action.msg, "write_file"); break; case NGX_HTTP_DELETE: ctx->action.code = NGX_HTTP_TFS_ACTION_REMOVE_FILE; ngx_str_set(&ctx->action.msg, "remove_file"); /* for outer user use */ if (ngx_http_arg(r, (u_char *) "hide", 4, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->unlink_type = ngx_atoi(arg_value.data, arg_value.len); /* hide(1) or reveal(0)*/ if (ctx->unlink_type == NGX_ERROR || (ctx->unlink_type != 0 && ctx->unlink_type != 1)) { return NGX_HTTP_BAD_REQUEST; } /* convert to actual type */ if (ctx->unlink_type == 1) { ctx->unlink_type = NGX_HTTP_TFS_UNLINK_CONCEAL; } else { ctx->unlink_type = NGX_HTTP_TFS_UNLINK_REVEAL; } } if (ngx_http_arg(r, (u_char *) "type", 4, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->unlink_type = ngx_atoi(arg_value.data, arg_value.len); /* del(0) or undel(2) or hide(4) or reveal(6)*/ if (ctx->unlink_type == NGX_ERROR || (ctx->unlink_type != NGX_HTTP_TFS_UNLINK_DELETE && ctx->unlink_type != NGX_HTTP_TFS_UNLINK_UNDELETE && ctx->unlink_type != NGX_HTTP_TFS_UNLINK_CONCEAL && ctx->unlink_type != NGX_HTTP_TFS_UNLINK_REVEAL)) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "suffix", 6, &arg_value) == NGX_OK) { ctx->file_suffix = arg_value; } rc = ngx_http_tfs_raw_fsname_parse(&ctx->file_path_s, &ctx->file_suffix, &ctx->fsname); if (rc != NGX_OK) { return NGX_HTTP_BAD_REQUEST; } /* large file not support UNDELETE */ if ((ctx->fsname.file_type == NGX_HTTP_TFS_LARGE_FILE_TYPE) && ctx->unlink_type == NGX_HTTP_TFS_UNLINK_UNDELETE) { return NGX_HTTP_BAD_REQUEST; } break; case NGX_HTTP_HEAD: if (ngx_http_arg(r, (u_char *) "suffix", 6, &arg_value) == NGX_OK) { ctx->file_suffix = arg_value; } rc = ngx_http_tfs_raw_fsname_parse(&ctx->file_path_s, &ctx->file_suffix, &ctx->fsname); if (rc != NGX_OK) { return NGX_HTTP_BAD_REQUEST; } if (ngx_http_arg(r, (u_char *) "type", 4, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->read_stat_type = ngx_atoi(arg_value.data, arg_value.len); /* normal_read/stat(0) or force_read/stat(1) */ if (ctx->read_stat_type == NGX_ERROR || (ctx->read_stat_type != NGX_HTTP_TFS_READ_STAT_NORMAL && ctx->read_stat_type != NGX_HTTP_TFS_READ_STAT_FORCE)) { return NGX_HTTP_BAD_REQUEST; } } ctx->action.code = NGX_HTTP_TFS_ACTION_STAT_FILE; ngx_str_set(&ctx->action.msg, "stat_file"); ctx->chk_exist = NGX_HTTP_TFS_YES; break; case NGX_HTTP_PUT: ctx->action.code = NGX_HTTP_TFS_ACTION_WRITE_FILE; if (ngx_http_arg(r, (u_char *) "suffix", 6, &arg_value) == NGX_OK) { ctx->file_suffix = arg_value; } if (ngx_http_arg(r, (u_char *) "simple_name", 11, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->simple_name = ngx_atoi(arg_value.data, arg_value.len); if (ctx->simple_name == NGX_ERROR || (ctx->simple_name != NGX_HTTP_TFS_NO && ctx->simple_name != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } if (ctx->file_path_s.data == NULL) { return NGX_HTTP_BAD_REQUEST; } /* large file not support update */ if (ngx_http_arg(r, (u_char *) "large_file", 10, &arg_value) == NGX_OK) { return NGX_HTTP_BAD_REQUEST; } rc = ngx_http_tfs_raw_fsname_parse(&ctx->file_path_s, &ctx->file_suffix, &ctx->fsname); /* large file not support update */ if (rc != NGX_OK || (ctx->fsname.file_type == NGX_HTTP_TFS_LARGE_FILE_TYPE)) { return NGX_HTTP_BAD_REQUEST; } ctx->is_raw_update = NGX_HTTP_TFS_YES; ngx_str_set(&ctx->action.msg, "write_file"); break; default: return NGX_HTTP_BAD_REQUEST; } return NGX_OK; }
static ngx_int_t ngx_http_restful_parse_action(ngx_http_request_t *r, ngx_http_tfs_restful_ctx_t *ctx) { ngx_int_t rc; ngx_str_t arg_value, file_path_d, file_temp_path; switch(r->method) { case NGX_HTTP_GET: if (ctx->get_appid) { ctx->action.code = NGX_HTTP_TFS_ACTION_GET_APPID; ngx_str_set(&ctx->action.msg, "get_appid"); return NGX_OK; } if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { if (ctx->meta) { ctx->action.code = NGX_HTTP_TFS_ACTION_LS_FILE; ngx_str_set(&ctx->action.msg, "ls_file"); return NGX_OK; } ctx->action.code = NGX_HTTP_TFS_ACTION_READ_FILE; ngx_str_set(&ctx->action.msg, "read_file"); if (r->headers_in.range != NULL) { return NGX_HTTP_BAD_REQUEST; } if (ngx_http_arg(r, (u_char *) "check_hole", 10, &arg_value) == NGX_OK) { ctx->chk_file_hole = ngx_atoi(arg_value.data, arg_value.len); if (ctx->chk_file_hole == NGX_ERROR || (ctx->chk_file_hole != NGX_HTTP_TFS_NO && ctx->chk_file_hole != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "offset", 6, &arg_value) == NGX_OK) { ctx->offset = ngx_http_tfs_atoll(arg_value.data, arg_value.len); if (ctx->offset == NGX_ERROR) { return NGX_HTTP_BAD_REQUEST; } } if (ngx_http_arg(r, (u_char *) "size", 4, &arg_value) == NGX_OK) { rc = ngx_http_tfs_atoull(arg_value.data, arg_value.len, (unsigned long long *)&ctx->size); if (rc == NGX_ERROR) { return NGX_HTTP_BAD_REQUEST; } if (ctx->size == 0) { return NGX_HTTP_BAD_REQUEST; } return NGX_OK; } ctx->size = NGX_HTTP_TFS_MAX_SIZE; return NGX_OK; } ctx->action.code = NGX_HTTP_TFS_ACTION_LS_DIR; ngx_str_set(&ctx->action.msg, "ls_dir"); return NGX_OK; case NGX_HTTP_POST: if (ngx_http_tfs_parse_headerin(r, &ali_move_source, &file_path_d) == NGX_OK) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "move from %V to %V", &file_path_d, &ctx->file_path_s); if (file_path_d.len < 1 || file_path_d.len > NGX_HTTP_TFS_MAX_FILE_NAME_LEN || ctx->file_path_s.len == 1) { return NGX_HTTP_BAD_REQUEST; } if (ctx->file_path_s.len == file_path_d.len && ngx_strncmp(ctx->file_path_s.data, file_path_d.data, file_path_d.len) == 0) { return NGX_HTTP_BAD_REQUEST; } file_temp_path = ctx->file_path_s; ctx->file_path_s = file_path_d; ctx->file_path_d = file_temp_path; if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { ctx->action.code = NGX_HTTP_TFS_ACTION_MOVE_FILE; ngx_str_set(&ctx->action.msg, "move_file"); } else { ctx->action.code = NGX_HTTP_TFS_ACTION_MOVE_DIR; ngx_str_set(&ctx->action.msg, "move_dir"); } } else { if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { ctx->action.code = NGX_HTTP_TFS_ACTION_CREATE_FILE; ngx_str_set(&ctx->action.msg, "create_file"); } else { /* forbid create "/" */ if (ctx->file_path_s.len == 1) { return NGX_HTTP_BAD_REQUEST; } ctx->action.code = NGX_HTTP_TFS_ACTION_CREATE_DIR; ngx_str_set(&ctx->action.msg, "create_dir"); } } if (ngx_http_arg(r, (u_char *) "recursive", 9, &arg_value) == NGX_OK) { if (arg_value.len != 1) { return NGX_HTTP_BAD_REQUEST; } ctx->recursive = ngx_atoi(arg_value.data, arg_value.len); if (ctx->recursive == NGX_ERROR || (ctx->recursive != NGX_HTTP_TFS_NO && ctx->recursive != NGX_HTTP_TFS_YES)) { return NGX_HTTP_BAD_REQUEST; } } break; case NGX_HTTP_PUT: if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { ctx->action.code = NGX_HTTP_TFS_ACTION_WRITE_FILE; ngx_str_set(&ctx->action.msg, "write_file"); if (ngx_http_arg(r, (u_char *) "offset", 6, &arg_value) == NGX_OK) { ctx->offset = ngx_http_tfs_atoll(arg_value.data, arg_value.len); if (ctx->offset == NGX_ERROR) { return NGX_HTTP_BAD_REQUEST; } } else { /* no specify offset, append by default */ ctx->offset = NGX_HTTP_TFS_APPEND_OFFSET; } return NGX_OK; } /* forbid put aciont on dir */ return NGX_ERROR; case NGX_HTTP_DELETE: if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { ctx->action.code = NGX_HTTP_TFS_ACTION_REMOVE_FILE; ngx_str_set(&ctx->action.msg, "remove_file"); /* for t->file.left_length */ ctx->size = NGX_HTTP_TFS_MAX_SIZE; return NGX_OK; } /* forbid delete "/" */ if (ctx->file_path_s.len == 1) { return NGX_HTTP_BAD_REQUEST; } ctx->action.code = NGX_HTTP_TFS_ACTION_REMOVE_DIR; ngx_str_set(&ctx->action.msg, "remove_dir"); break; case NGX_HTTP_HEAD: if (ctx->file_type == NGX_HTTP_TFS_CUSTOM_FT_FILE) { ctx->action.code = NGX_HTTP_TFS_ACTION_LS_FILE; ngx_str_set(&ctx->action.msg, "ls_file"); } else { ctx->action.code = NGX_HTTP_TFS_ACTION_LS_DIR; ngx_str_set(&ctx->action.msg, "ls_dir"); } ctx->chk_exist = NGX_HTTP_TFS_YES; return NGX_OK; } return NGX_OK; }
static ngx_int_t ngx_http_conhash_test_handler(ngx_http_request_t *r) { ngx_int_t rc, cmd; ngx_chain_t out; ngx_str_t value; ngx_conhash_t *conhash; ngx_http_conhash_test_main_conf_t *ctmcf; ctmcf = ngx_http_get_module_main_conf(r, ngx_http_conhash_test_module); conhash = ctmcf->conhash; out.buf = NULL; out.next = NULL; if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } if (conhash == NULL) { return NGX_DECLINED; } rc = ngx_http_arg(r, (u_char *) KEY_STR, sizeof(KEY_STR) - 1, &value); if (rc != NGX_OK) { return rc; } cmd = ngx_atoi(value.data, value.len); if (cmd < 1 && cmd > 4) { return NGX_DECLINED; } switch (cmd) { case 1: // add rc = ngx_http_conhash_test_add(r, conhash, &out); break; case 2: // del rc = ngx_http_conhash_test_del(r, conhash, &out); break; case 3: // search rc = ngx_http_conhash_test_search(r, conhash, &out); break; case 4: // traverse rc = ngx_http_conhash_test_traverse(r, conhash, &out); break; case 5: // clear rc = ngx_http_conhash_test_clear(r, conhash, &out); break; } if (rc != NGX_OK) { return rc; } r->headers_out.status = NGX_HTTP_OK; ngx_str_set(&r->headers_out.content_type, "text/plain"); if (out.buf != NULL) { r->headers_out.content_length_n = ngx_buf_size(out.buf); } else { r->header_only = 1; r->headers_out.content_length_n = 0; } 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_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; 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) { 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; } 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; } } } } 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) { 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); } 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; }
static ngx_int_t ngx_http_shmtest_add_or_update(ngx_http_request_t *r,int func){ ngx_int_t rc = NGX_HTTP_OK; ngx_str_t key = ngx_null_string; int32_t ikey = 0; ngx_str_t value = ngx_null_string; char* szFunc = funcs[func]; if(ngx_http_arg(r, (u_char*)"key", 3, &key)!=NGX_OK){ NLOG_ERROR("get arg 'key' failed!"); return NGX_HTTP_BAD_REQUEST; } if(ngx_http_arg(r, (u_char*)"value", 5, &value)!=NGX_OK){ NLOG_ERROR("get arg 'value' failed!"); return NGX_HTTP_BAD_REQUEST; } //如果key开始为0x 表示使用数字的KEY. if(key.len > 2 && key.data[0] == '0' && key.data[1] == 'x'){ key.data += 2; key.len -= 2; ikey = ngx_hextoi(key.data, key.len); ngx_str_set_int32(&key, &ikey); NLOG_DEBUG("use int key ikey=%d", ikey); } uint64_t exptime = 0; ngx_str_t sexptime = ngx_null_string; if(ngx_http_arg(r, (u_char*)"exptime", 7, &sexptime)==NGX_OK){ exptime = ngx_parse_time(&sexptime, 1); } if(ikey != 0){ NLOG_DEBUG("%s(key=%d,value=%V,exptime=%d)", szFunc,ikey,&value,exptime); }else{ NLOG_DEBUG("%s(key=%V,value=%V,exptime=%d)", szFunc,&key,&value,exptime); } shmtest_main_conf_t* smcf; smcf = ngx_http_get_module_main_conf(r, ngx_http_shmtest_module); if(smcf == NULL){ NLOG_ERROR("get module ngx_http_shmtest_module's main conf failed!"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_shm_zone_t* zone = smcf->shmap; int ret = 0; switch(func){ case FUNC_ADD: ret = ngx_shmap_add(zone, &key,&value,VT_STRING,exptime,0); break; case FUNC_SET: ret = ngx_shmap_set(zone, &key,&value,VT_STRING,exptime,0); break; case FUNC_REPLACE: ret = ngx_shmap_replace(zone, &key,&value,VT_STRING,exptime,0); break; default: NLOG_ERROR("un process type [%d]", func); return NGX_HTTP_BAD_REQUEST; } char* rsp = ngx_pcalloc(r->connection->pool, 256); int rsp_len = 0; if(ret == 0){ rsp_len = sprintf(rsp, "%s success!\n", szFunc); }else{ rsp_len = sprintf(rsp, "%s failed!\n", szFunc); } ngx_chain_t* chain = ngx_http_shmtest_resp(r, rsp, rsp_len); if(chain != NULL){ r->headers_out.content_length_n = rsp_len; }else{ r->headers_out.content_length_n = 0; } rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { }else{ rc = ngx_http_output_filter(r, chain); } return rc; }