Skip to content

Remove hard-coded '/1/' from all API request URIs. #77

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Nov 16, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public Task TrackEventAsync(string name,
data["dimensions"] = dimensions;
}

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

var command = new ParseCommand("/1/events/AppOpened",
var command = new ParseCommand("events/AppOpened",
method: "POST",
sessionToken: sessionToken,
data: PointerOrLocalIdEncoder.Instance.Encode(data) as IDictionary<string, object>);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public Task<T> CallFunctionAsync<T>(String name,
IDictionary<string, object> parameters,
string sessionToken,
CancellationToken cancellationToken) {
var command = new ParseCommand(string.Format("/1/functions/{0}", Uri.EscapeUriString(name)),
var command = new ParseCommand(string.Format("functions/{0}", Uri.EscapeUriString(name)),
method: "POST",
sessionToken: sessionToken,
data: NoObjectsEncoder.Instance.Encode(parameters) as IDictionary<string, object>);
Expand Down
17 changes: 16 additions & 1 deletion Parse/Internal/Command/ParseCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,20 @@ namespace Parse.Internal {
internal class ParseCommand : HttpRequest {
private const string revocableSessionTokenTrueValue = "1";

public IDictionary<string, object> DataObject { get; private set; }
public override Stream Data {
get {
if (base.Data != null) {
return base.Data;
}

return base.Data = DataObject != null
? new MemoryStream(Encoding.UTF8.GetBytes(Json.Encode(DataObject)))
: null;
}
internal set { base.Data = value; }
}

public ParseCommand(string relativeUri,
string method,
string sessionToken = null,
Expand All @@ -21,8 +35,9 @@ public ParseCommand(string relativeUri,
method: method,
sessionToken: sessionToken,
headers: headers,
stream: data != null ? new MemoryStream(UTF8Encoding.UTF8.GetBytes(Json.Encode(data))) : null,
stream: null,
contentType: data != null ? "application/json" : null) {
DataObject = data;
}

public ParseCommand(string relativeUri,
Expand Down
2 changes: 1 addition & 1 deletion Parse/Internal/Config/Controller/ParseConfigController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public ParseConfigController() {
public IParseCurrentConfigController CurrentConfigController { get; internal set; }

public Task<ParseConfig> FetchConfigAsync(String sessionToken, CancellationToken cancellationToken) {
var command = new ParseCommand("/1/config",
var command = new ParseCommand("config",
method: "GET",
sessionToken: sessionToken,
data: null);
Expand Down
2 changes: 1 addition & 1 deletion Parse/Internal/File/Controller/ParseFileController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public Task<FileState> SaveAsync(FileState state,
}

var oldPosition = dataStream.Position;
var command = new ParseCommand("/1/files/" + state.Name,
var command = new ParseCommand("files/" + state.Name,
method: "POST",
sessionToken: sessionToken,
contentType: state.MimeType,
Expand Down
5 changes: 1 addition & 4 deletions Parse/Internal/HttpRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading;
using System.Threading.Tasks;

namespace Parse.Internal {
/// <summary>
Expand All @@ -18,7 +15,7 @@ internal class HttpRequest {
/// <summary>
/// Data stream to be uploaded.
/// </summary>
public Stream Data { get; internal set; }
public virtual Stream Data { get; internal set; }

/// <summary>
/// HTTP method. One of <c>DELETE</c>, <c>GET</c>, <c>HEAD</c>, <c>POST</c> or <c>PUT</c>
Expand Down
59 changes: 36 additions & 23 deletions Parse/Internal/Object/Controller/ParseObjectController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ internal ParseObjectController(IParseCommandRunner commandRunner) {
public Task<IObjectState> FetchAsync(IObjectState state,
string sessionToken,
CancellationToken cancellationToken) {
var command = new ParseCommand(string.Format("/1/classes/{0}/{1}",
var command = new ParseCommand(string.Format("classes/{0}/{1}",
Uri.EscapeDataString(state.ClassName),
Uri.EscapeDataString(state.ObjectId)),
method: "GET",
Expand All @@ -36,8 +36,8 @@ public Task<IObjectState> SaveAsync(IObjectState state,
var objectJSON = ParseObject.ToJSONObjectForSaving(operations);

var command = new ParseCommand((state.ObjectId == null ?
string.Format("/1/classes/{0}", Uri.EscapeDataString(state.ClassName)) :
string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
string.Format("classes/{0}", Uri.EscapeDataString(state.ClassName)) :
string.Format("classes/{0}/{1}", Uri.EscapeDataString(state.ClassName), state.ObjectId)),
method: (state.ObjectId == null ? "POST" : "PUT"),
sessionToken: sessionToken,
data: objectJSON);
Expand All @@ -55,14 +55,15 @@ public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
IList<IDictionary<string, IParseFieldOperation>> operationsList,
string sessionToken,
CancellationToken cancellationToken) {
var requests = states.Zip(operationsList, (item, ops) => new Dictionary<string, object> {
{ "method", (item.ObjectId == null ? "POST" : "PUT") },
{ "path", (item.ObjectId == null ?
string.Format("/1/classes/{0}", Uri.EscapeDataString(item.ClassName)) :
string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(item.ClassName),
Uri.EscapeDataString(item.ObjectId))) },
{ "body", ParseObject.ToJSONObjectForSaving(ops) }
}).Cast<object>().ToList();

var requests = states
.Zip(operationsList, (item, ops) => new ParseCommand(
item.ObjectId == null
? string.Format("classes/{0}", Uri.EscapeDataString(item.ClassName))
: string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
method: item.ObjectId == null ? "POST" : "PUT",
data: ParseObject.ToJSONObjectForSaving(ops)))
.ToList();

var batchTasks = ExecuteBatchRequests(requests, sessionToken, cancellationToken);
var stateTasks = new List<Task<IObjectState>>();
Expand All @@ -78,7 +79,7 @@ public IList<Task<IObjectState>> SaveAllAsync(IList<IObjectState> states,
public Task DeleteAsync(IObjectState state,
string sessionToken,
CancellationToken cancellationToken) {
var command = new ParseCommand(string.Format("/1/classes/{0}/{1}",
var command = new ParseCommand(string.Format("classes/{0}/{1}",
state.ClassName, state.ObjectId),
method: "DELETE",
sessionToken: sessionToken,
Expand All @@ -90,24 +91,25 @@ public Task DeleteAsync(IObjectState state,
public IList<Task> DeleteAllAsync(IList<IObjectState> states,
string sessionToken,
CancellationToken cancellationToken) {
var requests = states.Where(item => item.ObjectId != null).Select(item => new Dictionary<string, object> {
{ "method", "DELETE" },
{ "path", string.Format("/1/classes/{0}/{1}", Uri.EscapeDataString(item.ClassName),
Uri.EscapeDataString(item.ObjectId)) }
}).Cast<object>().ToList();

var requests = states
.Where(item => item.ObjectId != null)
.Select(item => new ParseCommand(
string.Format("classes/{0}/{1}", Uri.EscapeDataString(item.ClassName), Uri.EscapeDataString(item.ObjectId)),
method: "DELETE",
data: null))
.ToList();
return ExecuteBatchRequests(requests, sessionToken, cancellationToken).Cast<Task>().ToList();
}

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

IEnumerable<object> remaining = requests;
IEnumerable<ParseCommand> remaining = requests;
while (batchSize > MaximumBatchSize) {
var process = remaining.Take(MaximumBatchSize).ToList();
remaining = remaining.Skip(MaximumBatchSize);
Expand All @@ -121,7 +123,7 @@ internal IList<Task<IDictionary<string, object>>> ExecuteBatchRequests(IList<obj
return tasks;
}

private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<object> requests,
private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<ParseCommand> requests,
string sessionToken,
CancellationToken cancellationToken) {
var tasks = new List<Task<IDictionary<string, object>>>();
Expand All @@ -133,10 +135,21 @@ private IList<Task<IDictionary<string, object>>> ExecuteBatchRequest(IList<objec
tasks.Add(tcs.Task);
}

var command = new ParseCommand("/1/batch",
var encodedRequests = requests.Select(r => {
var results = new Dictionary<string, object> {
{ "method", r.Method },
{ "path", r.Uri.AbsolutePath },
};

if (r.DataObject != null) {
results["body"] = r.DataObject;
}
return results;
}).Cast<object>().ToList();
var command = new ParseCommand("batch",
method: "POST",
sessionToken: sessionToken,
data: new Dictionary<string, object> { { "requests", requests } });
data: new Dictionary<string, object> { { "requests", encodedRequests } });

commandRunner.RunCommandAsync(command, cancellationToken: cancellationToken).ContinueWith(t => {
if (t.IsFaulted || t.IsCanceled) {
Expand Down
2 changes: 1 addition & 1 deletion Parse/Internal/Push/Controller/ParsePushController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace Parse.Internal {
internal class ParsePushController : IParsePushController {
public Task SendPushNotificationAsync(IPushState state, String sessionToken, CancellationToken cancellationToken) {
var command = new ParseCommand("/1/push",
var command = new ParseCommand("push",
method: "POST",
sessionToken: sessionToken,
data: ParsePushEncoder.Instance.Encode(state));
Expand Down
2 changes: 1 addition & 1 deletion Parse/Internal/Query/Controller/ParseQueryController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ private Task<IDictionary<string, object>> FindAsync(string className,
IDictionary<string, object> parameters,
string sessionToken,
CancellationToken cancellationToken) {
var command = new ParseCommand(string.Format("/1/classes/{0}?{1}",
var command = new ParseCommand(string.Format("classes/{0}?{1}",
Uri.EscapeDataString(className),
ParseClient.BuildQueryString(parameters)),
method: "GET",
Expand Down
6 changes: 3 additions & 3 deletions Parse/Internal/Session/Controller/ParseSessionController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ internal ParseSessionController(IParseCommandRunner commandRunner) {
}

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

public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken) {
var command = new ParseCommand("/1/logout",
var command = new ParseCommand("logout",
method: "POST",
sessionToken: sessionToken,
data: new Dictionary<string, object>());
Expand All @@ -34,7 +34,7 @@ public Task RevokeAsync(string sessionToken, CancellationToken cancellationToken
}

public Task<IObjectState> UpgradeToRevocableSessionAsync(string sessionToken, CancellationToken cancellationToken) {
var command = new ParseCommand("/1/upgradeToRevocableSession",
var command = new ParseCommand("upgradeToRevocableSession",
method: "POST",
sessionToken: sessionToken,
data: new Dictionary<string, object>());
Expand Down
10 changes: 5 additions & 5 deletions Parse/Internal/User/Controller/ParseUserController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public Task<IObjectState> SignUpAsync(IObjectState state,
CancellationToken cancellationToken) {
var objectJSON = ParseObject.ToJSONObjectForSaving(operations);

var command = new ParseCommand("/1/classes/_User",
var command = new ParseCommand("classes/_User",
method: "POST",
data: objectJSON);

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

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

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

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

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

public Task RequestPasswordResetAsync(string email, CancellationToken cancellationToken) {
var command = new ParseCommand("/1/requestPasswordReset",
var command = new ParseCommand("requestPasswordReset",
method: "POST",
data: new Dictionary<string, object> {
{"email", email}
Expand Down
2 changes: 1 addition & 1 deletion Parse/ParseClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ internal static string VersionString {
/// </param>
public static void Initialize(string applicationId, string dotnetKey) {
lock (mutex) {
HostName = HostName ?? new Uri("https://api.parse.com/");
HostName = HostName ?? new Uri("https://api.parse.com/1/");
ApplicationId = applicationId;
WindowsKey = dotnetKey;

Expand Down
6 changes: 3 additions & 3 deletions ParseTest.Unit/AnalyticsControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
namespace ParseTest {
[TestFixture]
public class AnalyticsControllerTests {
[SetUp]
public void SetUp() {
ParseClient.HostName = new Uri("http://parse.com");
[SetUp]
public void SetUp() {
ParseClient.HostName = new Uri("http://api.parse.local/1/");
}

[TearDown]
Expand Down
14 changes: 7 additions & 7 deletions ParseTest.Unit/CommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ParseTest {
public class CommandTests {
[SetUp]
public void SetUp() {
ParseClient.HostName = new Uri("http://parse.com");
ParseClient.HostName = new Uri("http://api.parse.local/1/");
}

[TearDown]
Expand All @@ -26,7 +26,7 @@ public void TearDown() {

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

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

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

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

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

ParseCommandRunner commandRunner = new ParseCommandRunner(mockHttpClient.Object);
var command = new ParseCommand("/1/endpoint", method: "GET", data: null);
var command = new ParseCommand("endpoint", method: "GET", data: null);
return commandRunner.RunCommandAsync(command).ContinueWith(t => {
Assert.True(t.IsFaulted);
Assert.False(t.IsCanceled);
Expand Down
2 changes: 1 addition & 1 deletion ParseTest.Unit/ObjectControllerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace ParseTest {
public class ObjectControllerTests {
[SetUp]
public void SetUp() {
ParseClient.HostName = new Uri("http://parse.com");
ParseClient.HostName = new Uri("http://api.parse.local/1/");
}

[TearDown]
Expand Down
Loading