unit, PSGI and Mojolicous

Alexander Borisov alexander.borisov at nginx.com
Thu Jan 24 16:13:47 UTC 2019


Hi Александр,

Please, try this patch for fix the problem:
# HG changeset patch
# User Alexander Borisov <alexander.borisov at nginx.com>
# Date 1548345939 -10800
#      Thu Jan 24 19:05:39 2019 +0300
# Node ID a0a93e0673de88519bfd1062bdb6df166aa5ffa9
# Parent  dace60fc4926351efe9322761faf974b0ce7964a
Perl: fixed issue with body reading from response object.

diff -r dace60fc4926 -r a0a93e0673de src/perl/nxt_perl_psgi.c
--- a/src/perl/nxt_perl_psgi.c  Wed Jan 23 17:47:53 2019 +0300
+++ b/src/perl/nxt_perl_psgi.c  Thu Jan 24 19:05:39 2019 +0300
@@ -51,6 +51,9 @@
 
 static SV *nxt_perl_psgi_call_var_application(PerlInterpreter *my_perl,
     SV *env, SV *app, nxt_unit_request_info_t *req);
+static SV *
+nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, const char *method,
+    nxt_unit_request_info_t *req);
 
 /* For currect load XS modules */
 EXTERN_C void boot_DynaLoader(pTHX_ CV *cv);
@@ -84,8 +87,6 @@
     SV *result, nxt_unit_request_info_t *req);
 static int nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl,
     SV *sv_body, nxt_unit_request_info_t *req);
-static ssize_t nxt_perl_psgi_io_read(nxt_unit_read_info_t *read_info,
-    void *dst, size_t size);
 static int nxt_perl_psgi_result_array(PerlInterpreter *my_perl,
     SV *result, nxt_unit_request_info_t *req);
 
@@ -251,6 +252,43 @@
 }
 
 
+static SV *
+nxt_perl_psgi_call_method(PerlInterpreter *my_perl, SV *obj, const char *method,
+                          nxt_unit_request_info_t *req)
+{
+    SV  *result;
+
+    dSP;
+
+    ENTER;
+    SAVETMPS;
+
+    PUSHMARK(sp);
+    XPUSHs(obj);
+    PUTBACK;
+
+    call_method( method, G_EVAL|G_SCALAR);
+
+    SPAGAIN;
+
+    if (SvTRUE(ERRSV)) {
+        nxt_unit_req_error(req, "PSGI: Failed to call method '%s':\n%s",
+                           method, SvPV_nolen(ERRSV));
+
+        result = NULL;
+    }
+    else {
+        result = SvREFCNT_inc(POPs);
+    }
+
+    PUTBACK;
+    FREETMPS;
+    LEAVE;
+
+    return result;
+}
+
+
 static u_char *
 nxt_perl_psgi_module_create(nxt_task_t *task, const char *script)
 {
@@ -775,43 +813,40 @@
 nxt_perl_psgi_result_body_ref(PerlInterpreter *my_perl, SV *sv_body,
     nxt_unit_request_info_t *req)
 {
-    IO                      *io;
-    nxt_unit_read_info_t    read_info;
-    nxt_perl_psgi_io_ctx_t  io_ctx;
-
-    io = GvIO(SvRV(sv_body));
+    SV          *data;
+    int         rc;
+    size_t      len;
+    const char  *body;
 
-    if (io == NULL) {
-        return NXT_UNIT_OK;
-    }
+    do {
+        data = nxt_perl_psgi_call_method(my_perl, sv_body, "getline", req);
+        if (nxt_slow_path(data == NULL)) {
+            return NXT_UNIT_ERROR;
+        }
 
-    io_ctx.my_perl = my_perl;
-    io_ctx.fp = IoIFP(io);
+        body = SvPV(data, len);
 
-    read_info.read = nxt_perl_psgi_io_read;
-    read_info.eof = PerlIO_eof(io_ctx.fp);
-    read_info.buf_size = 8192;
-    read_info.data = &io_ctx;
+        if (len == 0) {
+            SvREFCNT_dec(data);
 
-    return nxt_unit_response_write_cb(req, &read_info);
-}
-
+            data = nxt_perl_psgi_call_method(my_perl, sv_body, "close", req);
+            SvREFCNT_dec(data);
 
-static ssize_t
-nxt_perl_psgi_io_read(nxt_unit_read_info_t *read_info, void *dst, size_t size)
-{
-    ssize_t                 res;
-    nxt_perl_psgi_io_ctx_t  *ctx;
+            break;
+        }
+
+        rc = nxt_unit_response_write(req, body, len);
 
-    ctx = read_info->data;
-
-    dTHXa(ctx->my_perl);
+        SvREFCNT_dec(data);
 
-    res = PerlIO_read(ctx->fp, dst, size);
+        if (nxt_slow_path(rc != NXT_UNIT_OK)) {
+            nxt_unit_req_error(req, "PSGI: Failed to read line from response");
+            return rc;
+        }
 
-    read_info->eof = PerlIO_eof(ctx->fp);
+    } while (1);
 
-    return res;
+    return NXT_UNIT_OK;
 }
 
 

 
> 23 янв. 2019 г., в 22:40, Александр Поволоцкий <tarkhil at over.ru> написал(а):
> 
> 
> On 23.01.2019 19:27, Valentin V. Bartenev wrote:
>> On Wednesday 23 January 2019 18:56:57 Александр Поволоцкий wrote:
>>> Hello
>>> 
>>> I'm using Mojolicious::Lite, a Perl framework, which should support PSGI.
>>> 
>>> The smallest possible app, however, does not run
>>> 
>>> ===
>>> #!/usr/bin/env perl
>>> use Mojolicious::Lite;
>>> get '/' => sub {
>>>      my $c = shift;
>>> $c->render(text=>'hello');
>>> };
>>> 
>>> app->start;
>>> ===
>>> 
>>> 2019/01/23 09:41:23.029 [error] 26579#26579 [unit] #4: PSGI: Failed to
>>> run Perl Application:
>>> Undefined subroutine &main::1 called.
>>> 
>>> plackup runs it Ok, so there is some incompatibility, which I do not
>>> know how to trace.
>>> 
>>> What kind of error in framework can it be and how to trace it?
>>> 
>> [..]
>> 
>> https://mojolicious.org/perldoc/Mojolicious/Guides/Cookbook#PSGI-Plack
>> 
>> Seems it doesn't behave like PSGI application by default,
>> unless there's a PLACK_ENV environment variable.
>> 
>> Unit doesn't set PLACK_ENV by default.
> 
> Sorry for doubleposting, but I've found one strange thing.
> 
> root at VMNEW:~# telnet localhost 8000
> Trying ::1...
> Trying 127.0.0.1...
> Connected to localhost.
> Escape character is '^]'.
> GET / HTTP/1.0
> 
> HTTP/1.1 200 OK
> Content-Length: 6
> Date: Wed, 23 Jan 2019 19:31:37 GMT
> Content-Type: text/html;charset=UTF-8
> Server: Unit/1.7
> 
> Connection closed by foreign host.
> 
> when I was expecting "hello\n" to be sent as output. You see, Content-Length is correct, but no actual content.
> 
> Alex
> 
> _______________________________________________
> unit mailing list
> unit at nginx.org <mailto:unit at nginx.org>
> https://mailman.nginx.org/mailman/listinfo/unit <https://mailman.nginx.org/mailman/listinfo/unit>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/unit/attachments/20190124/53438400/attachment.html>


More information about the unit mailing list