Skip to content

Commit 814c5f0

Browse files
CopilotBranimir Karadžić
authored andcommitted
Use UrlLib StatusText for reason phrase; add XMLHttpRequest.statusText
Follow-up to #188. UrlLib now exposes UrlRequest::StatusText() (the wire reason phrase where available, else a canonical code->text table), so: - Fetch: drop the private status-code->text table and read request.StatusText() into Response.statusText. - XMLHttpRequest: expose statusText (previously absent) for free. Adds fetch + XMLHttpRequest statusText tests (OK / Not Found). Bumps the UrlLib pin to BabylonJS/UrlLib 74985214, which adds UrlRequest::StatusText() (BabylonJS/UrlLib#30). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent a407a33 commit 814c5f0

5 files changed

Lines changed: 29 additions & 34 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ FetchContent_Declare(llhttp
4141
EXCLUDE_FROM_ALL)
4242
FetchContent_Declare(UrlLib
4343
GIT_REPOSITORY https://github.com/BabylonJS/UrlLib.git
44-
GIT_TAG 16c7dfd88cb5e7121cb5b037b44b796b737955d4
44+
GIT_TAG 74985214bd4f83a4906b2c62134ac2f9ab89e1ae
4545
EXCLUDE_FROM_ALL)
4646
# --------------------------------------------------
4747

Polyfills/Fetch/Source/Fetch.cpp

Lines changed: 3 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ namespace Babylon::Polyfills::Internal
2424
struct ResponseData
2525
{
2626
int statusCode{};
27+
std::string statusText;
2728
std::string url;
2829
std::vector<std::pair<std::string, std::string>> headers;
2930
std::vector<std::byte> body;
@@ -51,36 +52,6 @@ namespace Babylon::Polyfills::Internal
5152
throw std::runtime_error{"Unsupported fetch method: " + method + " (only GET and POST are supported)"};
5253
}
5354

