Skip to content

Commit 325a5ad

Browse files
Merge pull request #77 from ParsePlatform/richardross.command.v1
Remove hard-coded '/1/' from all API request URIs.
2 parents 9d51b34 + e4fdf05 commit 325a5ad

17 files changed

+82
-57
lines changed

Parse/Internal/Analytics/Controller/ParseAnalyticsController.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public Task TrackEventAsync(string name,
2424
data["dimensions"] = dimensions;
2525
}
2626

27-
var command = new ParseCommand("/1/events/" + name,
27+
var command = new ParseCommand("events/" + name,
2828
method: "POST",
2929
sessionToken: sessionToken,
3030
data: PointerOrLocalIdEncoder.Instance.Encode(data) as IDictionary<string, object>);
@@ -42,7 +42,7 @@ public Task TrackAppOpenedAsync(string pushHash,
4242
data["push_hash"] = pushHash;
4343
}
4444

45-
var command = new ParseCommand("/1/events/AppOpened",
45+
var command = new ParseCommand("events/AppOpened",
4646
method: "POST",
4747
sessionToken: sessionToken,
4848
data: PointerOrLocalIdEncoder.Instance.Encode(data) as IDictionary<string, object>);

Parse/Internal/Cloud/Controller/ParseCloudCodeController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public Task<T> CallFunctionAsync<T>(String name,
1717
IDictionary<string, object> parameters,
1818
string sessionToken,
1919
CancellationToken cancellationToken) {
20-
var command = new ParseCommand(string.Format("/1/functions/{0}", Uri.EscapeUriString(name)),
20+
var command = new ParseCommand(string.Format("functions/{0}", Uri.EscapeUriString(name)),
2121
method: "POST",
2222
sessionToken: sessionToken,
2323
data: NoObjectsEncoder.Instance.Encode(parameters) as IDictionary<string, object>);

Parse/Internal/Command/ParseCommand.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,20 @@ namespace Parse.Internal {
1313
internal class ParseCommand : HttpRequest {
1414
private const string revocableSessionTokenTrueValue = "1";
1515

16+
public IDictionary<string, object> DataObject { get; private set; }
17+
public override Stream Data {
18+
get {
19+
if (base.Data != null) {
20+
return base.Data;
21+
}
22+
23+
return base.Data = DataObject != null
24+
? new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(DataObject)))
25+
: null;
26+
}
27+
internal set { base.Data = value; }
28+
}
29+
1630
public ParseCommand(string relativeUri,
1731
string method,
1832
string sessionToken = null,
@@ -21,8 +35,9 @@ public ParseCommand(string relativeUri,
2135
method: method,
2236
sessionToken: sessionToken,
2337
headers: headers,
24-
stream: data != null ? new MemoryStream(UTF8Encoding.UTF8.GetBytes(Json.Encode(data))) : null,
38+
stream: null,
2539
contentType: data != null ? "application/json" : null) {
40+
DataObject = data;
2641
}
2742

2843
public ParseCommand(string relativeUri,

Parse/Internal/Config/Controller/ParseConfigController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public ParseConfigController() {
1919
public IParseCurrentConfigController CurrentConfigController { get; internal set; }
2020

2121
public Task<ParseConfig> FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) {
22-
var command = new ParseCommand("/1/config",
22+
var command = new ParseCommand("config",
2323
method: "GET",
2424
sessionToken: sessionToken,
2525
data: null);

Parse/Internal/File/Controller/ParseFileController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public Task<FileState> SaveAsync(FileState state,
3030
}
3131

3232
var oldPosition = dataStream.Position;
33-
var command = new ParseCommand("/1/files/" + state.Name,
33+
var command = new ParseCommand("files/" + state.Name,
3434
method: "POST",
3535
sessionToken: sessionToken,
3636
contentType: state.MimeType,

Parse/Internal/HttpRequest.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
using System;
44
using System.Collections.Generic;
55
using System.IO;
6-
using System.Net;
7-
using System.Threading;
8-
using System.Threading.Tasks;
96

107
namespace Parse.Internal {
118
/// <summary>
@@ -18,7 +15,7 @@ internal class HttpRequest {
1815
/// <summary>
1916
/// Data stream to be uploaded.
2017
/// </summary>
21-
public Stream Data { get; internal set; }
18+
public virtual Stream Data { get; internal set; }
2219

2320
/// <summary>
2421
/// HTTP method. One of <c>DELETE</c>, <c>GET</c>, <c>HEAD</c>, <c>POST</c> or <c>PUT</c>

Parse/Internal/Object/Controller/ParseObjectController.cs

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal ParseObjectController(IParseCommandRunner commandRunner) {
1717
public Task<IObjectState> FetchAsync(IObjectState state,
1818
string sessionToken,
1919
CancellationToken cancellationToken) {
20-
var command = new ParseCommand(string.Format("/1/classes/{0}/{1}",
20+
var command = new ParseCommand(string.Format("classes/{0}/{1}",
2121
Uri.EscapeDataString(state.ClassName),
2222
Uri.EscapeDataString(state.ObjectId)),
2323
method: "GET",
@@ -36,8 +36,8 @@ public Task<IObjectState> SaveAsync(IObjectState state,
3636
var objectJSON = ParseObject.ToJSONObjectForSaving(operations);
3737

3838
var command = new ParseCommand((state.ObjectId == null ?
39-
string.Format("/1/classes/{0}", Uri.EscapeDataString(state.ClassName)) :
40-
string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
39+
string.Format("classes/{0}", Uri.EscapeDataString(state.ClassName)) :
40+
string.Format("classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
4141
method: (state.ObjectId == null ? "POST" : "PUT"),
4242
sessionToken: sessionToken,
4343
data: objectJSON);
@@ -55,14 +55,15 @@ public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
5555
IList<IDictionary<string, IParseFieldOperation>> operationsList,
5656
string sessionToken,
5757
CancellationToken cancellationToken) {
58-
var requests = states.Zip(operationsList, (item, ops) => new Dictionary<string, object> {
59-
{ "method", (item.ObjectId == null ? "POST" : "PUT") },
60-
{ "path", (item.ObjectId == null ?
61-
string.Format("/1/classes/{0}", Uri.EscapeDataString(item.ClassName)) :
62-
string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(item.ClassName),
63-
Uri.EscapeDataString(item.ObjectId))) },
64-
{ "body", ParseObject.ToJSONObjectForSaving(ops) }
65-
}).Cast<object>().ToList();
58+
59+
var requests = states
60+
.Zip(operationsList, (item, ops) => new ParseCommand(
61+
item.ObjectId == null
62+
? string.Format("classes/{0}", Uri.EscapeDataString(item.ClassName))
63+
: string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
64+
method: item.ObjectId == null ? "POST" : "PUT",
65+
data: ParseObject.ToJSONObjectForSaving(ops)))
66+
.ToList();
6667

6768
var batchTasks = ExecuteBatchRequests(requests, sessionToken, cancellationToken);
6869
var stateTasks = new List<Task<IObjectState>>();
@@ -78,7 +79,7 @@ public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
7879
public Task DeleteAsync(IObjectState state,
7980
string sessionToken,
8081
CancellationToken cancellationToken) {
81-
var command = new ParseCommand(string.Format("/1/classes/{0}/{1}",
82+
var command = new ParseCommand(string.Format("classes/{0}/{1}",
8283
state.ClassName, state.ObjectId),
8384
method: "DELETE",
8485
sessionToken: sessionToken,
@@ -90,24 +91,25 @@ public Task DeleteAsync(IObjectState state,
9091
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
9192
string sessionToken,
9293
CancellationToken cancellationToken) {
93-
var requests = states.Where(item => item.ObjectId != null).Select(item => new Dictionary<string, object> {
94-
{ "method", "DELETE" },
95-
{ "path", string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(item.ClassName),
96-
Uri.EscapeDataString(item.ObjectId)) }
97-
}).Cast<object>().ToList();
98-
94+
var requests = states
95+
.Where(item => item.ObjectId != null)
96+
.Select(item => new ParseCommand(
97+
string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
98+
method: "DELETE",
99+
data: null))
100+
.ToList();
99101
return ExecuteBatchRequests(requests, sessionToken, cancellationToken).Cast<Task>().ToList();
100102
}
101103

102104
// TODO (hallucinogen): move this out to a class to be used by Analytics
103105
private const int MaximumBatchSize = 50;
104-
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<object> requests,
106+
internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<ParseCommand> requests,
105107
string sessionToken,
106108
CancellationToken cancellationToken) {
107109
var tasks = new List<Task<IDictionary<string, object>>>();
108110
int batchSize = requests.Count;
109111

110-
IEnumerable<object> remaining = requests;
112+
IEnumerable<ParseCommand> remaining = requests;
111113
while (batchSize > MaximumBatchSize) {
112114
var process = remaining.Take(MaximumBatchSize).ToList();
113115
remaining = remaining.Skip(MaximumBatchSize);
@@ -121,7 +123,7 @@ internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<obj
121123
return tasks;
122124
}
123125

124-
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<object> requests,
126+
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<ParseCommand> requests,
125127
string sessionToken,
126128
CancellationToken cancellationToken) {
127129
var tasks = new List<Task<IDictionary<string, object>>>();
@@ -133,10 +135,21 @@ private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<objec
133135
tasks.Add(tcs.Task);
134136
}
135137

136-
var command = new ParseCommand("/1/batch",
138+
var encodedRequests = requests.Select(r => {
139+
var results = new Dictionary<string, object> {
140+
{ "method", r.Method },
141+
{ "path", r.Uri.AbsolutePath },
142+
};
143+
144+
if (r.DataObject != null) {
145+
results["body"] = r.DataObject;
146+
}
147+
return results;
148+
}).Cast<object>().ToList();
149+
var command = new ParseCommand("batch",
137150
method: "POST",
138151
sessionToken: sessionToken,
139-
data: new Dictionary<string, object> { { "requests", requests } });
152+
data: new Dictionary<string, object> { { "requests", encodedRequests } });
140153

141154
commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t => {
142155
if (t.IsFaulted || t.IsCanceled) {

Parse/Internal/Push/Controller/ParsePushController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
namespace Parse.Internal {
99
internal class ParsePushController : IParsePushController {
1010
public Task SendPushNotificationAsync(IPushState state, String sessionToken, CancellationToken cancellationToken) {
11-
var command = new ParseCommand("/1/push",
11+
var command = new ParseCommand("push",
1212
method: "POST",
1313
sessionToken: sessionToken,
1414
data: ParsePushEncoder.Instance.Encode(state));

Parse/Internal/Query/Controller/ParseQueryController.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ private Task<IDictionary<string, object>> FindAsync(string className,
5959
IDictionary<string, object> parameters,
6060
string sessionToken,
6161
CancellationToken cancellationToken) {
62-
var command = new ParseCommand(string.Format("/1/classes/{0}?{1}",
62+
var command = new ParseCommand(string.Format("classes/{0}?{1}",
6363
Uri.EscapeDataString(className),
6464
ParseClient.BuildQueryString(parameters)),
6565
method: "GET",

Parse/Internal/Session/Controller/ParseSessionController.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ internal ParseSessionController(IParseCommandRunner commandRunner) {
1414
}
1515

1616
public Task<IObjectState> GetSessionAsync(string sessionToken, CancellationToken cancellationToken) {
17-
var command = new ParseCommand("/1/sessions/me",
17+
var command = new ParseCommand("sessions/me",
1818
method: "GET",
1919
sessionToken: sessionToken,
2020
data: null);
@@ -25,7 +25,7 @@ public Task<IObjectState> GetSessionAsync(string sessionToken, CancellationToken
2525
}
2626

2727
public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) {
28-
var command = new ParseCommand("/1/logout",
28+
var command = new ParseCommand("logout",
2929
method: "POST",
3030
sessionToken: sessionToken,
3131
data: new Dictionary<string, object>());
@@ -34,7 +34,7 @@ public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken
3434
}
3535

3636
public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
37-
var command = new ParseCommand("/1/upgradeToRevocableSession",
37+
var command = new ParseCommand("upgradeToRevocableSession",
3838
method: "POST",
3939
sessionToken: sessionToken,
4040
data: new Dictionary<string, object>());

Parse/Internal/User/Controller/ParseUserController.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public Task<IObjectState> SignUpAsync(IObjectState state,
1818
CancellationToken cancellationToken) {
1919
var objectJSON = ParseObject.ToJSONObjectForSaving(operations);
2020

21-
var command = new ParseCommand("/1/classes/_User",
21+
var command = new ParseCommand("classes/_User",
2222
method: "POST",
2323
data: objectJSON);
2424

@@ -39,7 +39,7 @@ public Task<IObjectState> LogInAsync(string username,
3939
{"password", password}
4040
};
4141

42-
var command = new ParseCommand(string.Format("/1/login?{0}", ParseClient.BuildQueryString(data)),
42+
var command = new ParseCommand(string.Format("login?{0}", ParseClient.BuildQueryString(data)),
4343
method: "GET",
4444
data: null);
4545

@@ -58,7 +58,7 @@ public Task<IObjectState> LogInAsync(string authType,
5858
var authData = new Dictionary<string, object>();
5959
authData[authType] = data;
6060

61-
var command = new ParseCommand("/1/users",
61+
var command = new ParseCommand("users",
6262
method: "POST",
6363
data: new Dictionary<string, object> {
6464
{"authData", authData}
@@ -74,7 +74,7 @@ public Task<IObjectState> LogInAsync(string authType,
7474
}
7575

7676
public Task<IObjectState> GetUserAsync(string sessionToken, CancellationToken cancellationToken) {
77-
var command = new ParseCommand("/1/users/me",
77+
var command = new ParseCommand("users/me",
7878
method: "GET",
7979
sessionToken: sessionToken,
8080
data: null);
@@ -85,7 +85,7 @@ public Task<IObjectState> GetUserAsync(string sessionToken, CancellationToken ca
8585
}
8686

8787
public Task RequestPasswordResetAsync(string email, CancellationToken cancellationToken) {
88-
var command = new ParseCommand("/1/requestPasswordReset",
88+
var command = new ParseCommand("requestPasswordReset",
8989
method: "POST",
9090
data: new Dictionary<string, object> {
9191
{"email", email}

Parse/ParseClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ internal static string VersionString {
8282
/// </param>
8383
public static void Initialize(string applicationId, string dotnetKey) {
8484
lock (mutex) {
85-
HostName = HostName ?? new Uri("https://api.parse.com/");
85+
HostName = HostName ?? new Uri("https://api.parse.com/1/");
8686
ApplicationId = applicationId;
8787
WindowsKey = dotnetKey;
8888

ParseTest.Unit/AnalyticsControllerTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
namespace ParseTest {
1313
[TestFixture]
1414
public class AnalyticsControllerTests {
15-
[SetUp]
16-
public void SetUp() {
17-
ParseClient.HostName = new Uri("http://parse.com");
15+
[SetUp]
16+
public void SetUp() {
17+
ParseClient.HostName = new Uri("http://api.parse.local/1/");
1818
}
1919

2020
[TearDown]

ParseTest.Unit/CommandTests.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace ParseTest {
1515
public class CommandTests {
1616
[SetUp]
1717
public void SetUp() {
18-
ParseClient.HostName = new Uri("http://parse.com");
18+
ParseClient.HostName = new Uri("http://api.parse.local/1/");
1919
}
2020

2121
[TearDown]
@@ -26,7 +26,7 @@ public void TearDown() {
2626

2727
[Test]
2828
public void TestMakeCommand() {
29-
ParseCommand command = new ParseCommand("/1/endpoint",
29+
ParseCommand command = new ParseCommand("endpoint",
3030
method: "GET",
3131
sessionToken: "abcd",
3232
headers: null,
@@ -49,7 +49,7 @@ public Task TestRunCommand() {
4949
It.IsAny<CancellationToken>())).Returns(fakeResponse);
5050

5151
ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
52-
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
52+
var command = new ParseCommand("endpoint", method: "GET", data: null);
5353
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
5454
Assert.False(t.IsFaulted);
5555
Assert.False(t.IsCanceled);
@@ -69,7 +69,7 @@ public Task TestRunCommandWithArrayResult() {
6969
It.IsAny<CancellationToken>())).Returns(fakeResponse);
7070

7171
ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
72-
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
72+
var command = new ParseCommand("endpoint", method: "GET", data: null);
7373
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
7474
Assert.False(t.IsFaulted);
7575
Assert.False(t.IsCanceled);
@@ -91,7 +91,7 @@ public Task TestRunCommandWithInvalidString() {
9191
It.IsAny<CancellationToken>())).Returns(fakeResponse);
9292

9393
ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
94-
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
94+
var command = new ParseCommand("endpoint", method: "GET", data: null);
9595
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
9696
Assert.True(t.IsFaulted);
9797
Assert.False(t.IsCanceled);
@@ -112,7 +112,7 @@ public Task TestRunCommandWithErrorCode() {
112112
It.IsAny<CancellationToken>())).Returns(fakeResponse);
113113

114114
ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
115-
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
115+
var command = new ParseCommand("endpoint", method: "GET", data: null);
116116
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
117117
Assert.True(t.IsFaulted);
118118
Assert.False(t.IsCanceled);
@@ -134,7 +134,7 @@ public Task TestRunCommandWithInternalServerError() {
134134
It.IsAny<CancellationToken>())).Returns(fakeResponse);
135135

136136
ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
137-
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
137+
var command = new ParseCommand("endpoint", method: "GET", data: null);
138138
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
139139
Assert.True(t.IsFaulted);
140140
Assert.False(t.IsCanceled);

ParseTest.Unit/ObjectControllerTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace ParseTest {
1515
public class ObjectControllerTests {
1616
[SetUp]
1717
public void SetUp() {
18-
ParseClient.HostName = new Uri("http://parse.com");
18+
ParseClient.HostName = new Uri("http://api.parse.local/1/");
1919
}
2020

2121
[TearDown]

0 commit comments

Comments
 (0)