[Groonga-commit] groonga/groonga [master] return code and error info would be output in http mode.

Back to archive index

null+****@clear***** null+****@clear*****
2010年 6月 9日 (水) 22:38:10 JST


Daijiro MORI	2010-06-09 13:38:10 +0000 (Wed, 09 Jun 2010)

  New Revision: 107eb494f486d73903ead54c350dbf36b4547c2e

  Log:
    return code and error info would be output in http mode.

  Modified files:
    src/groonga.c

  Modified: src/groonga.c (+112 -90)
===================================================================
--- src/groonga.c    2010-06-09 04:41:37 +0000 (43ba045)
+++ src/groonga.c    2010-06-09 13:38:10 +0000 (3570da5)
@@ -358,53 +358,134 @@ parse_htpath(const char *p, const char *pe,
   (GRN_TEXT_LEN((obj)) == strlen((str)) && !memcmp(GRN_TEXT_VALUE((obj)), (str), strlen((str))))
 
 static void
-print_return_code_with_body(grn_ctx *ctx, grn_obj *buf, grn_content_type ct,
-                            grn_obj *body)
+print_return_code(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj *foot)
 {
-  switch (ct) {
+  switch (ctx->impl->output_type) {
   case GRN_CONTENT_JSON:
-    GRN_TEXT_PUTS(ctx, buf, "[[");
-    grn_text_itoa(ctx, buf, ctx->rc);
+    GRN_TEXT_PUTS(ctx, head, "[[");
+    grn_text_itoa(ctx, head, rc);
     {
       double dv;
       grn_timeval tv;
       grn_timeval_now(ctx, &tv);
       dv = ctx->impl->tv.tv_sec;
       dv += ctx->impl->tv.tv_usec / 1000000.0;
-      GRN_TEXT_PUTC(ctx, buf, ',');
-      grn_text_ftoa(ctx, buf, dv);
+      GRN_TEXT_PUTC(ctx, head, ',');
+      grn_text_ftoa(ctx, head, dv);
       dv = (tv.tv_sec - ctx->impl->tv.tv_sec);
       dv += (tv.tv_usec - ctx->impl->tv.tv_usec) / 1000000.0;
-      GRN_TEXT_PUTC(ctx, buf, ',');
-      grn_text_ftoa(ctx, buf, dv);
+      GRN_TEXT_PUTC(ctx, head, ',');
+      grn_text_ftoa(ctx, head, dv);
     }
-    if (ctx->rc != GRN_SUCCESS) {
-      GRN_TEXT_PUTS(ctx, buf, ",");
-      grn_text_esc(ctx, buf, ctx->errbuf, strlen(ctx->errbuf));
-    }
-    if (body && GRN_TEXT_LEN(body)) {
-      GRN_TEXT_PUTS(ctx, buf, "],");
-      GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(body), GRN_TEXT_LEN(body));
-      GRN_TEXT_PUTS(ctx, buf, "]");
-    } else {
-      GRN_TEXT_PUTS(ctx, buf, "]]");
+    if (rc != GRN_SUCCESS) {
+      GRN_TEXT_PUTC(ctx, head, ',');
+      grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf));
+      if (ctx->errfunc && ctx->errfile) {
+        /* TODO: output backtrace */
+        GRN_TEXT_PUTS(ctx, head, ",[[");
+        grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc));
+        GRN_TEXT_PUTC(ctx, head, ',');
+        grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile));
+        GRN_TEXT_PUTC(ctx, head, ',');
+        grn_text_itoa(ctx, head, ctx->errline);
+        GRN_TEXT_PUTS(ctx, head, "]]");
+      }
     }
+    GRN_TEXT_PUTC(ctx, head, ']');
+    if (GRN_TEXT_LEN(body)) { GRN_TEXT_PUTC(ctx, head, ','); }
+    GRN_TEXT_PUTC(ctx, foot, ']');
     break;
   case GRN_CONTENT_TSV:
   case GRN_CONTENT_XML:
-    if (body) {
-      GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(body), GRN_TEXT_LEN(body));
-    }
-    break;
   case GRN_CONTENT_NONE:
     break;
   }
 }
 
 static void
