Skip to content

Commit 5859ffa

Browse files
authored
Implement XHR getResponseHeader for all platforms (#1149)
1 parent 40557cd commit 5859ffa

File tree

10 files changed

+210
-232
lines changed

10 files changed

+210
-232
lines changed

Dependencies/AndroidExtensions/Include/AndroidExtensions/JavaWrappers.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace java::lang
1616
class ByteArray;
1717
class Object;
1818
class String;
19+
class Throwable;
1920
}
2021

2122
namespace java::io
@@ -222,6 +223,10 @@ namespace java::net
222223

223224
int GetContentLength() const;
224225

226+
lang::String GetHeaderField(int n) const;
227+
228+
lang::String GetHeaderFieldKey(int n) const;
229+
225230
io::InputStream GetInputStream() const;
226231

227232
explicit operator HttpURLConnection() const;

Dependencies/AndroidExtensions/Source/JavaWrappers.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,20 @@ namespace java::net
397397
return {inputStream};
398398
}
399399

400+
lang::String URLConnection::GetHeaderField(int n) const
401+
{
402+
auto result{(jstring)m_env->CallObjectMethod(JObject(), m_env->GetMethodID(m_class, "getHeaderField", "(I)Ljava/lang/String;"), n)};
403+
ThrowIfFaulted(m_env);
404+
return {result};
405+
}
406+
407+
lang::String URLConnection::GetHeaderFieldKey(int n) const
408+
{
409+
auto result{(jstring)m_env->CallObjectMethod(JObject(), m_env->GetMethodID(m_class, "getHeaderFieldKey", "(I)Ljava/lang/String;"), n)};
410+
ThrowIfFaulted(m_env);
411+
return {result};
412+
}
413+
400414
URLConnection::operator HttpURLConnection() const
401415
{
402416
return {JObject()};

Dependencies/UrlLib/CMakeLists.txt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
if(ANDROID)
22
set(ADDITIONAL_SOURCES
3-
"Source/Android/UrlRequest.cpp")
3+
"Source/UrlRequest_Android.cpp")
44
set(ADDITIONAL_LIBRARIES
55
PRIVATE AndroidExtensions)
66
elseif(APPLE)
77
set(ADDITIONAL_SOURCES
8-
"Source/Apple/UrlRequest.mm")
8+
"Source/UrlRequest_Apple.mm")
99
elseif(UNIX)
1010
set(ADDITIONAL_SOURCES
11-
"Source/Unix/UrlRequest.cpp")
11+
"Source/UrlRequest_Unix.cpp")
1212
set(ADDITIONAL_LIBRARIES
1313
PRIVATE curl)
1414
elseif(WIN32)
1515
set(ADDITIONAL_SOURCES
16-
"Source/Windows/UrlRequest.cpp")
16+
"Source/UrlRequest_Windows.cpp")
1717
if(NOT WINDOWS_STORE)
1818
set(ADDITIONAL_LIBRARIES
1919
PUBLIC onecoreuap.lib)
@@ -24,7 +24,8 @@ endif()
2424

2525
set(SOURCES
2626
"Include/UrlLib/UrlLib.h"
27-
"Source/Shared/UrlRequest.h"
27+
"Source/UrlRequest_Base.h"
28+
"Source/UrlRequest_Shared.h"
2829
${ADDITIONAL_SOURCES})
2930

3031
add_library(UrlLib ${SOURCES})
@@ -43,5 +44,4 @@ if(APPLE)
4344
set_property(TARGET UrlLib PROPERTY UNITY_BUILD false)
4445
endif()
4546

46-
4747
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})

Dependencies/UrlLib/Include/UrlLib/UrlLib.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#pragma once
22

33
#include <memory>
4+
#include <optional>
5+
#include <string>
46
#include <string_view>
57
#include <arcana/threading/task.h>
68

@@ -53,12 +55,14 @@ namespace UrlLib
5355

5456
std::string_view ResponseString() const;
5557

56-
std::optional<std::string> GetResponseHeader(const std::string& headerName) const;
57-
5858
gsl::span<const std::byte> ResponseBuffer() const;
5959

60+
std::optional<std::string> GetResponseHeader(const std::string& headerName) const;
61+
6062
private:
6163
class Impl;
64+
class ImplBase;
65+
6266
std::shared_ptr<Impl> m_impl{};
6367
};
6468
}

Dependencies/UrlLib/Source/Android/UrlRequest.cpp renamed to Dependencies/UrlLib/Source/UrlRequest_Android.cpp

Lines changed: 19 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#include <UrlLib/UrlLib.h>
2-
#include <arcana/threading/task.h>
1+
#include "UrlRequest_Base.h"
2+
33
#include <arcana/threading/task_schedulers.h>
44
#include <android/asset_manager.h>
55
#include <AndroidExtensions/Globals.h>
@@ -29,19 +29,9 @@ namespace UrlLib
2929
}
3030
}
3131

32-
class UrlRequest::Impl
32+
class UrlRequest::Impl : public ImplBase
3333
{
3434
public:
35-
~Impl()
36-
{
37-
Abort();
38-
}
39-
40-
void Abort()
41-
{
42-
m_cancellationSource.cancel();
43-
}
44-
4535
void Open(UrlMethod method, const std::string& url)
4636
{
4737
m_method = method;
@@ -65,16 +55,6 @@ namespace UrlLib
6555
}
6656
}
6757

