Skip to content

Commit

Permalink
Merge pull request #19 from mrmurb/use_post_for_chat.postMessage
Browse files Browse the repository at this point in the history
WebApi: Changed HTTP methods to POST where recommended by Slack
  • Loading branch information
soxtoby authored Aug 26, 2019
2 parents 62e8557 + 2138473 commit 34d9d1b
Show file tree
Hide file tree
Showing 24 changed files with 165 additions and 107 deletions.
12 changes: 12 additions & 0 deletions SlackNet.Tests/ApiLintTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,18 @@ public Task Post(string apiMethod, Args args, HttpContent content, CancellationT
return Task.FromResult(0);
}

public Task Post(string apiMethod, Args args, CancellationToken? cancellationToken) =>
Post<object>(apiMethod, args, cancellationToken);

public Task<T> Post<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class
{
HttpMethod = "POST";
SlackMethod = apiMethod;
Args = args;
CancellationToken = cancellationToken;
return Task.FromResult(Activator.CreateInstance<T>());
}

public Task<T> Post<T>(string apiMethod, Args args, HttpContent content, CancellationToken? cancellationToken) where T : class
{
HttpMethod = "POST";
Expand Down
14 changes: 3 additions & 11 deletions SlackNet/Http.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ namespace SlackNet
{
public interface IHttp
{
Task<T> Get<T>(string url, CancellationToken? cancellationToken = null);
Task<T> Post<T>(string url, HttpContent content, CancellationToken? cancellationToken = null);
Task<T> Execute<T>(HttpRequestMessage requestMessage, CancellationToken? cancellationToken = null);
}

class Http : IHttp
Expand All @@ -23,16 +22,9 @@ public Http(HttpClient client, SlackJsonSettings jsonSettings)
_jsonSettings = jsonSettings;
}

public async Task<T> Get<T>(string url, CancellationToken? cancellationToken = null)
public async Task<T> Execute<T>(HttpRequestMessage requestMessage, CancellationToken? cancellationToken = null)
{
var response = await _client.SendAsync(new HttpRequestMessage(HttpMethod.Get, url), cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return await Deserialize<T>(response).ConfigureAwait(false);
}

public async Task<T> Post<T>(string url, HttpContent content, CancellationToken? cancellationToken = null)
{
var response = await _client.PostAsync(url, content, cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
var response = await _client.SendAsync(requestMessage, cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
response.EnsureSuccessStatusCode();
return await Deserialize<T>(response).ConfigureAwait(false);
}
Expand Down
66 changes: 60 additions & 6 deletions SlackNet/SlackApiClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
Expand Down Expand Up @@ -56,6 +58,23 @@ public interface ISlackApiClient
/// <param name="cancellationToken"></param>
Task<T> Get<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class;

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
/// <param name="apiMethod">Name of Slack method.</param>
/// <param name="args">Arguments to send to Slack. Authorization headers will be added automatically.</param>
/// <param name="cancellationToken"></param>
Task Post(string apiMethod, Args args, CancellationToken? cancellationToken);

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
/// <typeparam name="T">Type of response expected.</typeparam>
/// <param name="apiMethod">Name of Slack method.</param>
/// <param name="args">Arguments to send to Slack. Authorization headers will be added automatically.</param>
/// <param name="cancellationToken"></param>
Task<T> Post<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class;

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
Expand All @@ -64,7 +83,7 @@ public interface ISlackApiClient
/// <param name="content">POST body content. Should be either <see cref="FormUrlEncodedContent"/> or <see cref="MultipartFormDataContent"/>.</param>
/// <param name="cancellationToken"></param>
Task Post(string apiMethod, Args args, HttpContent content, CancellationToken? cancellationToken);

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
Expand Down Expand Up @@ -145,8 +164,37 @@ public Task Get(string apiMethod, Args args, CancellationToken? cancellationToke
/// <param name="apiMethod">Name of Slack method.</param>
/// <param name="args">Arguments to send to Slack. The "token" parameter will be filled in automatically.</param>
/// <param name="cancellationToken"></param>
public async Task<T> Get<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class =>
Deserialize<T>(await _http.Get<WebApiResponse>(Url(apiMethod, args), cancellationToken ?? CancellationToken.None).ConfigureAwait(false));
public async Task<T> Get<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class
{
var requestMessage = new HttpRequestMessage(HttpMethod.Get, Url(apiMethod, args));
return Deserialize<T>(await _http.Execute<WebApiResponse>(requestMessage, cancellationToken ?? CancellationToken.None).ConfigureAwait(false));
}

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
/// <param name="apiMethod">Name of Slack method.</param>
/// <param name="args">Arguments to send to Slack. The "token" parameter will be filled in automatically.</param>
/// <param name="cancellationToken"></param>
public Task Post(string apiMethod, Args args, CancellationToken? cancellationToken) =>
Post<object>(apiMethod, args, cancellationToken);

/// <summary>
/// Calls a Slack API that requires POST content.
/// </summary>
/// <typeparam name="T">Type of response expected.</typeparam>
/// <param name="apiMethod">Name of Slack method.</param>
/// <param name="args">Arguments to send to Slack. The "token" parameter will be filled in automatically.</param>
/// <param name="cancellationToken"></param>
public async Task<T> Post<T>(string apiMethod, Args args, CancellationToken? cancellationToken) where T : class
{
var requestMessage = new HttpRequestMessage(HttpMethod.Post,Url(apiMethod));
requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);
requestMessage.Content = new StringContent(JsonConvert.SerializeObject(args, _jsonSettings.SerializerSettings), Encoding.UTF8, "application/json");

var response = await _http.Execute<WebApiResponse>(requestMessage, cancellationToken ?? CancellationToken.None).ConfigureAwait(false);
return Deserialize<T>(response);
}

/// <summary>
/// Calls a Slack API that requires POST content.
Expand All @@ -166,9 +214,15 @@ public Task Post(string apiMethod, Args args, HttpContent content, CancellationT
/// <param name="args">Arguments to send to Slack. The "token" parameter will be filled in automatically.</param>
/// <param name="content">POST body content. Should be either <see cref="FormUrlEncodedContent"/> or <see cref="MultipartFormDataContent"/>.</param>
/// <param name="cancellationToken"></param>
public async Task<T> Post<T>(string apiMethod, Args args, HttpContent content, CancellationToken? cancellationToken) where T : class =>
Deserialize<T>(await _http.Post<WebApiResponse>(Url(apiMethod, args), content, cancellationToken ?? CancellationToken.None).ConfigureAwait(false));

public async Task<T> Post<T>(string apiMethod, Args args, HttpContent content, CancellationToken? cancellationToken) where T : class
{
var requestMessage = new HttpRequestMessage(HttpMethod.Post, Url(apiMethod, args)) { Content = content };
return Deserialize<T>(await _http.Execute<WebApiResponse>(requestMessage, cancellationToken ?? CancellationToken.None).ConfigureAwait(false));
}

private string Url(string apiMethod) =>
_urlBuilder.Url(apiMethod, new Args());

private string Url(string apiMethod, Args args)
{
if (!args.ContainsKey("token"))
Expand Down
2 changes: 1 addition & 1 deletion SlackNet/WebApi/ApiApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public class ApiApi : IApiApi
public async Task<IReadOnlyDictionary<string, string>> Test(string error, Args args, CancellationToken? cancellationToken = null)
{
var query = new Args(args) { ["error"] = error };
return (await _client.Get<TestResponse>("api.test", query, cancellationToken).ConfigureAwait(false)).Args;
return (await _client.Post<TestResponse>("api.test", query, cancellationToken).ConfigureAwait(false)).Args;
}
}
}
2 changes: 1 addition & 1 deletion SlackNet/WebApi/AuthApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ public async Task<bool> Revoke(bool test, CancellationToken? cancellationToken =
/// Checks authentication and tells you who you are.
/// </summary>
public Task<AuthTestResponse> Test(CancellationToken? cancellationToken = null) =>
_client.Get<AuthTestResponse>("auth.test", new Args(), cancellationToken);
_client.Post<AuthTestResponse>("auth.test", new Args(), cancellationToken);
}
}
22 changes: 11 additions & 11 deletions SlackNet/WebApi/ChannelsApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public class ChannelsApi : IChannelsApi
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task Archive(string channelId, CancellationToken? cancellationToken = null) =>
_client.Get("channels.archive", new Args { { "channel", channelId } }, cancellationToken);
_client.Post("channels.archive", new Args { { "channel", channelId } }, cancellationToken);

/// <summary>
/// Used to create a channel.
Expand All @@ -172,7 +172,7 @@ public Task Archive(string channelId, CancellationToken? cancellationToken = nul
/// <param name="validate">Whether to return errors on invalid channel name instead of modifying it to meet the specified criteria.</param>
/// <param name="cancellationToken"></param>
public async Task<Channel> Create(string name, bool validate = false, CancellationToken? cancellationToken = null) =>
(await _client.Get<ChannelResponse>("channels.create", new Args
(await _client.Post<ChannelResponse>("channels.create", new Args
{
{ "name", name },
{ "validate", validate }
Expand Down Expand Up @@ -220,7 +220,7 @@ public async Task<Channel> Info(string channelId, CancellationToken? cancellatio
/// <param name="userId">User to invite to channel.</param>
/// <param name="cancellationToken"></param>
public async Task<Channel> Invite(string channelId, string userId, CancellationToken? cancellationToken = null) =>
(await _client.Get<ChannelResponse>("channels.invite", new Args
(await _client.Post<ChannelResponse>("channels.invite", new Args
{
{ "channel", channelId },
{ "user", userId }
Expand All @@ -240,7 +240,7 @@ public async Task<Channel> Invite(string channelId, string userId, CancellationT
/// This allows a client to see that the request to join GeNERaL is the same as the channel #general that the user is already in.
/// </returns>
public Task<ChannelJoinResponse> Join(string channelName, bool validate = false, CancellationToken? cancellationToken = null) =>
_client.Get<ChannelJoinResponse>("channels.join", new Args
_client.Post<ChannelJoinResponse>("channels.join", new Args
{
{ "channel", channelName },
{ "validate", validate }
Expand All @@ -253,7 +253,7 @@ public Task<ChannelJoinResponse> Join(string channelName, bool validate = false,
/// <param name="userId">User to remove from channel.</param>
/// <param name="cancellationToken"></param>
public Task Kick(string channelId, string userId, CancellationToken? cancellationToken = null) =>
_client.Get("channels.kick", new Args
_client.Post("channels.kick", new Args
{
{ "channel", channelId },
{ "user", userId }
Expand All @@ -266,7 +266,7 @@ public Task Kick(string channelId, string userId, CancellationToken? cancellatio
/// <param name="cancellationToken"></param>
/// <returns></returns>
public Task Leave(string channelId, CancellationToken? cancellationToken = null) =>
_client.Get("channels.leave", new Args { { "channel", channelId } }, cancellationToken);
_client.Post("channels.leave", new Args { { "channel", channelId } }, cancellationToken);

/// <summary>
/// Returns a list of all channels in the team.
Expand All @@ -292,7 +292,7 @@ public async Task<IReadOnlyList<Channel>> List(bool excludeArchived = false, boo
/// <param name="ts">Timestamp of the most recently seen message.</param>
/// <param name="cancellationToken"></param>
public Task Mark(string channelId, string ts, CancellationToken? cancellationToken = null) =>
_client.Get("channels.mark", new Args
_client.Post("channels.mark", new Args
{
{ "channel", channelId },
{ "ts", ts }
Expand All @@ -308,7 +308,7 @@ public Task Mark(string channelId, string ts, CancellationToken? cancellationTok
/// <param name="validate">Whether to return errors on invalid channel name instead of modifying it to meet the specified criteria.</param>
/// <param name="cancellationToken"></param>
public async Task<Channel> Rename(string channelId, string name, bool validate = false, CancellationToken? cancellationToken = null) =>
(await _client.Get<ChannelResponse>("channels.rename", new Args
(await _client.Post<ChannelResponse>("channels.rename", new Args
{
{ "channel", channelId },
{ "name", name },
Expand Down Expand Up @@ -338,7 +338,7 @@ public async Task<IReadOnlyList<MessageEvent>> Replies(string channelId, string
/// <param name="cancellationToken"></param>
/// <returns>The channel's new purpose.</returns>
public async Task<string> SetPurpose(string channelId, string purpose, CancellationToken? cancellationToken = null) =>
(await _client.Get<PurposeResponse>("channels.setPurpose", new Args
(await _client.Post<PurposeResponse>("channels.setPurpose", new Args
{
{ "channel", channelId },
{ "purpose", purpose }
Expand All @@ -353,7 +353,7 @@ public async Task<string> SetPurpose(string channelId, string purpose, Cancellat
/// <param name="cancellationToken"></param>
/// <returns>The channel's new topic.</returns>
public async Task<string> SetTopic(string channelId, string topic, CancellationToken? cancellationToken = null) =>
(await _client.Get<TopicResponse>("channels.setTopic", new Args
(await _client.Post<TopicResponse>("channels.setTopic", new Args
{
{ "channel", channelId },
{ "topic", topic }
Expand All @@ -366,6 +366,6 @@ public async Task<string> SetTopic(string channelId, string topic, CancellationT
/// <param name="channelId">Channel to unarchive.</param>
/// <param name="cancellationToken"></param>
public Task Unarchive(string channelId, CancellationToken? cancellationToken = null) =>
_client.Get("channels.unarchive", new Args { { "channel", channelId } }, cancellationToken);
_client.Post("channels.unarchive", new Args { { "channel", channelId } }, cancellationToken);
}
}
Loading

0 comments on commit 34d9d1b

Please sign in to comment.