Skip to content

Commit

Permalink
Fix URL processing code (#1180)
Browse files Browse the repository at this point in the history
  • Loading branch information
bghgary committed Jan 5, 2023
1 parent 9c69a24 commit 7eae0c3
Show file tree
Hide file tree
Showing 4 changed files with 196 additions and 226 deletions.
80 changes: 38 additions & 42 deletions Apps/UnitTests/Scripts/tests.js
Expand Up @@ -31,62 +31,58 @@ const expect = chai.expect;
describe("XMLHTTPRequest", function () {
this.timeout(0);
it("should have readyState=4 when load ends", async function () {
const xhr = await createRequest("GET", "https://babylonjs.com");
const xhr = await createRequest("GET", "https://httpbin.org/get");
expect(xhr.readyState).to.equal(4);
})
});
it("should have status=200 for a file that exists", async function () {
const xhr = await createRequest("GET", "https://babylonjs.com");
expect(xhr.status).to.equal(200);
})
it("should load unescaped URLs", async function () {
const xhr = await createRequest("GET", "https://github.com/BabylonJS/Assets/raw/master/meshes/στρογγυλεμένος % κύβος.glb");
const xhr = await createRequest("GET", "https://httpbin.org/status/200");
expect(xhr.status).to.equal(200);
})
it("should load partially unescaped URLs", async function () {
const xhr = await createRequest("GET", "https://github.com/BabylonJS/Assets/raw/master/meshes/στρογγυλεμένος%20%%20κύβος.glb");
});
it("should load URLs with escaped unicode characters", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/%CF%83%CF%84%CF%81%CE%BF%CE%B3%CE%B3%CF%85%CE%BB%CE%B5%CE%BC%CE%AD%CE%BD%CE%BF%CF%82%20%25%20%CE%BA%CF%8D%CE%B2%CE%BF%CF%82.glb");
expect(xhr.status).to.equal(200);
})
it("should load escaped URLs", async function () {
const xhr = await createRequest("GET", "https://github.com/BabylonJS/Assets/raw/master/meshes/%CF%83%CF%84%CF%81%CE%BF%CE%B3%CE%B3%CF%85%CE%BB%CE%B5%CE%BC%CE%AD%CE%BD%CE%BF%CF%82%20%25%20%CE%BA%CF%8D%CE%B2%CE%BF%CF%82.glb");
});
it("should load URLs with unescaped unicode characters", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/στρογγυλεμένος%20%25%20κύβος.glb");
expect(xhr.status).to.equal(200);
})
it("should load URLs with unescaped %s", async function () {
const xhr = await createRequest("GET", "https://github.com/BabylonJS/Assets/raw/master/meshes/%CF%83%CF%84%CF%81%CE%BF%CE%B3%CE%B3%CF%85%CE%BB%CE%B5%CE%BC%CE%AD%CE%BD%CE%BF%CF%82%20%%20%CE%BA%CF%8D%CE%B2%CE%BF%CF%82.glb");
});
it("should load URLs with unescaped unicode characters and spaces", async function () {
const xhr = await createRequest("GET", "https://raw.githubusercontent.com/BabylonJS/Assets/master/meshes/στρογγυλεμένος %25 κύβος.glb");
expect(xhr.status).to.equal(200);
})
});
it("should have status=404 for a file that does not exist", async function () {
const xhr = await createRequest("GET", "https://babylonjs.com/invalid");
const xhr = await createRequest("GET", "https://httpbin.org/status/404");
expect(xhr.status).to.equal(404);
})
});
it("should throw something when opening //", async function () {
function openDoubleSlash() {
const xhr = new XMLHttpRequest();
xhr.open("GET", "//");
xhr.send();
}
expect(openDoubleSlash).to.throw();
})
});
it("should throw something when opening a url with no scheme", function () {
function openNoProtocol() {
const xhr = new XMLHttpRequest();
xhr.open("GET", "noscheme.glb");
xhr.send();
}
expect(openNoProtocol).to.throw();
})
});
it("should throw something when sending before opening", function () {
function sendWithoutOpening() {
const xhr = new XMLHttpRequest();
xhr.send();
}
expect(sendWithoutOpening).to.throw();
})
});
it("should open a local file", async function () {
const xhr = await createRequest("GET", "app:///Scripts/tests.js");
expect(xhr).to.have.property('readyState', 4);
expect(xhr).to.have.property('status', 200);
expect(xhr).to.have.property('responseText').with.lengthOf.above(0);
})
});
});

describe("RequestFile", function () {
Expand All @@ -99,8 +95,8 @@ describe("RequestFile", function () {
);
}
expect(RequestFile).to.throw();
})
})
});
});

