Skip to content
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

POST requests and setting request headers. #1

Merged
merged 26 commits into from
Mar 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
81fcd20
point android extensions to correct branch
Feb 23, 2023
ae8312f
test print
Feb 23, 2023
0a85220
add missing imports
Feb 23, 2023
8c5d23a
test newly added method
lmaskati Feb 24, 2023
f5566ca
adding logic for setRequestHeaders
lmaskati Mar 2, 2023
be09108
add android post request logic
lmaskati Mar 6, 2023
a5ff524
Add windows implementation for post and setRequestHeaders
lmaskati Mar 6, 2023
9a57c32
add post logic and set request headers for apple
lmaskati Mar 6, 2023
dee7f25
set request headers before processing POST
lmaskati Mar 6, 2023
347433f
remove iostream import
lmaskati Mar 6, 2023
9b6d530
modify CMake to point at original repo
lmaskati Mar 7, 2023
e5131d0
Update Source/UrlRequest_Android.cpp
lmaskati Mar 7, 2023
3bb7230
Update Source/UrlRequest_Apple.mm
lmaskati Mar 7, 2023
82e863b
Formatting
lmaskati Mar 7, 2023
aa2c525
Formatting
lmaskati Mar 7, 2023
fa41404
Formatting
lmaskati Mar 7, 2023
d949839
formatting
lmaskati Mar 7, 2023
ca9cde7
Remove unnecessary string copies
lmaskati Mar 7, 2023
a473d09
process content type response header outside for loop
lmaskati Mar 7, 2023
7d4c5a9
Merge branch 'main' of https://github.com/lmaskati/UrlLib
lmaskati Mar 7, 2023
424f481
Automatically sets to empty string
lmaskati Mar 7, 2023
826d4cb
avoid copying for GetAllResponseHeaders
lmaskati Mar 7, 2023
89f30f7
Merge branch 'main' of https://github.com/lmaskati/UrlLib
lmaskati Mar 7, 2023
3571d70
Whitespace
bghgary Mar 7, 2023
8bd3932
group all header related functions together
lmaskati Mar 7, 2023
81df50c
Merge branch 'main' of https://github.com/lmaskati/UrlLib
lmaskati Mar 7, 2023
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
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ if(ANDROID AND NOT TARGET AndroidExtensions)
FetchContent_Declare(
AndroidExtensions
GIT_REPOSITORY https://github.com/BabylonJS/AndroidExtensions.git
GIT_TAG efaa68b2882d882470e7d1374b0d52d80db3ca35)
GIT_TAG 4a54e636bde25d4b9f1b02e2414ee642005ff244)

message(STATUS "Fetching AndroidExtensions")
FetchContent_MakeAvailable(AndroidExtensions)
Expand Down
12 changes: 10 additions & 2 deletions Include/UrlLib/UrlLib.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#include <string>
#include <string_view>
#include <arcana/threading/task.h>
#include <unordered_map>

namespace UrlLib
{
Expand All @@ -17,6 +18,7 @@ namespace UrlLib
enum class UrlMethod
{
Get,
Post
};

enum class UrlResponseType
Expand Down Expand Up @@ -49,6 +51,14 @@ namespace UrlLib

arcana::task<void, std::exception_ptr> SendAsync();

void SetRequestBody(std::string requestBody);

void SetRequestHeader(std::string name, std::string value);

std::optional<std::string> GetResponseHeader(const std::string& headerName) const;

const std::unordered_map<std::string, std::string>& GetAllResponseHeaders() const;

UrlStatusCode StatusCode() const;

std::string_view ResponseUrl() const;
Expand All @@ -57,8 +67,6 @@ namespace UrlLib

gsl::span<const std::byte> ResponseBuffer() const;

std::optional<std::string> GetResponseHeader(const std::string& headerName) const;

private:
class Impl;
class ImplBase;
Expand Down
27 changes: 26 additions & 1 deletion Source/UrlRequest_Android.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,33 @@ namespace UrlLib
URL url{m_appPathOrUrl.data()};

URLConnection connection{url.OpenConnection()};
connection.Connect();

// set request headers
for (auto request : m_requestHeaders)
{
const std::string& key = request.first;
const std::string& value = request.second;
connection.SetRequestProperty(key, value);
}
m_requestHeaders.clear();

// if this a POST request
if (m_method == UrlMethod::Post)
{
((HttpURLConnection)connection).SetRequestMethod("POST");
connection.SetDoOutput(true);

// need to manually set the content length of the request body
size_t numBytes = m_requestBody.size();
connection.SetRequestProperty("Content-Length", std::to_string(numBytes));

OutputStream outputStream{connection.GetOutputStream()};
OutputStreamWriter writer{outputStream};
writer.Write(m_requestBody);
writer.Close();
}

connection.Connect();
if (connection.GetClass().IsAssignableFrom(HttpURLConnection::Class()))
{
m_statusCode = static_cast<UrlStatusCode>(((HttpURLConnection)connection).GetResponseCode());
Expand Down
19 changes: 19 additions & 0 deletions Source/UrlRequest_Apple.mm
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ void Open(UrlMethod method, const std::string& url)
NSURLSession* session{[NSURLSession sharedSession]};
NSURLRequest* request{[NSURLRequest requestWithURL:m_url]};

NSMutableURLRequest* mutableRequest{[request mutableCopy]};

// set header requests
for (auto request: m_requestHeaders)
{
[mutableRequest setValue:@(request.second.data()) forHTTPHeaderField:@(request.first.data())];
}

if (m_method == UrlMethod::Post)
{
mutableRequest.HTTPMethod = @"POST";
// set the body
NSString* stringBody = [NSString stringWithUTF8String:m_requestBody.data()];
NSData* requestBodyData = [stringBody dataUsingEncoding:NSUTF8StringEncoding];
mutableRequest.HTTPBody = requestBodyData;
}

request = [mutableRequest copy];

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

id completionHandler{^(NSData* data, NSURLResponse* response, NSError* error)
Expand Down
38 changes: 27 additions & 11 deletions Source/UrlRequest_Base.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,31 @@ namespace UrlLib
m_cancellationSource.cancel();
}

void SetRequestBody(std::string requestBody) {
m_requestBody = requestBody;
}

void SetRequestHeader(std::string name, std::string value)
{
m_requestHeaders[name] = value;
}

const std::unordered_map<std::string, std::string>& GetAllResponseHeaders() const
{
return m_headers;
}

std::optional<std::string> GetResponseHeader(const std::string& headerName) const
{
const auto it = m_headers.find(ToLower(headerName.data()));
if (it == m_headers.end())
{
return {};
}

return it->second;
}

UrlResponseType ResponseType() const
{
return m_responseType;
Expand All @@ -46,17 +71,6 @@ namespace UrlLib
return m_responseString;
}

std::optional<std::string> GetResponseHeader(const std::string& headerName) const
{
const auto it = m_headers.find(ToLower(headerName.data()));
if (it == m_headers.end())
{
return {};
}

return it->second;
}

protected:
static std::string ToLower(const char* str)
{
Expand All @@ -77,5 +91,7 @@ namespace UrlLib
std::string m_responseUrl{};
std::string m_responseString{};
std::unordered_map<std::string, std::string> m_headers;
std::string m_requestBody{};
std::unordered_map<std::string, std::string> m_requestHeaders;
};
}
25 changes: 20 additions & 5 deletions Source/UrlRequest_Shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,26 @@ namespace UrlLib
m_impl->ResponseType(value);
}

