コード例 #1
0
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;
}
コード例 #2
0
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;
}
コード例 #3
0
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;
}
コード例 #4
0
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;
}
コード例 #5
0
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);
  }
}