describe("ColorParsing", function () {
expect(_native.Canvas.parseColor("")).to.equal(0);
Expand All @@ -120,70 +116,70 @@ describe("ColorParsing", function () {
_native.Canvas.parseColor("unknownColor");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("#");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("#12345");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgb(11)");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgb(11,22,33");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgb(11,22,33,");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgba(11, 22, 33, )");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgba(11, 22, 33, 44, 55, 66 )");
}
expect(incorrectColor).to.throw();
})
});

it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgb");
}
expect(incorrectColor).to.throw();
})
});
it("should throw", function () {
function incorrectColor() {
_native.Canvas.parseColor("rgba");
}
expect(incorrectColor).to.throw();
})
})
});
});

function createSceneAndWait(callback, done) {
const engine = new BABYLON.NativeEngine();
Expand All @@ -192,7 +188,7 @@ function createSceneAndWait(callback, done) {
callback(engine, scene);
scene.executeWhenReady(() => {
done();
})
});
}

describe("Materials", function() {
Expand All @@ -210,7 +206,7 @@ describe("Materials", function() {
}, done);
}
createEmptyShaderMat()
})
});
/*
TODO: Uncomment tests for materials as we implement more features
it("GradientMaterial should compile", function(done) {
Expand All @@ -220,7 +216,7 @@ describe("Materials", function() {
sphere.material = gradientMaterial;
}, done);
});*/
})
});

describe("PostProcesses", function() {
this.timeout(0);
Expand Down Expand Up @@ -325,7 +321,7 @@ describe("PostProcesses", function() {
new BABYLON.ScreenSpaceReflectionPostProcess("ssr", scene, 1.0, camera);
}, done);
});*/
})
});

describe("setTimeout", function () {
this.timeout(1000);
Expand Down Expand Up @@ -423,7 +419,7 @@ describe("setTimeout", function () {
}, i * 10);
}
});
})
});

describe("clearTimeout", function () {
this.timeout(0);
Expand All @@ -438,7 +434,7 @@ describe("clearTimeout", function () {
setTimeout(() => { done(); }, 0);
clearTimeout(undefined);
});
})
});

mocha.run(failures => {
// Test program will wait for code to be set before exiting
Expand Down
29 changes: 19 additions & 10 deletions Dependencies/UrlLib/Source/UrlRequest_Apple.mm
Expand Up @@ -6,6 +6,17 @@

#import <Foundation/Foundation.h>

namespace
{
auto URLAllowedCharacterSet = []()
{
NSRange range;
range.location = 0x21;
range.length = 0x7e - range.location + 1;
return [NSCharacterSet characterSetWithRange:range];
}();
}

namespace UrlLib
{
class UrlRequest::Impl : public ImplBase
Expand All @@ -14,34 +25,32 @@
void Open(UrlMethod method, const std::string& url)
{
m_method = method;
NSString* urlString = [NSString stringWithUTF8String:url.data()];
NSURL* nsURL{[NSURL URLWithString:urlString]};
if (!nsURL || !nsURL.scheme)
m_url = [NSURL URLWithString:[[NSString stringWithUTF8String:url.data()] stringByAddingPercentEncodingWithAllowedCharacters:URLAllowedCharacterSet]];
if (!m_url || !m_url.scheme)
{
throw std::runtime_error{"URL does not have a valid scheme"};
}
NSString* scheme{nsURL.scheme};
NSString* scheme{m_url.scheme};
if ([scheme isEqual:@"app"])
{
NSString* path{[[NSBundle mainBundle] pathForResource:nsURL.path ofType:nil]};
NSString* path = [[NSBundle mainBundle] pathForResource:[m_url.path substringFromIndex:1] ofType:nil];
if (path == nil)
{
throw std::runtime_error{"No file exists at local path"};
}
nsURL = [NSURL fileURLWithPath:path];
m_url = [NSURL fileURLWithPath:path];
}
m_nsURL = nsURL; // Only store the URL if we didn't throw
}

arcana::task<void, std::exception_ptr> SendAsync()
{
if (m_nsURL == nil)
if (m_url == nil)
{
// Complete the task, but retain the default status code of 0 to indicate a client side error.
return arcana::task_from_result<std::exception_ptr>();
}
NSURLSession* session{[NSURLSession sharedSession]};
NSURLRequest* request{[NSURLRequest requestWithURL:m_nsURL]};
NSURLRequest* request{[NSURLRequest requestWithURL:m_url]};

__block arcana::task_completion_source<void, std::exception_ptr> taskCompletionSource{};

Expand Down Expand Up @@ -112,7 +121,7 @@ void Open(UrlMethod method, const std::string& url)
}

private:
NSURL* m_nsURL{};
NSURL* m_url{};
NSData* m_responseBuffer{};
};
}
Expand Down

0 comments on commit 7eae0c3

Please sign in to comment.