static ngx_int_t ngx_http_mogilefs_eval_class(ngx_http_request_t *r, ngx_http_mogilefs_loc_conf_t *mgcf) { ngx_uint_t i; ngx_http_mogilefs_class_template_t *t; ngx_str_t class; if(mgcf->class_templates == NULL) { return NGX_DECLINED; } t = mgcf->class_templates->elts; for(i = 0;i < mgcf->class_templates->nelts;i++) { if(t->lengths != NULL && t->values != NULL) { if(ngx_http_script_run(r, &class, t->lengths->elts, 0, t->values->elts) == NULL) { return NGX_ERROR; } } else { if(ngx_http_mogilefs_add_aux_param(r, &ngx_http_mogilefs_class, &t->source) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } if(class.len) { if(ngx_http_mogilefs_add_aux_param(r, &ngx_http_mogilefs_class, &class) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } t++; }
static ngx_int_t ngx_http_mogilefs_put_handler(ngx_http_request_t *r) { ngx_http_mogilefs_put_ctx_t *ctx; ngx_str_t args; ngx_uint_t flags; ngx_http_request_t *sr; ngx_str_t spare_location = ngx_null_string, uri, value; ngx_int_t rc; u_char *p; ngx_http_core_loc_conf_t *clcf; ngx_http_mogilefs_loc_conf_t *mgcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mogilefs put handler"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); mgcf = ngx_http_get_module_loc_conf(r, ngx_http_mogilefs_module); if (clcf->handler != ngx_http_mogilefs_handler || (mgcf->location_type == NGX_MOGILEFS_MAIN && !(r->method & mgcf->methods))) { return NGX_DECLINED; } ctx = ngx_http_get_module_ctx(r, ngx_http_mogilefs_module); if(ctx == NULL) { ctx = ngx_palloc(r->pool, sizeof(ngx_http_mogilefs_put_ctx_t)); if (ctx == NULL) { return NGX_ERROR; } ctx->psr = NULL; ctx->state = START; ctx->status = 0; ctx->create_open_ctx = NULL; if(ngx_http_mogilefs_eval_key(r, &ctx->key) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_mogilefs_module); } if(ctx->psr == NULL) { ctx->psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (ctx->psr == NULL) { return NGX_ERROR; } } if(r->request_body == NULL) { rc = ngx_http_read_client_request_body(r, ngx_http_mogilefs_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } return NGX_DONE; } // Still receiving body? if(r->request_body->rest) { return NGX_DONE; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mogilefs put handler state: %ui, status: %i", ctx->state, ctx->status); if(ctx->state == CREATE_OPEN || ctx->state == FETCH || ctx->state == CREATE_CLOSE) { if(ctx->status != NGX_OK && ctx->status != NGX_HTTP_CREATED && ctx->status != NGX_HTTP_NO_CONTENT) { return (ctx->status >= NGX_HTTP_SPECIAL_RESPONSE) ? ctx->status : NGX_HTTP_INTERNAL_SERVER_ERROR; } } switch(ctx->state) { case START: spare_location = mgcf->create_open_spare_location; ctx->state = CREATE_OPEN; break; case CREATE_OPEN: spare_location = mgcf->fetch_location; ctx->state = FETCH; break; case FETCH: spare_location = mgcf->create_close_spare_location; ctx->state = CREATE_CLOSE; break; case CREATE_CLOSE: r->headers_out.content_length_n = 0; r->headers_out.status = NGX_HTTP_CREATED; r->header_only = 1; return ngx_http_send_header(r); } uri.len = spare_location.len + ctx->key.len; uri.data = ngx_palloc(r->pool, uri.len); p = ngx_cpymem(uri.data, spare_location.data, spare_location.len); p = ngx_cpymem(p, ctx->key.data, ctx->key.len); args.len = 0; args.data = NULL; flags = 0; if (ngx_http_parse_unsafe_uri(r, &uri, &args, &flags) != NGX_OK) { return NGX_ERROR; } ctx->psr->handler = ngx_http_mogilefs_finish_phase_handler; ctx->psr->data = ctx; flags |= NGX_HTTP_SUBREQUEST_WAITED; if(ctx->state == FETCH) { flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY; } rc = ngx_http_subrequest(r, &uri, &args, &sr, ctx->psr, flags); if (rc == NGX_ERROR) { return rc; } if(ctx->state == CREATE_CLOSE) { ngx_http_set_ctx(sr, ctx->create_open_ctx, ngx_http_mogilefs_module); value.data = ngx_palloc(r->pool, NGX_OFF_T_LEN); if(value.data == NULL) { return NGX_ERROR; } value.len = ngx_sprintf(value.data, "%O", r->headers_in.content_length_n) - value.data; if(ngx_http_mogilefs_add_aux_param(sr, &ngx_http_mogilefs_size, &value) != NGX_OK) { return NGX_ERROR; } } /* * Nginx closes temporary file with buffered body * whenever it starts sending reponse from upstream * and it is not doing subrequest in memory. * * Since the request body in create_open subrequest is * inherited from main request, it is necessary to prevent * nginx from closing the temporary file with request body, * before it could be passed to the storage node on fetch/store * stage. * * We do it by "hiding" the request body from nginx internals. */ if(ctx->state == CREATE_OPEN) { sr->request_body = NULL; } sr->method = NGX_HTTP_PUT; sr->method_name = ngx_http_mogilefs_put_method; /* * Wait for subrequest to complete */ return NGX_DONE; }