[Groonga-commit] groonga/groonga [master] groonga-httpd: support load by POST

アーカイブの一覧に戻る

Kouhei Sutou null+****@clear*****
Thu Sep 6 18:43:33 JST 2012


Kouhei Sutou	2012-09-06 18:43:33 +0900 (Thu, 06 Sep 2012)

  New Revision: 658b92e93d16a9ba6e5e09714ec4466b9f2fd0e8
  https://github.com/groonga/groonga/commit/658b92e93d16a9ba6e5e09714ec4466b9f2fd0e8

  Log:
    groonga-httpd: support load by POST

  Modified files:
    src/nginx-module/ngx_http_groonga_module.c

  Modified: src/nginx-module/ngx_http_groonga_module.c (+147 -5)
===================================================================
--- src/nginx-module/ngx_http_groonga_module.c    2012-09-06 17:35:01 +0900 (6d96e62)
+++ src/nginx-module/ngx_http_groonga_module.c    2012-09-06 18:43:33 +0900 (cfb8dff)
@@ -73,6 +73,16 @@ ngx_str_null_terminate(ngx_pool_t *pool, const ngx_str_t *string)
   return null_terminated_c_string;
 }
 
+static grn_bool
+ngx_str_equal_c_string(ngx_str_t *string, const char *c_string)
+{
+  if (string->len != strlen(c_string)) {
+    return GRN_FALSE;
+  }
+
+  return memcmp(c_string, string->data, string->len) == 0;
+}
+
 static void
 ngx_http_groonga_context_log_error(ngx_log_t *log, grn_ctx *context)
 {
@@ -90,7 +100,7 @@ ngx_http_groonga_context_check_error(ngx_log_t *log, grn_ctx *context)
     return NGX_OK;
   } else {
     ngx_http_groonga_context_log_error(log, context);
-    return NGX_HTTP_INTERNAL_SERVER_ERROR;
+    return NGX_HTTP_BAD_REQUEST;
   }
 }
 
@@ -226,6 +236,15 @@ ngx_http_groonga_extract_command_path(ngx_http_request_t *r,
   return NGX_OK;
 }
 
+static void
+ngx_http_groonga_handler_set_content_type(ngx_http_request_t *r,
+                                          const char *content_type)
+{
+  r->headers_out.content_type.len = strlen(content_type);
+  r->headers_out.content_type.data = (u_char *)content_type;
+  r->headers_out.content_type_len = r->headers_out.content_type.len;
+}
+
 static ngx_int_t
 ngx_http_groonga_handler_create_data(ngx_http_request_t *r,
                                      ngx_http_groonga_handler_data_t **data_return)
@@ -284,6 +303,104 @@ ngx_http_groonga_handler_process_command_path(ngx_http_request_t *r,
   return NGX_OK;
 }
 
+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_process_load(ngx_http_request_t *r,
+                                      ngx_str_t *command_path,
+                                      ngx_http_groonga_handler_data_t *data)
+{
+  ngx_int_t rc;
+
+  rc = ngx_http_groonga_handler_validate_post_command(r, command_path, data);
+  if (rc != NGX_OK) {
+    return rc;
+  }
+
+  rc = ngx_http_groonga_handler_process_command_path(r, command_path, data);
+  if (rc != NGX_OK) {
+    return rc;
+  }
+
+  rc = ngx_http_groonga_handler_process_body(r, data);
+  if (rc != NGX_OK) {
+    return rc;
+  }
+
+  return NGX_OK;
+}
+
 static ngx_chain_t *
 ngx_http_groonga_attach_chain(ngx_chain_t *chain, ngx_chain_t *new_chain)
 {
@@ -322,10 +439,10 @@ ngx_http_groonga_handler_send_response(ngx_http_request_t *r,
   context = &(data->context);
 
   /* set the 'Content-type' header */
-  content_type = grn_ctx_get_mime_type(context);
-  r->headers_out.content_type.len = strlen(content_type);
-  r->headers_out.content_type.data = (u_char *)content_type;
-  r->headers_out.content_type_len = r->headers_out.content_type.len;
+  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));
@@ -403,6 +520,25 @@ ngx_http_groonga_handler_get(ngx_http_request_t *r)
   return rc;
 }
 
+static void
+ngx_http_groonga_handler_post(ngx_http_request_t *r)
+{
+  ngx_int_t rc;
+  ngx_str_t command_path;
+  ngx_http_groonga_handler_data_t *data;
+
+  rc = ngx_http_groonga_extract_command_path(r, &command_path);
+  if (rc == NGX_OK) {
+    rc = ngx_http_groonga_handler_create_data(r, &data);
+  }
+  if (rc == NGX_OK) {
+    rc = ngx_http_groonga_handler_process_load(r, &command_path, data);
+  }
+
+  ngx_http_groonga_handler_send_response(r, data);
+  ngx_http_finalize_request(r, rc);
+}
+
 static ngx_int_t
 ngx_http_groonga_handler(ngx_http_request_t *r)
 {
@@ -413,6 +549,12 @@ ngx_http_groonga_handler(ngx_http_request_t *r)
   case NGX_HTTP_HEAD:
     rc = ngx_http_groonga_handler_get(r);
     break;
+  case NGX_HTTP_POST:
+    rc = ngx_http_read_client_request_body(r, ngx_http_groonga_handler_post);
+    if (rc < NGX_HTTP_SPECIAL_RESPONSE) {
+      rc = NGX_DONE;
+    }
+    break;
   default:
     rc = NGX_HTTP_NOT_ALLOWED;
     break;
-------------- next part --------------
HTML����������������������������...
ダウンロード 



More information about the Groonga-commit mailing list
アーカイブの一覧に戻る