Skip to content

Commit

Permalink
Merge pull request #668 from azuisleet/webapi-generic-args
Browse files Browse the repository at this point in the history
Pass WebAPI args as generic objects. Encode with correct HttpUtility.UrlEncode override
  • Loading branch information
yaakov-h authored May 5, 2019
2 parents a7cfa25 + 49f3382 commit 51e54e0
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 14 deletions.
7 changes: 6 additions & 1 deletion Samples/6.WebAPI/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,10 +92,15 @@ static void Main( string[] args )
// you can call interface functions through a Call method
using ( WebAPI.Interface steamNews = WebAPI.GetInterface( "ISteamNews" ) )
{
Dictionary<string, string> newsArgs = new Dictionary<string,string>();
Dictionary<string, object> newsArgs = new Dictionary<string, object>();
newsArgs[ "appid" ] = "440";

KeyValue results = steamNews.Call( "GetNewsForApp", /* version */ 1, newsArgs );

foreach ( KeyValue news in results[ "newsitems" ][ "newsitem" ].Children )
{
Console.WriteLine( "News: {0}", news[ "title" ].AsString() );
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion SteamKit2/SteamKit2/Steam/WebAPI/SteamDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ static async Task<IReadOnlyCollection<ServerRecord>> LoadCoreAsync( SteamConfigu
}

var directory = configuration.GetAsyncWebAPIInterface( "ISteamDirectory" );
var args = new Dictionary<string, string>
var args = new Dictionary<string, object>
{
["cellid"] = configuration.CellID.ToString( CultureInfo.InvariantCulture )
};
Expand Down
35 changes: 23 additions & 12 deletions SteamKit2/SteamKit2/Steam/WebAPI/WebAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;

namespace SteamKit2
{
Expand Down Expand Up @@ -67,7 +68,7 @@ internal Interface( HttpClient httpClient, string iface, string apiKey )
/// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception>
/// <exception cref="WebAPIRequestException">A network error occurred when performing the request.</exception>
/// <exception cref="InvalidDataException">An error occured when parsing the response from the WebAPI.</exception>
public KeyValue Call( string func, int version = 1, Dictionary<string, string> args = null )
public KeyValue Call( string func, int version = 1, Dictionary<string, object> args = null )
=> Call( HttpMethod.Get, func, version, args );


Expand All @@ -83,7 +84,7 @@ public KeyValue Call( string func, int version = 1, Dictionary<string, string> a
/// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception>
/// <exception cref="WebAPIRequestException">A network error occurred when performing the request.</exception>
/// <exception cref="InvalidDataException">An error occured when parsing the response from the WebAPI.</exception>
public KeyValue Call( HttpMethod method, string func, int version = 1, Dictionary<string, string> args = null )
public KeyValue Call( HttpMethod method, string func, int version = 1, Dictionary<string, object> args = null )
{
var callTask = asyncInterface.CallAsync( method, func, version, args );

Expand Down Expand Up @@ -209,7 +210,7 @@ internal AsyncInterface( HttpClient httpClient, string iface, string apiKey )
/// <exception cref="HttpRequestException">An network error occurred when performing the request.</exception>
/// <exception cref="WebAPIRequestException">A network error occurred when performing the request.</exception>
/// <exception cref="InvalidDataException">An error occured when parsing the response from the WebAPI.</exception>
public Task<KeyValue> CallAsync( HttpMethod method, string func, int version = 1, Dictionary<string, string> args = null )
public Task<KeyValue> CallAsync( HttpMethod method, string func, int version = 1, Dictionary<string, object> args = null )
{
var task = CallAsyncCore( method, func, version, args );

Expand All @@ -226,7 +227,7 @@ public Task<KeyValue> CallAsync( HttpMethod method, string func, int version = 1
return task;
}

async Task<KeyValue> CallAsyncCore( HttpMethod method, string func, int version = 1, Dictionary<string, string> args = null )
async Task<KeyValue> CallAsyncCore( HttpMethod method, string func, int version = 1, Dictionary<string, object> args = null )
{
if ( method == null )
{
Expand All @@ -240,7 +241,7 @@ async Task<KeyValue> CallAsyncCore( HttpMethod method, string func, int version

if ( args == null )
{
args = new Dictionary<string, string>();
args = new Dictionary<string, object>();
}


Expand Down Expand Up @@ -268,11 +269,21 @@ async Task<KeyValue> CallAsyncCore( HttpMethod method, string func, int version
// append any args
paramBuilder.Append( string.Join( "&", args.Select( kvp =>
{
// TODO: the WebAPI is a special snowflake that needs to appropriately handle url encoding
// this is in contrast to the steam3 content server APIs which use an entirely different scheme of encoding
string key = HttpUtility.UrlEncode( kvp.Key );
string value;

string key = WebHelpers.UrlEncode( kvp.Key );
string value = kvp.Value; // WebHelpers.UrlEncode( kvp.Value );
if ( kvp.Value == null )
{
value = string.Empty;
}
else if ( kvp.Value is byte[] buffer )
{
value = HttpUtility.UrlEncode( buffer );
}
else
{
value = HttpUtility.UrlEncode( kvp.Value.ToString() );
}

return string.Format( "{0}={1}", key, value );
} ) ) );
Expand Down Expand Up @@ -360,7 +371,7 @@ public override bool TryInvokeMember( InvokeMemberBinder binder, object[] args,
throw new InvalidOperationException( "Argument mismatch in API call. All parameters must be passed as named arguments." );
}

var apiArgs = new Dictionary<string, string>();
var apiArgs = new Dictionary<string, object>();

var requestMethod = HttpMethod.Get;

Expand All @@ -384,14 +395,14 @@ public override bool TryInvokeMember( InvokeMemberBinder binder, object[] args,

foreach ( object value in enumerable )
{
apiArgs.Add( String.Format( "{0}[{1}]", argName, index++ ), value.ToString() );
apiArgs.Add( String.Format( "{0}[{1}]", argName, index++ ), value );
}

continue;
}


apiArgs.Add( argName, argValue.ToString() );
apiArgs.Add( argName, argValue );
}

Match match = funcNameRegex.Match( binder.Name );
Expand Down

0 comments on commit 51e54e0

Please sign in to comment.