Skip to content

Commit

Permalink
Improve application/json POST support
Browse files Browse the repository at this point in the history
While the code already existed to support "application/json" as a valid content-type for POST
requests, this did not do anything useful in practice.  So this commit adds the following:

- Add automatic decoding of the POST entity into the variable $CGI::json_ref.  If this variable
  exists, it is already guaranteed to be structurally valid.

- Conditionally handle "application/json" POST mapping into CGI space, using the new UnpackJSON
directive.  This means that for the POSTed JSON object we will populate %CGI::values with the keys
of that object with the (potentially deep structured) values of the same object.

We enable UnpackJSON handling by default, though this value is up for debate.  Considering that we
already don't (shouldn't) trust CGI values, simply making it easier to have structured data using a
JSON request doesn't seem like there are additional security implications.  Additionally, by shoving
this into CGI space, we already have ITL/tag support for accessing the values of the response, which
seem to make this much easier than having redundant UserTags/SystemTags to support inspection of
$CGI::json_ref for the common use case.
  • Loading branch information
David Christensen committed Dec 29, 2014
1 parent 9e02071 commit 59dd4cd
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/Vend/Config.pm
Expand Up @@ -513,6 +513,7 @@ sub global_directives {
['Catalog', 'catalog', ''],
['SubCatalog', 'catalog', ''],
['AutoVariable', 'autovar', 'UrlJoiner'],
['UnpackJSON', 'yesno', 'Yes'],
['XHTML', 'yesno', 'No'],
['UTF8', 'yesno', $ENV{MINIVEND_DISABLE_UTF8} ? 'No' : 'Yes'],
['External', 'yesno', 'No'],
Expand Down
20 changes: 19 additions & 1 deletion lib/Vend/Server.pm
Expand Up @@ -35,6 +35,7 @@ use Errno qw/:POSIX/;
use Config;
use Socket;
use Symbol;
use JSON ();
use strict;

no warnings qw(uninitialized);
Expand Down Expand Up @@ -260,6 +261,8 @@ EOF

#::logDebug("CGI::query_string=" . $CGI::query_string);
#::logDebug("entity=" . ${$h->{entity}});
#::logDebug("request_method=$CGI::request_method");
#::logDebug("content_type=$CGI::content_type");

#::logDebug("Check robot UA=$Global::RobotUA IP=$Global::RobotIP");
if ($Global::RobotIP and $CGI::remote_addr =~ $Global::RobotIP) {
Expand Down Expand Up @@ -320,7 +323,22 @@ sub parse_cgi {
if ($CGI::content_type =~ m{^(?:multipart/form-data|application/x-www-form-urlencoded|application/xml|application/json)\b}i) {
parse_post(\$CGI::query_string, 1)
if $Global::TolerateGet;
parse_post($h->{entity});
if ($CGI::content_type =~ m{^application/json\s*(?:;|$)}i) {
$CGI::post_ref = $h->{entity};
undef $CGI::json_ref;
eval {
$CGI::json_ref = JSON::from_json($$CGI::post_ref);
#::logDebug('json: %s', ::uneval($CGI::json_ref));
# populate CGI from json_ref; maybe make a directive?
if ($Global::UnpackJSON && ref $CGI::json_ref eq 'HASH') {
@CGI::values{keys %$CGI::json_ref} = values %$CGI::json_ref;
}
};
logError("Error parsing JSON data: $@") if $@;
}
else {
parse_post($h->{entity});
}
}
else {
## invalid content type for POST
Expand Down

0 comments on commit 59dd4cd

Please sign in to comment.