static ngx_int_t ngx_http_groonga_handler_process_body(ngx_http_request_t *r, ngx_http_groonga_handler_data_t *data) { ngx_int_t rc; grn_ctx *context; ngx_buf_t *body; u_char *body_data; u_char *body_data_end; context = &(data->context); body = r->request_body->bufs->buf; if (!body) { ngx_http_groonga_handler_set_content_type(r, "text/plain"); GRN_TEXT_PUTS(context, &(data->body), "must send load data as body"); return NGX_HTTP_BAD_REQUEST; } rc = ngx_http_groonga_join_request_body_chain(r, r->request_body->bufs, &body_data, &body_data_end); if (rc != NGX_OK) { return rc; } rc = ngx_http_groonga_send_lines(context, r, body_data, body_data_end); ngx_pfree(r->pool, body_data); return rc; }
static ngx_int_t ngx_http_groonga_handler_validate_post_command(ngx_http_request_t *r, ngx_str_t *command_path, ngx_http_groonga_handler_data_t *data) { grn_ctx *context; ngx_str_t command; command.data = command_path->data; if (r->args.len == 0) { command.len = command_path->len; } else { command.len = command_path->len - r->args.len - strlen("?"); } if (ngx_str_equal_c_string(&command, "load")) { return NGX_OK; } context = &(data->context); ngx_http_groonga_handler_set_content_type(r, "text/plain"); GRN_TEXT_PUTS(context, &(data->body), "command for POST must be <load>: <"); GRN_TEXT_PUT(context, &(data->body), command.data, command.len); GRN_TEXT_PUTS(context, &(data->body), ">"); return NGX_HTTP_BAD_REQUEST; }
static ngx_int_t ngx_http_groonga_handler_process_body(ngx_http_request_t *r, ngx_http_groonga_handler_data_t *data) { ngx_int_t rc; grn_ctx *context; ngx_buf_t *body; u_char *line_start, *current; context = &(data->context); body = r->request_body->buf; if (!body) { ngx_http_groonga_handler_set_content_type(r, "text/plain"); GRN_TEXT_PUTS(context, &(data->body), "must send load data as body"); return NGX_HTTP_BAD_REQUEST; } for (line_start = current = body->pos; current < body->last; current++) { if (*current != '\n') { continue; } grn_ctx_send(context, (const char *)line_start, current - line_start, GRN_NO_FLAGS); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } line_start = current + 1; } if (line_start < current) { grn_ctx_send(context, (const char *)line_start, current - line_start, GRN_NO_FLAGS); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } } return NGX_OK; }
static ngx_int_t ngx_http_groonga_handler_send_response(ngx_http_request_t *r, ngx_http_groonga_handler_data_t *data) { ngx_int_t rc; grn_ctx *context; const char *content_type; ngx_buf_t *head_buf, *body_buf, *foot_buf; ngx_chain_t head_chain, body_chain, foot_chain; ngx_chain_t *output_chain = NULL; context = &(data->context); /* set the 'Content-type' header */ if (r->headers_out.content_type.len == 0) { content_type = grn_ctx_get_mime_type(context); ngx_http_groonga_handler_set_content_type(r, content_type); } /* allocate buffers for a response body */ head_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->head)); if (!head_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } body_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->body)); if (!body_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } foot_buf = ngx_http_groonga_grn_obj_to_ngx_buf(r->pool, &(data->foot)); if (!foot_buf) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach buffers to the buffer chain */ head_chain.buf = head_buf; output_chain = ngx_http_groonga_attach_chain(output_chain, &head_chain); body_chain.buf = body_buf; output_chain = ngx_http_groonga_attach_chain(output_chain, &body_chain); foot_chain.buf = foot_buf; output_chain = ngx_http_groonga_attach_chain(output_chain, &foot_chain); /* set the status line */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = GRN_TEXT_LEN(&(data->head)) + GRN_TEXT_LEN(&(data->body)) + GRN_TEXT_LEN(&(data->foot)); /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ rc = ngx_http_output_filter(r, output_chain); return rc; }
static void ngx_http_groonga_context_receive_handler_raw(grn_ctx *context, int flags, ngx_http_groonga_handler_data_t *data) { char *chunk = NULL; unsigned int chunk_size = 0; int recv_flags; ngx_http_request_t *r; ngx_log_t *log; grn_bool is_last_chunk; grn_ctx_recv(context, &chunk, &chunk_size, &recv_flags); data->raw.processed = GRN_TRUE; if (data->raw.rc != NGX_OK) { return; } r = data->raw.r; log = r->connection->log; is_last_chunk = (flags & GRN_CTX_TAIL); if (!data->raw.header_sent) { ngx_http_groonga_handler_set_content_type(r, grn_ctx_get_mime_type(context)); r->headers_out.status = NGX_HTTP_OK; if (is_last_chunk) { r->headers_out.content_length_n = chunk_size; if (chunk_size == 0) { r->header_only = 1; } } else { r->headers_out.content_length_n = -1; } data->raw.rc = ngx_http_send_header(r); data->raw.header_sent = GRN_TRUE; if (data->raw.rc != NGX_OK) { return; } } if (chunk_size > 0 || is_last_chunk) { ngx_chain_t *chain; chain = ngx_chain_get_free_buf(r->pool, &(data->raw.free_chain)); if (!chain) { ngx_log_error(NGX_LOG_ERR, log, 0, "http_groonga: failed to allocate memory for chunked body"); data->raw.rc = NGX_ERROR; return; } if (chunk_size == 0) { chain->buf->pos = NULL; chain->buf->last = NULL; chain->buf->memory = 0; } else { chain->buf->pos = (u_char *)chunk; chain->buf->last = (u_char *)chunk + chunk_size; chain->buf->memory = 1; } chain->buf->tag = (ngx_buf_tag_t)&ngx_http_groonga_module; chain->buf->flush = 1; chain->buf->temporary = 0; chain->buf->in_file = 0; if (is_last_chunk) { chain->buf->last_buf = 1; } else { chain->buf->last_buf = 0; } chain->next = NULL; data->raw.rc = ngx_http_output_filter(r, chain); ngx_chain_update_chains(r->pool, &(data->raw.free_chain), &(data->raw.busy_chain), &chain, (ngx_buf_tag_t)&ngx_http_groonga_module); } }