Is connecting to a REST API within the scope of help on these forums?

Discussion in 'CommandHelper' started by malon, May 21, 2017.

  1. malon

    malon Member

    I'm trying to connect to challonge.com's public API, and so far, I've done very well for myself. I've created a tournament, deleted it, added participants, removed them, looped through upcoming matches. It seemed I had a pretty good handle on how it works, or at least I thought so. Also, to be clear, this is the first REST API I have ever connected with, so I am brand new to it.

    But I am completely failing at updating a match. (https://api.challonge.com/v1/documents/matches/update) Every time I try to update the match, I get a server response of "Match parameters are required". But I am sending the match parameters, as I had to send parameters on every other previous request for creating, deleting, etc, so I know how to send parameters. I have tried to get in contact with challonge.com to see if it's an API issue or not. I think I'm probably doing something wrong.

    So what's different about this one vs all the others? Nothing really, except that this is the 1st time using "PUT". However, challonge.com offers an alternative to POST it witha a special paramter of "put" as an alternate method, but neither one works for me. I basically don't know where to turn at this point. I'm pretty sure it's not CommandHelper that's broken. I give it about a 10% chance that challonge is broken and a 90% chance I'm doing something wrong.

    I am going to provide some active code, you should be able to copy-paste this to your own server and see the error messages. Yes, I realize I'm posting my public API key, I will be obviously deleting and regenerating a different key after this issue is resolved. Yes, I know this is risky, but asking help to debug an API interaction that really has little to do with CH directly is a steep request, so I am trying to make it as easy as possible.

    On to the code

    PHP:


    # This code references match 1 of this tournament
    # http://challonge.com/moops_omnivs - lissakitty vs God_Doesnt_Exist
    # The goal of this code is to retrieve the json info about this match and also
    # update the score of the match so that lissakitty wins. Only the former has been
    # successful.

    /apiget = >>>

    @tournamentName = 'moops'
    @tournamentURL = @tournamentName.'_omnivs'
    @matchID = 88443733
    @challongeAPIKey = ''

    # Request JSON for a specific match
    # https://api.challonge.com/v1/documents/matches/show
    @url = 'https://api.challonge.com/v1/tournaments/'[email protected]tournamentURL.'/matches/'[email protected]matchID.'.json'
    http_request(@url, array(
        method: 'GET',
        headers: array(
         'Content-Type': 'application/json'
        ),
        # params from the website
       params: array(
         'api_key': @challongeAPIKey
        ),
        # Server Response
       success: closure(@response){
            # If the server throws an error
           if(@response['responseCode'] != 200){
                tmsg(@plr,color(red).'Error!')
                # Full debug reponse along with url
                msg(@response)
                msg(@url)
                @error = json_decode(@response['body'])
                foreach(@error in @error['errors']){
                    tmsg(@plr,color(red)[email protected]error)
                }
                die()
            }
            # Successful resposne from the API and displays the array of info
            msg(json_decode(@response['body']))
            msg('Success!')
        }
    ))

    <<<

    /apiset = >>>

    @tournamentName = 'moops'
    @tournamentURL = @tournamentName.'_omnivs'
    @matchID = 88443733
    @winnerID = 55979279
    @score = '1-0'
    @challongeAPIKey = ''

    # Uncomment this one to try it - suggest commenting the above block
    # https://api.challonge.com/v1/documents/matches/update
    # Update score to match
    @url = 'https://api.challonge.com/v1/tournaments/'[email protected]tournamentURL.'/matches/'[email protected]matchID.'.json'
    http_request(@url, array(
        method: 'POST',
        headers: array(
         'Content-Type': 'application/json'
        ),
        # params from the website
       params: array(
         'api_key': @challongeAPIKey,
         '_method': 'put', # CH supports the PUT method, but I had trouble using it - this way succeeds in getting a JSON response
        'scores_csv': @score, # should be in CSV format (eg '1-0,3-4,9-3') The 1st number is considered Player 1's score
        'winner_id': @winnerID, # The Challonge ID of the winner
        'player1_votes': '1', # optional
        'player2_votes': '0', # optional
       ),
        # Server Response
       success: closure(@response){
            if(@response['responseCode'] != 200){
                msg(color(red).'Error!')
                # Full debug reponse along with url
                msg(@response)
                msg(@url)
                @error = json_decode(@response['body'])
                foreach(@error in @error['errors']){
                    msg(color(red)[email protected]error)
                }
                die()
            }
             msg(json_decode(@response['body']))
            msg('Success!')
        }
    ))

    <<<

     
    Last edited: May 22, 2017
  2. PseudoKnight

    PseudoKnight Well-Known Member

    I looked at their API and it seems you need to put 'scores_csv', 'winner_id', 'player1_votes', and 'player2_votes' inside an array with the index 'match'. It might not have been apparent with their documentation formatting, but that's probably why it said "Match parameters are required". It was literally looking for 'match'.
    PHP:
    'params': array(
        'api_key': @challongeAPIKey,
        '_method': 'put',
        'match': array(
            'scores_csv': @score,
            'winner_id': @winnerID,
            'player1_votes': '1',
            'player2_votes': '0',
        ),
    ),
    Let me know if it works. I haven't tried it.
  3. malon

    malon Member

    I'm trying it right now, thank you. Would you please tell me how you figured that out?
    Last edited: May 22, 2017
  4. PseudoKnight

    PseudoKnight Well-Known Member

    I just inferred it from the API based on a few clues. The formatting for those keys was different than the others, and I knew there was a reason. The sample response had 'scores_csv' under the 'match' key, possibly suggesting a consistency. And of course, the error message itself. I also benefited from knowing something was wrong and being a new pair of eyes, as they say.

    http://api.challonge.com/v1/documents/matches/update
  5. malon

    malon Member

    Unfortunately, that didn't seem to work, same error message:

    PHP:

    /apiset = >>>

    @tournamentName = 'moops'
    @tournamentURL = @tournamentName.'_omnivs'
    @matchID = 88443733
    @winnerID = 55979279
    @score = '1-0'
    @challongeAPIKey = ''

    # Uncomment this one to try it - suggest commenting the above block
    # https://api.challonge.com/v1/documents/matches/update
    # Update score to match
    @url = 'https://api.challonge.com/v1/tournaments/'[email protected]tournamentURL.'/matches/'[email protected]matchID.'.json'
    http_request(@url, array(
        method: 'POST',
        headers: array(
         'Content-Type': 'application/json'
        ),
        # params from the website
      params: array(
         'api_key': @challongeAPIKey,
         '_method': 'put', # CH supports the PUT method, but I had trouble using it - this way succeeds in getting a JSON response
        'match': array(
           'scores_csv': @score, # should be in CSV format (eg '1-0,3-4,9-3') The 1st number is considered Player 1's score
          'winner_id': @winnerID, # The Challonge ID of the winner
          'player1_votes': '1', # optional
          'player2_votes': '0', # optional
      )),
        # Server Response
      success: closure(@response){
            if(@response['responseCode'] != 200){
                msg(color(red).'Error!')
                # Full debug reponse along with url
               msg(@response)
                msg(@url)
                @error = json_decode(@response['body'])
                foreach(@error in @error['errors']){
                    msg(color(red)[email protected]error)
                }
                die()
            }
             msg(json_decode(@response['body']))
            msg('Success!')
        }
    ))
    <<<

     
    Last edited: May 22, 2017
  6. malon

    malon Member

    Got it...apparently the params are literally 'match[scores_csv/winner_id]' as a string, weird.
  7. PseudoKnight

    PseudoKnight Well-Known Member

    That might have something to do with how CH encodes it, not sure. Can you give me an example?
  8. malon

    malon Member

    This is what I was doing:
    PHP:

      params: array(
         'api_key':@challongeAPIKey,
         '_method':'put',
         'scores_csv':@score,
         'winner_id':@winnerID,
      )
     
    This is what they wanted
    PHP:

      params: array(
         'api_key':@challongeAPIKey,
         '_method':'put',
         'match[scores_csv]':@score,
         'match[winner_id]':@winnerID,
      )
     
  9. PseudoKnight

    PseudoKnight Well-Known Member

    Hah. Wow. That's way more literal than I thought.
  10. LadyCailin

    LadyCailin Administrator Developer

    You found a bug!

    After reading around the internet, including some RFCs, the following would be expected behavior for these params:
    Code (Text):
     params: array(
                    v: array(
                                 'one':'test1',
                                 'two': array(
                                       'a': 'test2',
                                       'b': 'test3'
                                  )
                    ),
                    m: 'test4'
            )
    Code (Text):
    url.com?v%5Bone%5D=test1&v%5Btwo%5D%5Ba%5D=test2&v%5Btwo%5D%5Bb%5D=test3&m=test4
    Or without the brackets encoded (incorrect, but easier to read):

    Code (Text):
    url.com?v[one]=test1&v[two][a]=test2&v[two][b]=test3&m=test4
    I believe that this logic should also hold for post requests, since application/x-www-form-encoded is the mime type for url query strings.

    So in other words, your original code should have worked. I will fix this problem, but in the meantime, your solution should work, and actually should continue to work even after I make the change.
    Last edited: Jul 24, 2017