Search code examples
rhttphttr

Httr header returns invalid character '-' in numeric literal


I'm using the httr to access the API for stockfighter, a CTF style trading game.

The GET function is working without any problems, but when I try and authenticate using an API key in the headers it doesn't appear to be working. Here's my place_order function

place_order <- function(acct, exchange, stock, price, qty,
                        direction = c("buy", "sell"),
                        type = c("limit", "market", "fill-or-kill",
                                 "immediate-or-cancel")) {
# Place a stock order
  if (!exists("key")) stop("No authorisation key defined.")
  direction <- match.arg(direction)
  type <- match.arg(type)
  bdy <- list("account" = acct, "venue" = exchange, "symbol" = stock,
               "price" = price, "qty" = qty, "direction" = direction,
               "orderType" = type)
  rurl <- paste(burl, "/venues/", exchange, "/stocks/", stock, "/orders",
               sep = "")
  r <- POST(rurl, body = bdy, add_headers(`X-Starfighter-Authorization` = key))
  return(content(r))
}

This is what I get in return:

$ok
[1] FALSE

$error
[1] "invalid character '-' in numeric literal"

It appears that the JSON is not escaping the dashes correctly.

This is the response I get when I post to httpbin instead of the API:

$args
named list()

$data
[1] ""

$files
named list()

$form
$form$account
[1] "RB34256134"

$form$direction
[1] "buy"

$form$orderType
[1] "limit"

$form$price
[1] "12400"

$form$qty
[1] "100"

$form$symbol
[1] "FOOBAR"

$form$venue
[1] "TESTEX"


$headers
$headers$Accept
[1] "application/json, text/xml, application/xml, */*"

$headers$`Accept-Encoding`
[1] "gzip, deflate"

$headers$`Content-Length`
[1] "751"

$headers$`Content-Type`
[1] "multipart/form-data; boundary=------------------------49a2e51c0c6926dd"

$headers$Host
[1] "httpbin.org"

$headers$`User-Agent`
[1] "libcurl/7.43.0 r-curl/0.9.4 httr/1.0.0.9000"

$headers$`X-Starfighter-Authorization`
[1] "OBFUSCATED KEY HERE"


$json
NULL

$origin
[1] "1.125.48.185"

$url
[1] "http://httpbin.org/post"

I feel like this is probably a really stupid simple error but I can't work it out.

EDIT:

Here's the python method using requests and json that works perfectly.

def sf_post(path, data, key, **kwargs):
    base_url = "https://api.stockfighter.io/ob/api/"
    r = requests.post("%s/%s" % (base_url, path), data = data, headers = {'X-Starfighter-Authorization': key}, **kwargs)
    return(r)    

def order(self, price, qty, direction, order_type):
            data = dict(account = self.account, venue = self.exchange, symbol = self.symbol, price = price, qty = qty,
                        direction = direction, orderType = order_type)
            r = sf_post("%s/orders" % self.rurl, data = json.dumps(data), key = self.key)
            return r.json()

    cph = Stock("CPH", "EXMBEX", account = "ACCOUNTCODEHERE", key = os.environ.get("SF_KEY"))

    cph.order(5000, qty = 100, direction = "buy", order_type = "limit")
    {u'direction': u'buy', u'ok': True, u'ts': u'2016-01-24T00:35:21.148877285Z', u'fills': [{u'price': 4694, u'ts': u'2016-01-24T00:35:21.148881279Z', u'qty': 100}], u'originalQty': 100, u'orderType': u'limit', u'symbol': u'CPH', u'venue': u'EXMBEX', u'account': u'SSM90915021', u'qty': 0, u'id': 754, u'totalFilled': 100, u'open': False, u'price': 5000}

Solution

  • I thought I was probably missing something stupid, and as @hadley pointed out in the comments I was. I needed to add encode = "json" to my POST call. For posterity here's the updated function code:

    place_order <- function(acct, exchange, stock, price, qty,
                            direction = c("buy", "sell"),
                            type = c("limit", "market", "fill-or-kill",
                                     "immediate-or-cancel")) {
      if (!exists("key")) stop("No authorisation key defined.")
      direction <- match.arg(direction)
      type <- match.arg(type)
      bdy <- list("account" = acct, "venue" = exchange, "symbol" = stock,
                   "price" = price, "qty" = qty, "direction" = direction,
                   "orderType" = type)
        rurl <- paste(burl, "venues/", exchange, "/stocks/", stock, "/orders",
                     sep = "")
      r <- POST(rurl, body = bdy,
                add_headers(`X-Starfighter-Authorization` = key),
                encode = "json")
      return(content(r))
    }