[aur-dev] [PATCH 4/4] rpc: allow multiple args on info query
elij
elij.mx at gmail.com
Tue Apr 12 02:04:22 EDT 2011
On Mon, Apr 11, 2011 at 10:15 PM, Dan McGee <dan at archlinux.org> wrote:
> The majority of "real world" info requests [1] come in hefty batches. We
> would be better served to handle these in one request rather than
> multiple by allowing AUR clients to send multiple arguments.
>
> This enables things like this to work:
> http://aur.test/rpc.php?type=info&arg[]=cups-xerox&arg[]=cups-mc2430dl&arg[]=10673
This kind of breaks the query format convention (thanks php!).
It might be cleaner to use a separator (like a space) to break up args
(and simply split on space).
http://aur.test/rpc.php?type=info&arg=cups-xerox+cups-mc1430dl+10673
(note using plus signs here as an example since spaces or %20s are
harder to 'see')
> Note to RPC users: unfortunately due to the asinine design of PHP, you
> unfortunately have to use the 'arg[]' syntax if you want more than one
> query argument, or you will only get the package satisfying the last arg
> you pass.
>
> [1] Rough data from April 11, 2011, with a total hit count of 1,109,163:
> 12 /login.php
> 13 /rpc.php?type=sarch
> 15 /rpc.php?type=msearch
> 16 /pingserver.php
> 16 /rpc.php
> 22 /logout.php
> 163 /passreset.php
> 335 /account.php
> 530 /pkgsubmit.php
> 916 /rss2.php
> 3838 /index.php
> 6752 /rss.php
> 9699 /
> 42478 /rpc.php?type=search
> 184737 /packages.php
> 681725 /rpc.php?type=info
>
> That means a whopping 61.5% of our requests were for info over the RPC
> interface; package pages are a distant second at only 16.7%.
>
> Signed-off-by: Dan McGee <dan at archlinux.org>
> ---
> web/lib/aurjson.class.php | 59 ++++++++++++++++++++++++++++++++++++--------
> 1 files changed, 48 insertions(+), 11 deletions(-)
>
> diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php
> index 9b0e1a0..57096d8 100644
> --- a/web/lib/aurjson.class.php
> +++ b/web/lib/aurjson.class.php
> @@ -101,6 +101,36 @@ class AurJSON {
> }
>
> /**
> + * Parse the args to the info function. We may have a string or an array,
> + * so do the appropriate thing. Within the elements, both * package IDs
> + * and package names are valid; sort them into the relevant arrays and
> + * escape/quote the names.
> + * @param $args the arg string or array to parse.
> + * @return mixed An array containing 'ids' and 'names'.
> + **/
> + private function parse_info_args($args) {
> + if (!is_array($args)) {
> + $args = array($args);
> + }
> +
> + $id_args = array();
> + $name_args = array();
> + foreach ($args as $arg) {
> + if (!$arg) {
> + continue;
> + }
> + if (is_numeric($arg)) {
> + $id_args[] = intval($arg);
> + } else {
> + $escaped = mysql_real_escape_string($arg, $this->dbh);
> + $name_args[] = "'" . $escaped . "'";
> + }
> + }
> +
> + return array('ids' => $id_args, 'names' => $name_args);
> + }
> +
> + /**
> * Performs a fulltext mysql search of the package database.
> * @param $keyword_string A string of keywords to search with.
> * @return mixed Returns an array of package matches.
> @@ -129,21 +159,28 @@ class AurJSON {
> **/
> private function info($pqdata) {
> $fields = implode(',', self::$fields);
> + $args = $this->parse_info_args($pqdata);
> + $ids = $args['ids'];
> + $names = $args['names'];
>
> - $base_query = "SELECT {$fields} " .
> - " FROM Packages WHERE ";
> + if (!$ids && !$names) {
> + return $this->json_error('Invalid query arguments');
> + }
>
> - if ( is_numeric($pqdata) ) {
> - // just using sprintf to coerce the pqd to an int
> - // should handle sql injection issues, since sprintf will
> - // bork if not an int, or convert the string to a number 0
> - $query_stub = "ID={$pqdata}";
> + $query = "SELECT {$fields} " .
> + " FROM Packages WHERE ";
> + if ($ids) {
> + $ids_value = implode(',', $args['ids']);
> + $query .= "ID IN ({$ids_value})";
I thought 'where in' queries in mysql were known to be terribly slow
compared to using 'where ='.
> }
> - else {
> - $query_stub = sprintf("Name=\"%s\"",
> - mysql_real_escape_string($pqdata, $this->dbh));
> + if ($ids && $names) {
> + $query .= " OR ";
> + }
> + if ($names) {
> + // individual names were quoted in parse_info_args()
> + $names_value = implode(',', $args['names']);
> + $query .= "Name IN ({$names_value})";
> }
> - $query = $base_query . $query_stub;
>
> return $this->process_query('info', $query);
> }
> --
> 1.7.4.4
>
>
More information about the aur-dev
mailing list