-print_return_code(grn_ctx *ctx, grn_obj *buf, grn_content_type ct)
+h_output(grn_ctx *ctx, grn_rc expr_rc, grn_sock fd,
+         grn_obj *jsonp_func, grn_obj *body, const char *mime_type)
 {
-  print_return_code_with_body(ctx, buf, ct, NULL);
+  grn_obj head, foot, *outbuf = ctx->impl->outbuf;
+  GRN_TEXT_INIT(&head, 0);
+  GRN_TEXT_INIT(&foot, 0);
+  if (!expr_rc) {
+    if (GRN_TEXT_LEN(jsonp_func)) {
+      GRN_TEXT_PUT(ctx, &head, GRN_TEXT_VALUE(jsonp_func), GRN_TEXT_LEN(jsonp_func));
+      GRN_TEXT_PUTC(ctx, &head, '(');
+      print_return_code(ctx, expr_rc, &head, outbuf, &foot);
+      GRN_TEXT_PUTS(ctx, &foot, ");");
+    } else {
+      print_return_code(ctx, expr_rc, &head, outbuf, &foot);
+    }
+    GRN_TEXT_SETS(ctx, body, "HTTP/1.1 200 OK\r\n");
+    GRN_TEXT_PUTS(ctx, body, "Connection: close\r\n");
+    GRN_TEXT_PUTS(ctx, body, "Content-Type: ");
+    GRN_TEXT_PUTS(ctx, body, mime_type);
+    GRN_TEXT_PUTS(ctx, body, "\r\nContent-Length: ");
+    grn_text_lltoa(ctx, body,
+                   GRN_TEXT_LEN(&head) + GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot));
+    GRN_TEXT_PUTS(ctx, body, "\r\n\r\n");
+  } else {
+    GRN_BULK_REWIND(outbuf);
+    print_return_code(ctx, expr_rc, &head, outbuf, &foot);
+    if (expr_rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) {
+      GRN_TEXT_SETS(ctx, body, "HTTP/1.1 404 Not Found\r\n");
+    } else {
+      GRN_TEXT_SETS(ctx, body, "HTTP/1.1 500 Internal Server Error\r\n");
+    }
+    GRN_TEXT_PUTS(ctx, body, "Content-Type: application/json\r\n\r\n");
+  }
+  {
+    ssize_t ret;
+#ifdef WIN32
+    WSABUF wsabufs[4];
+    wsabufs[0].buf = GRN_TEXT_VALUE(body);
+    wsabufs[0].len = GRN_TEXT_LEN(body);
+    wsabufs[1].buf = GRN_TEXT_VALUE(&head);
+    wsabufs[1].len = GRN_TEXT_LEN(&head);
+    wsabufs[2].buf = GRN_TEXT_VALUE(outbuf);
+    wsabufs[2].len = GRN_TEXT_LEN(outbuf);
+    wsabufs[3].buf = GRN_TEXT_VALUE(&foot);
+    wsabufs[4].len = GRN_TEXT_LEN(&foot);
+    if (WSASend(fd, wsabufs, 4, &ret, 0, NULL, NULL) == SOCKET_ERROR) {
+      SERR("WSASend");
+    }
+#else /* WIN32 */
+    struct iovec msg_iov[4];
+    struct msghdr msg;
+    msg.msg_name = NULL;
+    msg.msg_namelen = 0;
+    msg.msg_iov = msg_iov;
+    msg.msg_iovlen = 4;
+    msg.msg_control = NULL;
+    msg.msg_controllen = 0;
+    msg.msg_flags = 0;
+    msg_iov[0].iov_base = GRN_TEXT_VALUE(body);
+    msg_iov[0].iov_len = GRN_TEXT_LEN(body);
+    msg_iov[1].iov_base = GRN_TEXT_VALUE(&head);
+    msg_iov[1].iov_len = GRN_TEXT_LEN(&head);
+    msg_iov[2].iov_base = GRN_TEXT_VALUE(outbuf);
+    msg_iov[2].iov_len = GRN_TEXT_LEN(outbuf);
+    msg_iov[3].iov_base = GRN_TEXT_VALUE(&foot);
+    msg_iov[3].iov_len = GRN_TEXT_LEN(&foot);
+    if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) {
+      SERR("sendmsg");
+    }
+#endif /* WIN32 */
+  }
+  GRN_BULK_REWIND(body);
+  GRN_BULK_REWIND(outbuf);
+  GRN_OBJ_FIN(ctx, &foot);
+  GRN_OBJ_FIN(ctx, &head);
+  {
+    uint64_t et;
+    grn_timeval tv;
+    grn_timeval_now(ctx, &tv);
+    et = (tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_USEC_PER_SEC
+      + (tv.tv_usec - ctx->impl->tv.tv_usec);
+    GRN_LOG(ctx, GRN_LOG_NONE, "%08x|<%012zu rc=%d", (intptr_t)ctx, et, ctx->rc);
+  }
 }
 
 static void
@@ -442,12 +523,10 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body)
     }
     /* TODO: handle post body */
     {
+      const char *mime_type = NULL;
       grn_rc expr_rc = GRN_SUCCESS;
       grn_obj jsonp_func;
-      const char *mime_type;
-
       GRN_TEXT_INIT(&jsonp_func, 0);
-
       if (*path != '/') {
         expr_rc = GRN_INVALID_ARGUMENT;
       } else {
@@ -466,7 +545,8 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body)
                      &key_end, &filename_end, &ot, &mime_type);
         if ((GRN_TEXT_LEN(&key) >= 2 &&
              GRN_TEXT_VALUE(&key)[0] == 'd' && GRN_TEXT_VALUE(&key)[1] == '/') &&
-            (expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&key) + 2, key_end - GRN_TEXT_VALUE(&key) - 2))) {
+            (expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&key) + 2,
+                                key_end - GRN_TEXT_VALUE(&key) - 2))) {
           while (g < pathe) {
             GRN_BULK_REWIND(&key);
             g = grn_text_cgidec(ctx, &key, g, pathe, '=');
@@ -487,6 +567,7 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body)
             grn_obj_reinit(ctx, val, GRN_DB_INT32, 0);
             GRN_INT32_SET(ctx, val, (int32_t)ot);
           }