void UrlRequest::SetRequestBody(std::string requestBody)
{
m_impl->SetRequestBody(requestBody);
}

void UrlRequest::SetRequestHeader(std::string key, std::string value)
{
m_impl->SetRequestHeader(key, value);
}

const std::unordered_map<std::string, std::string>& UrlRequest::GetAllResponseHeaders() const
{
return m_impl->GetAllResponseHeaders();
}

std::optional<std::string> UrlRequest::GetResponseHeader(const std::string& headerName) const
{
return m_impl->GetResponseHeader(headerName);
}

arcana::task<void, std::exception_ptr> UrlRequest::SendAsync()
{
return m_impl->SendAsync();
Expand All @@ -61,9 +81,4 @@ namespace UrlLib
{
return m_impl->ResponseBuffer();
}

std::optional<std::string> UrlRequest::GetResponseHeader(const std::string& headerName) const
{
return m_impl->GetResponseHeader(headerName);
}
}
35 changes: 35 additions & 0 deletions Source/UrlRequest_Windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <winrt/Windows.Web.Http.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.Web.Http.Headers.h>

namespace UrlLib
{
Expand All @@ -21,6 +22,8 @@ namespace UrlLib
{
case UrlMethod::Get:
return Web::Http::HttpMethod::Get();
case UrlMethod::Post:
return Web::Http::HttpMethod::Post();
default:
throw std::runtime_error("Unsupported method");
}
Expand Down Expand Up @@ -83,6 +86,34 @@ namespace UrlLib
requestMessage.RequestUri(m_uri);
requestMessage.Method(ConvertHttpMethod(m_method));

std::string contentType;

for (auto request : m_requestHeaders)
{
// content type needs to be set separately
if (request.first == "Content-Type")
{
contentType = request.second;
}
else
{
requestMessage.Headers().Append(winrt::to_hstring(request.first), winrt::to_hstring(request.second));
}
}

m_requestHeaders.clear();

// check the method
if (m_method == UrlMethod::Post)
{
// if post, set the content type
requestMessage.Content(Web::Http::HttpStringContent(
winrt::to_hstring(m_requestBody),
winrt::Windows::Storage::Streams::UnicodeEncoding::Utf8,
winrt::to_hstring(contentType))
);
}

Web::Http::HttpClient client;
return arcana::create_task<std::exception_ptr>(client.SendRequestAsync(requestMessage))
.then(arcana::inline_scheduler, m_cancellationSource, [this](Web::Http::HttpResponseMessage responseMessage)
Expand All @@ -99,6 +130,10 @@ namespace UrlLib
{
m_headers.insert(std::make_pair(winrt::to_string(iter.Key()), winrt::to_string(iter.Value())));
}
// process the content type response header
std::string contentTypeValue = winrt::to_string(responseMessage.Content().Headers().ContentType().ToString());
std::string contentTypeKey = "content-type";
m_headers.insert(std::make_pair(contentTypeKey, contentTypeValue));

switch (m_responseType)
{
Expand Down