54-
const char* StatusText(int statusCode)
55-
{
56-
switch (statusCode)
57-
{
58-
case 200: return "OK";
59-
case 201: return "Created";
60-
case 202: return "Accepted";
61-
case 204: return "No Content";
62-
case 206: return "Partial Content";
63-
case 301: return "Moved Permanently";
64-
case 302: return "Found";
65-
case 304: return "Not Modified";
66-
case 307: return "Temporary Redirect";
67-
case 308: return "Permanent Redirect";
68-
case 400: return "Bad Request";
69-
case 401: return "Unauthorized";
70-
case 403: return "Forbidden";
71-
case 404: return "Not Found";
72-
case 405: return "Method Not Allowed";
73-
case 408: return "Request Timeout";
74-
case 409: return "Conflict";
75-
case 429: return "Too Many Requests";
76-
case 500: return "Internal Server Error";
77-
case 502: return "Bad Gateway";
78-
case 503: return "Service Unavailable";
79-
case 504: return "Gateway Timeout";
80-
default: return "";
81-
}
82-
}
83-
8455
std::optional<std::string> FindHeader(const ResponseData& data, std::string_view name)
8556
{
8657
for (const auto& header : data.headers)
@@ -181,7 +152,7 @@ namespace Babylon::Polyfills::Internal
181152
const bool ok = data->statusCode >= 200 && data->statusCode < 300;
182153
response.Set("ok", Napi::Boolean::New(env, ok));
183154
response.Set("status", Napi::Number::New(env, data->statusCode));
184-
response.Set("statusText", Napi::String::New(env, StatusText(data->statusCode)));
155+
response.Set("statusText", Napi::String::New(env, data->statusText));
185156
response.Set("url", Napi::String::New(env, data->url));
186157
response.Set("redirected", Napi::Boolean::New(env, false));
187158
response.Set("type", Napi::String::New(env, "basic"));
@@ -355,6 +326,7 @@ namespace Babylon::Polyfills::Internal
355326

356327
auto data = std::make_shared<ResponseData>();
357328
data->statusCode = status;
329+
data->statusText = std::string{request->StatusText()};
358330
data->url = std::string{request->ResponseUrl()};
359331
for (const auto& header : request->GetAllResponseHeaders())
360332
{

Polyfills/XMLHttpRequest/Source/XMLHttpRequest.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ namespace Babylon::Polyfills::Internal
8080
InstanceAccessor("responseType", &XMLHttpRequest::GetResponseType, &XMLHttpRequest::SetResponseType),
8181
InstanceAccessor("responseURL", &XMLHttpRequest::GetResponseURL, nullptr),
8282
InstanceAccessor("status", &XMLHttpRequest::GetStatus, nullptr),
83+
InstanceAccessor("statusText", &XMLHttpRequest::GetStatusText, nullptr),
8384
InstanceMethod("getAllResponseHeaders", &XMLHttpRequest::GetAllResponseHeaders),
8485
InstanceMethod("getResponseHeader", &XMLHttpRequest::GetResponseHeader),
8586
InstanceMethod("setRequestHeader", &XMLHttpRequest::SetRequestHeader),
@@ -149,6 +150,18 @@ namespace Babylon::Polyfills::Internal
149150
return Napi::Value::From(Env(), arcana::underlying_cast(m_request.StatusCode()));
150151
}
151152

153+
Napi::Value XMLHttpRequest::GetStatusText(const Napi::CallbackInfo&)
154+
{
155+
// Per the XHR spec, statusText is the empty string until a response is available
156+
// (status 0 means UNSENT/OPENED or a network error).
157+
if (arcana::underlying_cast(m_request.StatusCode()) == 0)
158+
{
159+
return Napi::String::New(Env(), "");
160+
}
161+
162+
return Napi::String::New(Env(), std::string{m_request.StatusText()});
163+
}
164+
152165
Napi::Value XMLHttpRequest::GetResponseHeader(const Napi::CallbackInfo& info)
153166
{
154167
const auto headerName = info[0].As<Napi::String>().Utf8Value();

Polyfills/XMLHttpRequest/Source/XMLHttpRequest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ namespace Babylon::Polyfills::Internal
3434
Napi::Value GetAllResponseHeaders(const Napi::CallbackInfo& info);
3535
Napi::Value GetResponseURL(const Napi::CallbackInfo& info);
3636
Napi::Value GetStatus(const Napi::CallbackInfo& info);
37+
Napi::Value GetStatusText(const Napi::CallbackInfo& info);
3738

3839
void AddEventListener(const Napi::CallbackInfo& info);
3940
void RemoveEventListener(const Napi::CallbackInfo& info);

Tests/UnitTests/Scripts/tests.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,13 @@ describe("XMLHTTPRequest", function () {
121121
expect(xhr.status).to.equal(404);
122122
});
123123

124+
it("should expose statusText", async function () {
125+
const okXhr = await createRequest("GET", "https://github.com/");
126+
expect(okXhr.statusText).to.equal("OK");
127+
const notFoundXhr = await createRequest("GET", "https://github.com/babylonJS/BabylonNative404");
128+
expect(notFoundXhr.statusText).to.equal("Not Found");
129+
});
130+
124131
it("should fire 'error' event for a remote URL that returns HTTP 404", async function () {
125132
// Regression test: previously the success-only continuation in XMLHttpRequest::Send
126133
// skipped 'error' on async failures including non-2xx HTTP responses, so onerror
@@ -254,8 +261,10 @@ describe("fetch", function () {
254261
});
255262

256263
it("should expose statusText", async function () {
257-
const response = await fetch("https://github.com/babylonJS/BabylonNative404");
258-
expect(response.statusText).to.equal("Not Found");
264+
const okResponse = await fetch("https://github.com/");
265+
expect(okResponse.statusText).to.equal("OK");
266+
const notFoundResponse = await fetch("https://github.com/babylonJS/BabylonNative404");
267+
expect(notFoundResponse.statusText).to.equal("Not Found");
259268
});
260269

261270
it("text() should return the body as a string", async function () {

0 commit comments

Comments
 (0)