68-
UrlResponseType ResponseType() const
69-
{
70-
return m_responseType;
71-
}
72-
73-
void ResponseType(UrlResponseType value)
74-
{
75-
m_responseType = value;
76-
}
77-
7858
arcana::task<void, std::exception_ptr> SendAsync()
7959
{
8060
return arcana::make_task(arcana::threadpool_scheduler, m_cancellationSource, [this]()
@@ -122,6 +102,21 @@ namespace UrlLib
122102
m_statusCode = UrlStatusCode::Ok;
123103
}
124104

105+
for (int n = 0;; ++n)
106+
{
107+
String key = connection.GetHeaderFieldKey(n);
108+
String value = connection.GetHeaderField(n);
109+
if ((jstring)key == nullptr || (jstring)value == nullptr)
110+
{
111+
break;
112+
}
113+
114+
std::string lowerCaseKey = key;
115+
ToLower(lowerCaseKey);
116+
117+
m_headers.insert({lowerCaseKey, value});
118+
}
119+
125120
int contentLength = connection.GetContentLength();
126121
if (contentLength < 0)
127122
{
@@ -168,43 +163,16 @@ namespace UrlLib
168163
});
169164
}
170165

171-
UrlStatusCode StatusCode() const
172-
{
173-
return m_statusCode;
174-
}
175-
176-
std::string_view ResponseUrl()
177-
{
178-
return m_responseUrl;
179-
}
180-
181-
std::string_view ResponseString()
182-
{
183-
return m_responseString;
184-
}
185-
186166
gsl::span<const std::byte> ResponseBuffer() const
187167
{
188168
return m_responseBuffer;
189169
}
190170

191-
std::optional<std::string> GetResponseHeader(const std::string& /*headerName*/) const
192-
{
193-
// todo: implementation
194-
return {};
195-
}
196-
197171
private:
198-
arcana::cancellation_source m_cancellationSource{};
199-
UrlResponseType m_responseType{UrlResponseType::String};
200-
UrlMethod m_method{UrlMethod::Get};
201172
bool m_schemeIsApp{};
202173
std::string m_appPathOrUrl{};
203-
UrlStatusCode m_statusCode{UrlStatusCode::None};
204-
std::string m_responseUrl{};
205-
std::string m_responseString{};
206174
std::vector<std::byte> m_responseBuffer{};
207175
};
208176
}
209177

210-
#include <Shared/UrlRequest.h>
178+
#include "UrlRequest_Shared.h"

Dependencies/UrlLib/Source/Apple/UrlRequest.mm renamed to Dependencies/UrlLib/Source/UrlRequest_Apple.mm

Lines changed: 10 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,16 @@
1-
#if ! __has_feature(objc_arc)
1+
#if !__has_feature(objc_arc)
22
#error "ARC is off"
33
#endif
44

5-
#include <UrlLib/UrlLib.h>
6-
#include <arcana/threading/task.h>
7-
#include <arcana/threading/task_schedulers.h>
5+
#include "UrlRequest_Base.h"
86

97
#import <Foundation/Foundation.h>
108

119
namespace UrlLib
1210
{
13-
class UrlRequest::Impl
11+
class UrlRequest::Impl : public ImplBase
1412
{
1513
public:
16-
~Impl()
17-
{
18-
Abort();
19-
}
20-
21-
void Abort()
22-
{
23-
m_cancellationSource.cancel();
24-
}
25-
2614
void Open(UrlMethod method, const std::string& url)
2715
{
2816
m_method = method;
@@ -45,16 +33,6 @@ void Open(UrlMethod method, const std::string& url)
4533
m_nsURL = nsURL; // Only store the URL if we didn't throw
4634
}
4735

48-
UrlResponseType ResponseType() const
49-
{
50-
return m_responseType;
51-
}
52-
53-
void ResponseType(UrlResponseType value)
54-
{
55-
m_responseType = value;
56-
}
57-
5836
arcana::task<void, std::exception_ptr> SendAsync()
5937
{
6038
if (m_nsURL == nil)
@@ -81,6 +59,12 @@ void ResponseType(UrlResponseType value)
8159
{
8260
NSHTTPURLResponse* httpResponse{(NSHTTPURLResponse*)response};
8361
m_statusCode = static_cast<UrlStatusCode>(httpResponse.statusCode);
62+
63+
for (id key in httpResponse.allHeaderFields)
64+
{
65+
id value = [httpResponse.allHeaderFields objectForKey:key];
66+
m_headers.insert({ToLower([key UTF8String]), [value UTF8String]});
67+
}
8468
}
8569
else
8670
{
@@ -117,21 +101,6 @@ void ResponseType(UrlResponseType value)
117101
return taskCompletionSource.as_task();
118102
}
119103

120-
UrlStatusCode StatusCode() const
121-
{
122-
return m_statusCode;
123-
}
124-
125-
std::string_view ResponseUrl()
126-
{
127-
return m_responseUrl;
128-
}
129-
130-
std::string_view ResponseString()
131-
{
132-
return m_responseString;
133-
}
134-
135104
gsl::span<const std::byte> ResponseBuffer() const
136105
{
137106
if (m_responseBuffer)
@@ -142,22 +111,10 @@ UrlStatusCode StatusCode() const
142111
return {};
143112
}
144113

145-
std::optional<std::string> GetResponseHeader(const std::string& /*headerName*/) const
146-
{
147-
// todo: implementation
148-
return {};
149-
}
150-
151114
private:
152-
arcana::cancellation_source m_cancellationSource{};
153-
UrlResponseType m_responseType{UrlResponseType::String};
154-
UrlMethod m_method{UrlMethod::Get};
155115
NSURL* m_nsURL{};
156-
UrlStatusCode m_statusCode{UrlStatusCode::None};
157-
std::string m_responseUrl{};
158-
std::string m_responseString{};
159116
NSData* m_responseBuffer{};
160117
};
161118
}
162119

163-
#include <Shared/UrlRequest.h>
120+
#include "UrlRequest_Shared.h"

0 commit comments

Comments
 (0)