Testing an HTTPS POST request
Update
An alternative to the Dancer-powered program that I present here might be Test::Fake::HTTPD, though I have yet to try it. If you use Test::Fake::HTTPD instead of Dancer, you would still use the App::TLSMe-related code in your program. brian d foy offers a tutorial in his blog post.
See run_https_server()
--It looks like you should be able to do
OO-style (new
, then run
) if you pass a 'scheme' argument to new
(although this is not documented).
Lastly, I also came across the related HTTP::Daemon::SSL, though I have not tried that either.
Recently, I wanted to test an application that was going to make an HTTP
POST request via HTTPS (to be subsequently referred to as "HTTPS POST").
The content-type of the request was supposed to be
application/x-www-form-urlencoded
.
In order to verify the request, and to really see what the request was going to look like, I went down a path of writing a small Perl-powered program. The goal was to quickly and to temporarily start an HTTP test server to be used for debugging.
By using CPAN modules like Dancer and App::TLSMe, I was able to run a local HTTP server wrapped in TLS (SSL). The resulting program, https-test-server, provides a simple way to inspect the HTTPS POST request:
#!/usr/bin/env perl use Dancer; use Data::Dumper; use App::TLSMe; use Proc::Fork qw( run_fork child ); my $http_port = 3001; my $https_port = 8080; set port => $http_port; set logger => 'console'; run_fork { child { App::TLSMe->new( listen => "0.0.0.0:${https_port}", backend => "0.0.0.0:${http_port}", method => "any", )->run; } }; get '/' => sub { return 'Is SSL working? :)'; }; post '/post_test' => sub { local $Data::Dumper::Indent = 0; debug 'Content-type: ' . request->content_type; debug 'Method used: ' . request->method; debug 'Body: ' . request->body; debug 'Body params: ' . Dumper( { params('body') } ); debug 'Query params: ' . Dumper( { params('query') } ); }; dance;
You probably need to install some dependencies for this program before you can run it. :) You can try this fun automated method, assuming that you have cpanm installed:
$ cpanm Perl::PrereqScanner && \ scan_prereqs --combine https-test-server | awk '{ print $1 }' | cpanm
Now, run the Perl-powered HTTP server, which will wrap itself in TLS:
$ perl https-test-server >> Dancer 1.31 server 20543 listening on http://0.0.0.0:3001 == Entering the development dance floor ...
As specified in the source of https-test-server
, Dancer will run the
HTTP server at port 3001. The HTTPS entry point will be at port 8080, as
provided by App::TLSMe.
Start by hitting the Dancer application at port 3001: point your browser
to http://localhost:3001
.
You will get a web page with the message "Is SSL working? :)" in your browser. Of course, the answer to that question is: "Not yet." :)
Now hit the Dancer application at port 8080: point your browser to
https://localhost:8080
. [1] You see that same message, but now it's
coming at you through an encrypted connection. Say it with me: "Oh
yeah!" :)
Now it's time to see what an HTTPS POST will do, via the /post_test
route in the web application. In another shell, use curl(1) to POST
form data. In this case, I sent a query string consisting of some
familiar
words
(foo => bar
and baz => quux
):
$ curl --insecure --data 'foo=bar&baz=quux' https://localhost:8080/post_test 1
Switch back to the other shell. You should see some debugging statements like this:
[20543] debug @0.001974> [hit #1]Content-type: application/x-www-form-urlencoded in https-test-server l. 29 [20543] debug @0.002348> [hit #1]Method used: POST in https-test-server l. 30 [20543] debug @0.002645> [hit #1]Body: foo=bar&baz=quux in https-test-server l. 31 [20543] debug @0.003818> [hit #1]Body params: $VAR1 = {'baz' => 'quux',' foo' => 'bar'}; in https-test-server l. 32 [20543] debug @0.004271> [hit #1]Query params: $VAR1 = {}; in https-test-server l. 33
The content-type is correct, the method is correct, and the sent form
data is present in both the body and in the body params. Excellent! :)
Now you can use the https://localhost:8080/post_test
URL as an
endpoint anywhere else to see what a POST request will look like.
Lastly, I'll note that in taking a tip from an old Dancer mailing list thread, I had tried to follow the instructions in the HTTP::Server::Simple documentation to subclass the module, in order to enable the SSL layer underneath. That wasn't working, so luckily I came across App::TLSMe after seeing a mention of it in the PocketIO documentation. It works beautifully. Thanks Viacheslav! :)
[1] You'll likely get a scary message from the browser about how it's an insecure connection. That's because App::TLSMe uses a phony SSL certificate by default. Fine by me: who pays for legitimate SSL certificates for development environments? :)