Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

Re: CGI: newlines, write exactly "\r\n" to end the headers, then turn off binmode

by 7stud (Deacon)
on Mar 09, 2018 at 11:07 UTC ( [id://1210559]=note: print w/replies, xml ) Need Help??


in reply to Re: CGI: write exactly "\r\n" to end the headers, then turn off binmode
in thread CGI: newlines, write exactly "\r\n" to end the headers, then turn off binmode

Thanks for the responses.

In a CGI script, you usually don't need to care about ending the headers. Just use the $cgi->header(...) method correctly.

In my case, I can't do that. I'm trying to read some simple json data in the body of a post request, but $cgi->{POSTDATA} gives me inconsistent results depending on my server. With an apache server, POSTDATA successfully contains the json. However, I tried my perl script on another server, and POSTDATA returns undef. To solve that issue, I'm reading from STDIN directly. I looked at the source code for CGI.pm, and I don't understand why CGI.pm fails to read the json while executing on my non-apache server, because I can get the json when I read from STDIN directly doing this:

(The cgi spec requires that a script not try to read more than Content-Length from STDIN.)

#!/usr/bin/env perl use strict; use warnings; use 5.020; use autodie; use Data::Dumper; use JSON; if (my $content_len = $ENV{CONTENT_LENGTH}) { read(STDIN, my $json, $content_len); #<===HERE ************ my $href = decode_json($json); my $a = $href->{a}; my $b = $href->{b}; print 'Content-type: text/html'; print "\r\n\r\n"; print "<div>a=$a</div>"; print "<div>b=$b</div>"; } else { my $error = "Could not read json: No Content-Length header in requ +est."; print 'Content-type: text/html'; print "\r\n\r\n"; print "<div>$error</div>"; }
And, once I read from STDIN directly, then none of perl's CGI functionality works.

Replies are listed 'Best First'.
Re^2: CGI: newlines, write exactly "\r\n" to end the headers, then turn off binmode
by Anonymous Monk on Mar 09, 2018 at 13:56 UTC
    what server? What version cgi.pm? You can create cgi objects without it reading fom stdin.

      what server? What version cgi.pm? You can create cgi objects without it reading fom stdin.

      1. I'm experimenting with an Erlang inets httpd server. If you install Erlang, I can give you the code to start a server.
      2. ~$ perl -MCGI -e 'print "$CGI::VERSION\n";' => 4.38

      You can create cgi objects without it reading fom stdin.

      When I create a cgi object after reading from STDIN, my curl request to my Erlang server for the cgi script hangs, then times out (but it does succeed on my apache server):

      #!/usr/bin/env perl use strict; use warnings; use 5.020; use autodie; use Data::Dumper; use JSON; use CGI; use CGI::Carp qw(fatalsToBrowser); if (my $content_len = $ENV{CONTENT_LENGTH}) { read(STDIN, my $json, $content_len); my $href = decode_json($json); my $a = $href->{a}; my $b = $href->{b}; my $q = CGI->new; #Doesn't work with inets httpd server print $q->header, $q->start_html("Test Page"), $q->div("json=$json"), $q->div("a=$a"), $q->div("b=$b"), $q->end_html; #print 'Content-type: text/html'; #print "\r\n\r\n"; #print "<div>a=$a</div>"; #print "<div>b=$b</div>"; } else { my $error = "Could not read json: No Content-Length header in requ +est."; #print 'Content-type: text/html'; #print "\r\n\r\n"; #print "<div>$error</div>"; my $q = CGI->new; print $q->header, $q->start_html("Test Page"), $q->h1($error), $q->end_html; }

      If I comment out the $q lines and uncomment the other print statements, then my curl request succeeds.

      Failed curl request:

      ~$ curl -v -H 'Content-Type: application/json' --data '{"a": 1, "b": 2 +}' http://localhost:65451/cgi-bin/1.pl * Trying ::1... * TCP_NODELAY set * Connection failed * connect to ::1 port 65451 failed: Connection refused * Trying 127.0.0.1... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 65451 (#0) > POST /cgi-bin/1.pl HTTP/1.1 > Host: localhost:65451 > User-Agent: curl/7.58.0 > Accept: */* > Content-Type: application/json > Content-Length: 16 > * upload completely sent off: 16 out of 16 bytes ==== Hangs here for about 5 sseconds ======= < HTTP/1.1 504 Gateway Time-out < Date: Fri, 09 Mar 2018 14:40:55 GMT < Content-Type: text/html < Server: inets/6.4.5 * no chunk, no close, no size. Assume close to signal end < * Closing connection 0 ~$

      Succesful curl request:

      ~$ curl -v -H 'Content-Type: application/json' --data '{"a": 1, "b": 2 +}' http://localhost:65451/cgi-bin/1.pl * Trying ::1... * TCP_NODELAY set * Connection failed * connect to ::1 port 65451 failed: Connection refused * Trying 127.0.0.1... * TCP_NODELAY set * Connected to localhost (127.0.0.1) port 65451 (#0) > POST /cgi-bin/1.pl HTTP/1.1 > Host: localhost:65451 > User-Agent: curl/7.58.0 > Accept: */* > Content-Type: application/json > Content-Length: 16 > * upload completely sent off: 16 out of 16 bytes < HTTP/1.1 200 OK < Date: Fri, 09 Mar 2018 14:52:03 GMT < Server: inets/6.4.5 < Transfer-Encoding: chunked < Content-Type: text/html < * Connection #0 to host localhost left intact <div>a=1</div><div>b=2</div>~$ </div>

        Hi,

        $cgi->{POSTDATA} gives me inconsistent results depending on my server

        Hmm, that isn't exactly how you spell  $cgi->param('POSTDATA')

        I'm sure both CGI.pm maintainer and erlang inets maintainers would be grateful for code that demonstrates these bugs , so they can fix them.

        I'm experimenting with an Erlang inets httpd server. If you install Erlang, I can give you the code to start a server.

        What version of erlang inets ? Surely even erlang inets httpd server have version numbers :)

        When I create a cgi object after reading from STDIN, my curl request to my Erlang server for the cgi script hangs, then times out (but it does succeed on my apache server):

        I'm fairly certain thats the version that tries to read from STDIN. So I would suggest checking CGI.pm docs for ->new and use the version of the call that doesn't try to read from STDIN

        1210567 In reply to 1210553

        Why are you replying to your own nodes instead of hitting "reply" to the node you're quoting?

        Threaded discussion is threaded.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1210559]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (7)
As of 2024-03-29 12:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found