7a8,9 > #include > #include 8a11 > 38,39c41 < static nxt_int_t nxt_ruby_run(nxt_task_t *task, nxt_app_rmsg_t *rmsg, < nxt_app_wmsg_t *wmsg); --- > static void nxt_ruby_request_handler(nxt_unit_request_info_t *req); 42,45c44,48 < static nxt_int_t nxt_ruby_read_request(nxt_ruby_run_ctx_t *run_ctx, < VALUE hash_env); < nxt_inline nxt_int_t nxt_ruby_read_add_env(nxt_task_t *task, < nxt_app_rmsg_t *rmsg, VALUE hash_env, const char *name, nxt_str_t *str); --- > static int nxt_ruby_read_request(VALUE hash_env); > nxt_inline void nxt_ruby_add_sptr(VALUE hash_env, > const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len); > nxt_inline void nxt_ruby_add_str(VALUE hash_env, > const char *name, uint32_t name_len, char *str, uint32_t len); 47,54c50,54 < nxt_inline nxt_int_t nxt_ruby_write(nxt_task_t *task, nxt_app_wmsg_t *wmsg, < const u_char *data, size_t len, nxt_bool_t flush, nxt_bool_t last); < static nxt_int_t nxt_ruby_rack_result_headers(VALUE result); < static int nxt_ruby_hash_foreach(VALUE r_key, VALUE r_value, VALUE arg); < static nxt_int_t nxt_ruby_head_send_part(const char *key, size_t key_size, < const char *value, size_t value_size); < static nxt_int_t nxt_ruby_rack_result_body(VALUE result); < static nxt_int_t nxt_ruby_rack_result_body_file_write(VALUE filepath); --- > static int nxt_ruby_rack_result_headers(VALUE result, nxt_int_t status); > static int nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg); > static int nxt_ruby_hash_add(VALUE r_key, VALUE r_value, VALUE arg); > static int nxt_ruby_rack_result_body(VALUE result); > static int nxt_ruby_rack_result_body_file_write(VALUE filepath); 60c60 < static void nxt_ruby_atexit(nxt_task_t *task); --- > static void nxt_ruby_atexit(void); 74c74 < NXT_EXPORT nxt_application_module_t nxt_app_module = { --- > NXT_EXPORT nxt_app_module_t nxt_app_module = { 80,81d79 < nxt_ruby_run, < nxt_ruby_atexit, 88c86 < int state; --- > int state, rc; 89a88,89 > nxt_unit_ctx_t *unit_ctx; > nxt_unit_init_t ruby_unit_init; 130a131,151 > nxt_unit_default_init(task, &ruby_unit_init); > > ruby_unit_init.callbacks.request_handler = nxt_ruby_request_handler; > > unit_ctx = nxt_unit_init(&ruby_unit_init); > if (nxt_slow_path(unit_ctx == NULL)) { > return NXT_ERROR; > } > > nxt_ruby_run_ctx.unit_ctx = unit_ctx; > > rc = nxt_unit_run(unit_ctx); > > nxt_ruby_atexit(); > > nxt_ruby_run_ctx.unit_ctx = NULL; > > nxt_unit_done(unit_ctx); > > exit(rc); > 322,323c343,344 < static nxt_int_t < nxt_ruby_run(nxt_task_t *task, nxt_app_rmsg_t *rmsg, nxt_app_wmsg_t *wmsg) --- > static void > nxt_ruby_request_handler(nxt_unit_request_info_t *req) 328,330c349 < nxt_ruby_run_ctx.task = task; < nxt_ruby_run_ctx.rmsg = rmsg; < nxt_ruby_run_ctx.wmsg = wmsg; --- > nxt_ruby_run_ctx.req = req; 333,334c352,353 < if (nxt_slow_path(state != 0)) { < nxt_ruby_exception_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, --- > if (nxt_slow_path(res == Qnil || state != 0)) { > nxt_ruby_exception_log(NULL, NXT_LOG_ERR, 336d354 < return NXT_ERROR; 338,343d355 < < if (nxt_slow_path(res == Qnil)) { < return NXT_ERROR; < } < < return NXT_OK; 349a362 > int rc; 351c364 < nxt_int_t rc; --- > nxt_int_t status; 355,358c368,371 < rc = nxt_ruby_read_request(&nxt_ruby_run_ctx, env); < if (nxt_slow_path(rc != NXT_OK)) { < nxt_alert(nxt_ruby_run_ctx.task, < "Ruby: Failed to process incoming request"); --- > rc = nxt_ruby_read_request(env); > if (nxt_slow_path(rc != NXT_UNIT_OK)) { > nxt_unit_req_alert(nxt_ruby_run_ctx.req, > "Ruby: Failed to process incoming request"); 365,366c378,379 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Invalid response format from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Invalid response format from application"); 372,374c385,387 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Invalid response format from application. " < "Need 3 entries [Status, Headers, Body]"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Invalid response format from application. " > "Need 3 entries [Status, Headers, Body]"); 379,380c392,396 < rc = nxt_ruby_rack_result_status(result); < if (nxt_slow_path(rc != NXT_OK)) { --- > status = nxt_ruby_rack_result_status(result); > if (nxt_slow_path(status < 0)) { > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Invalid response status from application."); > 384,385c400,401 < rc = nxt_ruby_rack_result_headers(result); < if (nxt_slow_path(rc != NXT_OK)) { --- > rc = nxt_ruby_rack_result_headers(result, status); > if (nxt_slow_path(rc != NXT_UNIT_OK)) { 390c406 < if (nxt_slow_path(rc != NXT_OK)) { --- > if (nxt_slow_path(rc != NXT_UNIT_OK)) { 394,397c410,411 < rc = nxt_app_msg_flush(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, 1); < if (nxt_slow_path(rc != NXT_OK)) { < goto fail; < } --- > nxt_unit_request_done(nxt_ruby_run_ctx.req, rc); > nxt_ruby_run_ctx.req = NULL; 404a419,421 > nxt_unit_request_done(nxt_ruby_run_ctx.req, NXT_UNIT_ERROR); > nxt_ruby_run_ctx.req = NULL; > 411,412c428,429 < static nxt_int_t < nxt_ruby_read_request(nxt_ruby_run_ctx_t *run_ctx, VALUE hash_env) --- > static int > nxt_ruby_read_request(VALUE hash_env) 414,420c431,434 < u_char *colon; < size_t query_size; < nxt_int_t rc; < nxt_str_t str, value, path, target; < nxt_str_t host, server_name, server_port; < nxt_task_t *task; < nxt_app_rmsg_t *rmsg; --- > char *host_start, *port_start; > uint32_t i, host_length, port_length; > nxt_unit_field_t *f; > nxt_unit_request_t *r; 422,423c436 < static nxt_str_t def_host = nxt_string("localhost"); < static nxt_str_t def_port = nxt_string("80"); --- > r = nxt_ruby_run_ctx.req->request; 425,426c438 < task = run_ctx->task; < rmsg = run_ctx->rmsg; --- > #define NL(S) (S), sizeof(S)-1 428,430c440,447 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "REQUEST_METHOD", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > nxt_ruby_add_sptr(hash_env, NL("REQUEST_METHOD"), &r->method, > r->method_length); > nxt_ruby_add_sptr(hash_env, NL("REQUEST_URI"), &r->target, > r->target_length); > nxt_ruby_add_sptr(hash_env, NL("PATH_INFO"), &r->path, r->path_length); > if (r->query.offset) { > nxt_ruby_add_sptr(hash_env, NL("QUERY_STRING"), &r->query, > r->query_length); 431a449,453 > nxt_ruby_add_sptr(hash_env, NL("SERVER_PROTOCOL"), &r->version, > r->version_length); > nxt_ruby_add_sptr(hash_env, NL("REMOTE_ADDR"), &r->remote, > r->remote_length); > nxt_ruby_add_sptr(hash_env, NL("SERVER_ADDR"), &r->local, r->local_length); 433,436c455,456 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "REQUEST_URI", &target); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > for (i = 0; i < r->fields_count; i++) { > f = r->fields + i; 438,440c458,459 < rc = nxt_app_msg_read_str(task, rmsg, &path); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > nxt_ruby_add_sptr(hash_env, nxt_unit_sptr_get(&f->name), f->name_length, > &f->value, f->value_length); 443,446c462,463 < rc = nxt_app_msg_read_size(task, rmsg, &query_size); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > if (r->content_length_field != NXT_UNIT_NONE_FIELD) { > f = r->fields + r->content_length_field; 448,449c465,466 < if (path.start == NULL || path.length == 0) { < path = target; --- > nxt_ruby_add_sptr(hash_env, NL("CONTENT_LENGTH"), > &f->value, f->value_length); 452,453c469,470 < rb_hash_aset(hash_env, rb_str_new2("PATH_INFO"), < rb_str_new((const char *) path.start, (long) path.length)); --- > if (r->content_type_field != NXT_UNIT_NONE_FIELD) { > f = r->fields + r->content_type_field; 455,466c472,473 < if (query_size > 0) { < query_size--; < < if (nxt_slow_path(target.length < query_size)) { < return NXT_ERROR; < } < < str.start = &target.start[query_size]; < str.length = target.length - query_size; < < rb_hash_aset(hash_env, rb_str_new2("QUERY_STRING"), < rb_str_new((const char *) str.start, (long) str.length)); --- > nxt_ruby_add_sptr(hash_env, NL("CONTENT_TYPE"), > &f->value, f->value_length); 469,472c476,477 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "SERVER_PROTOCOL", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > if (r->host_field != NXT_UNIT_NONE_FIELD) { > f = r->fields + r->host_field; 474,477c479,480 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "REMOTE_ADDR", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > host_start = nxt_unit_sptr_get(&f->value); > host_length = f->value_length; 479,501d481 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "SERVER_ADDR", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < rc = nxt_app_msg_read_str(task, rmsg, &host); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < if (host.length == 0) { < host = def_host; < } < < colon = nxt_memchr(host.start, ':', host.length); < server_name = host; < < if (colon != NULL) { < server_name.length = colon - host.start; < < server_port.start = colon + 1; < server_port.length = host.length - server_name.length - 1; < 503c483,484 < server_port = def_port; --- > host_start = NULL; > host_length = 0; 506,508c487,488 < rb_hash_aset(hash_env, rb_str_new2("SERVER_NAME"), < rb_str_new((const char *) server_name.start, < (long) server_name.length)); --- > nxt_unit_split_host(host_start, host_length, &host_start, &host_length, > &port_start, &port_length); 510,512c490,491 < rb_hash_aset(hash_env, rb_str_new2("SERVER_PORT"), < rb_str_new((const char *) server_port.start, < (long) server_port.length)); --- > nxt_ruby_add_str(hash_env, NL("SERVER_NAME"), host_start, host_length); > nxt_ruby_add_str(hash_env, NL("SERVER_PORT"), port_start, port_length); 514,517c493 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "CONTENT_TYPE", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > #undef NL 519,550c495 < rc = nxt_ruby_read_add_env(task, rmsg, hash_env, "CONTENT_LENGTH", &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < for ( ;; ) { < rc = nxt_app_msg_read_str(task, rmsg, &str); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < if (nxt_slow_path(str.length == 0)) { < break; < } < < rc = nxt_app_msg_read_str(task, rmsg, &value); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < rb_hash_aset(hash_env, < rb_str_new((char *) str.start, (long) str.length), < rb_str_new((const char *) value.start, < (long) value.length)); < } < < rc = nxt_app_msg_read_size(task, rmsg, &run_ctx->body_preread_size); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < return NXT_OK; --- > return NXT_UNIT_OK; 554,556c499,501 < nxt_inline nxt_int_t < nxt_ruby_read_add_env(nxt_task_t *task, nxt_app_rmsg_t *rmsg, VALUE hash_env, < const char *name, nxt_str_t *str) --- > nxt_inline void > nxt_ruby_add_sptr(VALUE hash_env, > const char *name, uint32_t name_len, nxt_unit_sptr_t *sptr, uint32_t len) 558c503 < nxt_int_t rc; --- > char *str; 560,563c505 < rc = nxt_app_msg_read_str(task, rmsg, str); < if (nxt_slow_path(rc != NXT_OK)) { < return rc; < } --- > str = nxt_unit_sptr_get(sptr); 565,568c507,508 < if (str->start == NULL) { < rb_hash_aset(hash_env, rb_str_new2(name), Qnil); < return NXT_OK; < } --- > rb_hash_aset(hash_env, rb_str_new(name, name_len), rb_str_new(str, len)); > } 570,571d509 < rb_hash_aset(hash_env, rb_str_new2(name), < rb_str_new((const char *) str->start, (long) str->length)); 573c511,515 < return NXT_OK; --- > nxt_inline void > nxt_ruby_add_str(VALUE hash_env, > const char *name, uint32_t name_len, char *str, uint32_t len) > { > rb_hash_aset(hash_env, rb_str_new(name, name_len), rb_str_new(str, len)); 580,584c522 < VALUE status; < u_char *p; < size_t len; < nxt_int_t rc; < u_char buf[3]; --- > VALUE status; 589,602c527 < nxt_sprintf(buf, buf + 3, "%03d", FIX2INT(status)); < < p = buf; < len = 3; < < } else if (TYPE(status) == T_STRING) { < p = (u_char *) RSTRING_PTR(status); < len = RSTRING_LEN(status); < < } else { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Invalid response 'status' format from application"); < < return NXT_ERROR; --- > return FIX2INT(status); 605,608c530,532 < rc = nxt_ruby_write(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) "Status: ", nxt_length("Status: "), 0, 0); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > if (TYPE(status) == T_STRING) { > return nxt_int_parse((u_char *) RSTRING_PTR(status), > RSTRING_LEN(status)); 611,615c535,536 < rc = nxt_ruby_write(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < p, len, 0, 0); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, "Ruby: Invalid response 'status' " > "format from application"); 617,623c538 < rc = nxt_ruby_write(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) "\r\n", nxt_length("\r\n"), 0, 0); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; < } < < return NXT_OK; --- > return -2; 627,631c542,546 < nxt_inline nxt_int_t < nxt_ruby_write(nxt_task_t *task, nxt_app_wmsg_t *wmsg, < const u_char *data, size_t len, nxt_bool_t flush, nxt_bool_t last) < { < nxt_int_t rc; --- > typedef struct { > int rc; > uint32_t fields; > uint32_t size; > } nxt_ruby_headers_info_t; 633,636d547 < rc = nxt_app_msg_write_raw(task, wmsg, data, len); < if (nxt_slow_path(rc != NXT_OK)) { < return rc; < } 638,647c549,550 < if (flush || last) { < rc = nxt_app_msg_flush(task, wmsg, last); < } < < return rc; < } < < < static nxt_int_t < nxt_ruby_rack_result_headers(VALUE result) --- > static int > nxt_ruby_rack_result_headers(VALUE result, nxt_int_t status) 649,650c552,554 < VALUE headers; < nxt_int_t rc; --- > int rc; > VALUE headers; > nxt_ruby_headers_info_t headers_info; 654,655c558,560 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Invalid response 'headers' format from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Invalid response 'headers' format from " > "application"); 657c562 < return NXT_ERROR; --- > return NXT_UNIT_ERROR; 660c565 < rc = NXT_OK; --- > rc = NXT_UNIT_OK; 662,664c567,574 < rb_hash_foreach(headers, nxt_ruby_hash_foreach, (VALUE) (uintptr_t) &rc); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > headers_info.rc = NXT_UNIT_OK; > headers_info.fields = 0; > headers_info.size = 0; > > rb_hash_foreach(headers, nxt_ruby_hash_info, > (VALUE) (uintptr_t) &headers_info); > if (nxt_slow_path(headers_info.rc != NXT_UNIT_OK)) { > return headers_info.rc; 667,670c577,580 < rc = nxt_ruby_write(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) "\r\n", nxt_length("\r\n"), 0, 0); < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > rc = nxt_unit_response_init(nxt_ruby_run_ctx.req, status, > headers_info.fields, headers_info.size); > if (nxt_slow_path(rc != NXT_UNIT_OK)) { > return rc; 673c583,585 < return NXT_OK; --- > rb_hash_foreach(headers, nxt_ruby_hash_add, (VALUE) (uintptr_t) &rc); > > return rc; 678c590 < nxt_ruby_hash_foreach(VALUE r_key, VALUE r_value, VALUE arg) --- > nxt_ruby_hash_info(VALUE r_key, VALUE r_value, VALUE arg) 680,681c592,593 < nxt_int_t rc, *rc_p; < const char *value, *value_end, *pos; --- > const char *value, *value_end, *pos; > nxt_ruby_headers_info_t *headers_info; 683c595 < rc_p = (nxt_int_t *) (uintptr_t) arg; --- > headers_info = (void *) (uintptr_t) arg; 686,687c598,599 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Wrong header entry 'key' from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Wrong header entry 'key' from application"); 693,694c605,606 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Wrong header entry 'value' from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Wrong header entry 'value' from application"); 711,715c623,624 < rc = nxt_ruby_head_send_part(RSTRING_PTR(r_key), RSTRING_LEN(r_key), < value, pos - value); < if (nxt_slow_path(rc != NXT_OK)) { < goto fail; < } --- > headers_info->fields++; > headers_info->size += RSTRING_LEN(r_key) + (pos - value); 722,726c631,632 < rc = nxt_ruby_head_send_part(RSTRING_PTR(r_key), RSTRING_LEN(r_key), < value, value_end - value); < if (nxt_slow_path(rc != NXT_OK)) { < goto fail; < } --- > headers_info->fields++; > headers_info->size += RSTRING_LEN(r_key) + (value_end - value); 729,730d634 < *rc_p = NXT_OK; < 735c639 < *rc_p = NXT_ERROR; --- > headers_info->rc = NXT_UNIT_ERROR; 741,743c645,646 < static nxt_int_t < nxt_ruby_head_send_part(const char *key, size_t key_size, < const char *value, size_t value_size) --- > static int > nxt_ruby_hash_add(VALUE r_key, VALUE r_value, VALUE arg) 745c648,650 < nxt_int_t rc; --- > int *rc; > uint32_t key_len; > const char *value, *value_end, *pos; 747,751c652 < rc = nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) key, key_size); < if (nxt_slow_path(rc != NXT_OK)) { < return rc; < } --- > rc = (int *) (uintptr_t) arg; 753,756c654,676 < rc = nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) ": ", nxt_length(": ")); < if (nxt_slow_path(rc != NXT_OK)) { < return rc; --- > value = RSTRING_PTR(r_value); > value_end = value + RSTRING_LEN(r_value); > > key_len = RSTRING_LEN(r_key); > > pos = value; > > for ( ;; ) { > pos = strchr(pos, '\n'); > > if (pos == NULL) { > break; > } > > *rc = nxt_unit_response_add_field(nxt_ruby_run_ctx.req, > RSTRING_PTR(r_key), key_len, > value, pos - value); > if (nxt_slow_path(*rc != NXT_UNIT_OK)) { > goto fail; > } > > pos++; > value = pos; 759,762c679,685 < rc = nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) value, value_size); < if (nxt_slow_path(rc != NXT_OK)) { < return rc; --- > if (value <= value_end) { > *rc = nxt_unit_response_add_field(nxt_ruby_run_ctx.req, > RSTRING_PTR(r_key), key_len, > value, value_end - value); > if (nxt_slow_path(*rc != NXT_UNIT_OK)) { > goto fail; > } 765,766c688,694 < return nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) "\r\n", nxt_length("\r\n")); --- > return ST_CONTINUE; > > fail: > > *rc = NXT_UNIT_ERROR; > > return ST_STOP; 770c698 < static nxt_int_t --- > static int 773,774c701,702 < VALUE fn, body; < nxt_int_t rc; --- > int rc; > VALUE fn, body; 782,783c710,712 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to get 'body' file path from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Failed to get 'body' file path from " > "application"); 785c714 < return NXT_ERROR; --- > return NXT_UNIT_ERROR; 789,790c718,719 < if (nxt_slow_path(rc != NXT_OK)) { < return NXT_ERROR; --- > if (nxt_slow_path(rc != NXT_UNIT_OK)) { > return rc; 797,798c726,728 < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Invalid response 'body' format from application"); --- > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Invalid response 'body' format " > "from application"); 800c730 < return NXT_ERROR; --- > return NXT_UNIT_ERROR; 807c737 < return NXT_OK; --- > return NXT_UNIT_OK; 811,812c741,749 < static nxt_int_t < nxt_ruby_rack_result_body_file_write(VALUE filepath) --- > typedef struct { > int fd; > off_t pos; > off_t rest; > } nxt_ruby_rack_file_t; > > > static ssize_t > nxt_ruby_rack_file_read(nxt_unit_read_info_t *read_info, void *dst, size_t size) 814,820c751,752 < size_t len; < ssize_t n; < nxt_off_t rest; < nxt_int_t rc; < nxt_file_t file; < nxt_file_info_t finfo; < u_char buf[8192]; --- > ssize_t res; > nxt_ruby_rack_file_t *file; 822c754 < nxt_memzero(&file, sizeof(nxt_file_t)); --- > file = read_info->data; 824c756 < file.name = (nxt_file_name_t *) RSTRING_PTR(filepath); --- > size = nxt_min(size, (size_t) file->rest); 826,831c758 < rc = nxt_file_open(nxt_ruby_run_ctx.task, &file, NXT_FILE_RDONLY, < NXT_FILE_OPEN, 0); < if (nxt_slow_path(rc != NXT_OK)) { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to open 'body' file: %s", < (const char *) file.name); --- > res = pread(file->fd, dst, size, file->pos); 833c760,766 < return NXT_ERROR; --- > if (res >= 0) { > file->pos += res; > file->rest -= res; > > if (size > (size_t) res) { > file->rest = 0; > } 836,840c769 < rc = nxt_file_info(&file, &finfo); < if (nxt_slow_path(rc != NXT_OK)) { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to get 'body' file information: %s", < (const char *) file.name); --- > read_info->eof = file->rest == 0; 842,843c771,772 < goto fail; < } --- > return res; > } 845d773 < rest = nxt_file_size(&finfo); 847,848c775,781 < while (rest != 0) { < len = nxt_min(rest, (nxt_off_t) sizeof(buf)); --- > static int > nxt_ruby_rack_result_body_file_write(VALUE filepath) > { > int fd, rc; > struct stat finfo; > nxt_ruby_rack_file_t ruby_file; > nxt_unit_read_info_t read_info; 850,853c783,787 < n = nxt_file_read(&file, buf, len, nxt_file_size(&finfo) - rest); < if (nxt_slow_path(n != (ssize_t) len)) { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to read 'body' file"); --- > fd = open(RSTRING_PTR(filepath), O_RDONLY, 0); > if (nxt_slow_path(fd == -1)) { > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Failed to open content file \"%s\": %s (%d)", > RSTRING_PTR(filepath), strerror(errno), errno); 855,856c789,790 < goto fail; < } --- > return NXT_UNIT_ERROR; > } 858c792,796 < rest -= len; --- > rc = fstat(fd, &finfo); > if (nxt_slow_path(rc == -1)) { > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Content file fstat(\"%s\") failed: %s (%d)", > RSTRING_PTR(filepath), strerror(errno), errno); 860,864c798 < rc = nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < buf, len); < if (nxt_slow_path(rc != NXT_OK)) { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to write 'body' from application"); --- > close(fd); 866,867c800 < goto fail; < } --- > return NXT_UNIT_ERROR; 870c803,805 < nxt_file_close(nxt_ruby_run_ctx.task, &file); --- > ruby_file.fd = fd; > ruby_file.pos = 0; > ruby_file.rest = finfo.st_size; 872c807,810 < return NXT_OK; --- > read_info.read = nxt_ruby_rack_file_read; > read_info.eof = ruby_file.rest == 0; > read_info.buf_size = ruby_file.rest; > read_info.data = &ruby_file; 874c812,816 < fail: --- > rc = nxt_unit_response_write_cb(nxt_ruby_run_ctx.req, &read_info); > if (nxt_slow_path(rc != NXT_UNIT_OK)) { > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Failed to write content file."); > } 876c818 < nxt_file_close(nxt_ruby_run_ctx.task, &file); --- > close(fd); 878c820 < return NXT_ERROR; --- > return rc; 885c827 < nxt_int_t rc; --- > int rc; 891,895c833,837 < rc = nxt_app_msg_write_raw(nxt_ruby_run_ctx.task, nxt_ruby_run_ctx.wmsg, < (u_char *) RSTRING_PTR(body), RSTRING_LEN(body)); < if (nxt_slow_path(rc != NXT_OK)) { < nxt_log(nxt_ruby_run_ctx.task, NXT_LOG_ERR, < "Ruby: Failed to write 'body' from application"); --- > rc = nxt_unit_response_write(nxt_ruby_run_ctx.req, RSTRING_PTR(body), > RSTRING_LEN(body)); > if (nxt_slow_path(rc != NXT_UNIT_OK)) { > nxt_unit_req_error(nxt_ruby_run_ctx.req, > "Ruby: Failed to write 'body' from application"); 908c850,851 < nxt_log(task, level, "Ruby: %s", desc); --- > if (task != NULL) { > nxt_log(task, level, "Ruby: %s", desc); 909a853,856 > } else { > nxt_unit_log(nxt_ruby_run_ctx.unit_ctx, level, "Ruby: %s", desc); > } > 911c858,860 < ary = rb_funcall(err, rb_intern("backtrace"), 0); --- > if (nxt_slow_path(err == Qnil)) { > return; > } 913c862,863 < if (RARRAY_LEN(ary) == 0) { --- > ary = rb_funcall(err, rb_intern("backtrace"), 0); > if (nxt_slow_path(RARRAY_LEN(ary) == 0)) { 920,922c870,873 < nxt_log(task, level, "Ruby: %s: %s (%s)", < RSTRING_PTR(RARRAY_PTR(ary)[0]), < RSTRING_PTR(msg), RSTRING_PTR(eclass)); --- > if (task != NULL) { > nxt_log(task, level, "Ruby: %s: %s (%s)", > RSTRING_PTR(RARRAY_PTR(ary)[0]), > RSTRING_PTR(msg), RSTRING_PTR(eclass)); 923a875,880 > } else { > nxt_unit_log(nxt_ruby_run_ctx.unit_ctx, level, "Ruby: %s: %s (%s)", > RSTRING_PTR(RARRAY_PTR(ary)[0]), > RSTRING_PTR(msg), RSTRING_PTR(eclass)); > } > 925c882,888 < nxt_log(task, level, "from %s", RSTRING_PTR(RARRAY_PTR(ary)[i])); --- > if (task != NULL) { > nxt_log(task, level, "from %s", RSTRING_PTR(RARRAY_PTR(ary)[i])); > > } else { > nxt_unit_log(nxt_ruby_run_ctx.unit_ctx, level, "from %s", > RSTRING_PTR(RARRAY_PTR(ary)[i])); > } 931c894 < nxt_ruby_atexit(nxt_task_t *task) --- > nxt_ruby_atexit(void)