+          ctx->impl->output_type = ot;
           grn_ctx_push(ctx, ctx->impl->outbuf);
           expr_rc = grn_expr_exec(ctx, expr, 1);
           val = grn_ctx_pop(ctx);
@@ -498,6 +579,7 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body)
             GRN_TEXT_SET(ctx, val,
                          GRN_TEXT_VALUE(&key), filename_end - GRN_TEXT_VALUE(&key));
           }
+          ctx->impl->output_type = ot;
           grn_ctx_push(ctx, ctx->impl->outbuf);
           expr_rc = grn_expr_exec(ctx, expr, 1);
           val = grn_ctx_pop(ctx);
@@ -505,68 +587,8 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body)
         }
         GRN_OBJ_FIN(ctx, &key);
       }
-      /* TODO: Content-Length */
-      if (!expr_rc) {
-        GRN_TEXT_SETS(ctx, body, "HTTP/1.1 200 OK\r\n");
-        GRN_TEXT_PUTS(ctx, body, "Connection: close\r\n");
-        GRN_TEXT_PUTS(ctx, body, "Content-Type: ");
-        GRN_TEXT_PUTS(ctx, body, mime_type);
-        GRN_TEXT_PUTS(ctx, body, "\r\nContent-Length: ");
-        if (GRN_TEXT_LEN(&jsonp_func)) {
-          grn_text_lltoa(ctx, body,
-                         GRN_TEXT_LEN(ctx->impl->outbuf) + GRN_TEXT_LEN(&jsonp_func) + 3);
-          GRN_TEXT_PUTS(ctx, body, "\r\n\r\n");
-          GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(&jsonp_func), GRN_TEXT_LEN(&jsonp_func));
-          GRN_TEXT_PUTC(ctx, body, '(');
-          GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(ctx->impl->outbuf),
-                       GRN_TEXT_LEN(ctx->impl->outbuf));
-          GRN_TEXT_PUTS(ctx, body, ");");
-        } else {
-          grn_text_lltoa(ctx, body, GRN_TEXT_LEN(ctx->impl->outbuf));
-          GRN_TEXT_PUTS(ctx, body, "\r\n\r\n");
-          GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(ctx->impl->outbuf),
-                       GRN_TEXT_LEN(ctx->impl->outbuf));
-        }
-      } else {
-        if (expr_rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) {
-          GRN_TEXT_SETS(ctx, body, "HTTP/1.1 404 Not Found\r\n");
-        } else {
-          GRN_TEXT_SETS(ctx, body, "HTTP/1.1 500 Internal Server Error\r\n");
-        }
-        GRN_TEXT_PUTS(ctx, body, "Content-Type: application/json\r\n\r\n");
-        GRN_TEXT_PUTS(ctx, body, "[[");
-        grn_text_itoa(ctx, body, expr_rc);
-        GRN_TEXT_PUTS(ctx, body, ",0,0");
-        if (ctx->errbuf && strlen(ctx->errbuf)) {
-          GRN_TEXT_PUTC(ctx, body, ',');
-          grn_text_esc(ctx, body, ctx->errbuf, strlen(ctx->errbuf));
-          if (ctx->errfunc && ctx->errfile) {
-            /* TODO: output backtrace */
-            GRN_TEXT_PUTS(ctx, body, ",[[");
-            grn_text_esc(ctx, body, ctx->errfunc, strlen(ctx->errfile));
-            GRN_TEXT_PUTC(ctx, body, ',');
-            grn_text_esc(ctx, body, ctx->errfile, strlen(ctx->errfile));
-            GRN_TEXT_PUTC(ctx, body, ',');
-            grn_text_itoa(ctx, body, ctx->errline);
-            GRN_TEXT_PUTS(ctx, body, "]]");
-          }
-        }
-        GRN_TEXT_PUTS(ctx, body, "]]");
-      }
+      h_output(ctx, expr_rc, fd, &jsonp_func, body, mime_type);
       GRN_OBJ_FIN(ctx, &jsonp_func);
-      if (send(fd, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body), MSG_NOSIGNAL) == -1) {
-        SERR("send");
-      }
-      GRN_BULK_REWIND(body);
-      GRN_BULK_REWIND(ctx->impl->outbuf);
-      {
-        uint64_t et;
-        grn_timeval tv;
-        grn_timeval_now(ctx, &tv);
-        et = (tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_USEC_PER_SEC
-          + (tv.tv_usec - ctx->impl->tv.tv_usec);
-        GRN_LOG(ctx, GRN_LOG_NONE, "%08x|<%012zu rc=%d", (intptr_t)ctx, et, ctx->rc);
-      }
     }
   }
 exit :




Groonga-commit メーリングリストの案内
Back to archive index