Skip to content

Commit 8cf45b1

Browse files
committed
Add user-configurable timeout to wasm http requests
1 parent 5f536c5 commit 8cf45b1

File tree

7 files changed

+68
-2
lines changed

7 files changed

+68
-2
lines changed

CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ set(GIT2CPP_SRC
9898
${GIT2CPP_SOURCE_DIR}/utils/progress.hpp
9999
${GIT2CPP_SOURCE_DIR}/utils/terminal_pager.cpp
100100
${GIT2CPP_SOURCE_DIR}/utils/terminal_pager.hpp
101+
${GIT2CPP_SOURCE_DIR}/wasm/constants.hpp
101102
${GIT2CPP_SOURCE_DIR}/wasm/libgit2_internals.cpp
102103
${GIT2CPP_SOURCE_DIR}/wasm/libgit2_internals.hpp
103104
${GIT2CPP_SOURCE_DIR}/wasm/response.cpp
@@ -110,6 +111,8 @@ set(GIT2CPP_SRC
110111
${GIT2CPP_SOURCE_DIR}/wasm/subtransport.hpp
111112
${GIT2CPP_SOURCE_DIR}/wasm/transport.cpp
112113
${GIT2CPP_SOURCE_DIR}/wasm/transport.hpp
114+
${GIT2CPP_SOURCE_DIR}/wasm/utils.cpp
115+
${GIT2CPP_SOURCE_DIR}/wasm/utils.hpp
113116
${GIT2CPP_SOURCE_DIR}/wrapper/annotated_commit_wrapper.cpp
114117
${GIT2CPP_SOURCE_DIR}/wrapper/annotated_commit_wrapper.hpp
115118
${GIT2CPP_SOURCE_DIR}/wrapper/branch_wrapper.cpp

src/wasm/constants.hpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#pragma once
2+
3+
#include <string_view>
4+
5+
// Constants used in wasm transport layer.
6+
// Exposed to non-emscripten builds so that they can be used in help.
7+
8+
// Environment variable for http transport timeout.
9+
// Must be a positive number as a timeout of 0 will block forever.
10+
inline constexpr std::string_view WASM_HTTP_TRANSPORT_TIMEOUT_NAME = "GIT_HTTP_TIMEOUT";
11+
inline constexpr unsigned int WASM_HTTP_TRANSPORT_TIMEOUT_DEFAULT = 10;

src/wasm/stream.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ EM_JS(
4444
const char* method,
4545
const char* content_type_header,
4646
const char* authorization_header,
47+
unsigned long request_timeout_ms,
4748
size_t buffer_size),
4849
{
4950
const url_js = UTF8ToString(url);
@@ -65,6 +66,7 @@ EM_JS(
6566
// Should this only be set if using https? What about CORS via http?
6667
xhr.setRequestHeader("Authorization", authorization_header_js);
6768
}
69+
xhr.timeout = request_timeout_ms;
6870

6971
// Cache request info on JavaScript side so that it is available in subsequent calls
7072
// without having to pass it back and forth to/from C++.
@@ -257,6 +259,7 @@ static int create_request(wasm_http_stream* stream, std::string_view content_hea
257259
name_for_method(stream->m_service.m_method).c_str(),
258260
content_header.data(),
259261
stream->m_subtransport->m_authorization_header.c_str(),
262+
stream->m_subtransport->m_request_timeout_ms,
260263
EMFORGE_BUFSIZE
261264
);
262265
return stream->m_request_index;

src/wasm/subtransport.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22

33
# include "subtransport.hpp"
44

5+
# include <iostream>
56
# include <regex>
67
# include <sstream>
78

8-
# include <emscripten.h>
99
# include <git2/sys/credential.h>
1010
# include <git2/sys/remote.h>
1111

1212
# include "libgit2_internals.hpp"
1313
# include "stream.hpp"
14+
# include "utils.hpp"
1415

1516
// C functions.
1617

@@ -93,6 +94,7 @@ int create_wasm_http_subtransport(git_smart_subtransport** out, git_transport* o
9394
subtransport->m_owner = owner;
9495
subtransport->m_base_url = "";
9596
subtransport->m_credential = nullptr;
97+
subtransport->m_request_timeout_ms = get_request_timeout_ms();
9698

9799
*out = &subtransport->m_parent;
98100
return 0;

src/wasm/subtransport.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ struct wasm_http_subtransport
1717
// Data stored for reuse on other streams of this transport:
1818
std::string m_base_url;
1919
std::string m_authorization_header;
20-
git_credential* m_credential; // libgit2 creates this, we are responsible for deleting it.
20+
git_credential* m_credential; // libgit2 creates this, we are responsible for deleting it.
21+
unsigned long m_request_timeout_ms; // Timeout for http(s) requests in milliseconds.
2122
};
2223

2324
// git_smart_subtransport_cb

src/wasm/utils.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifdef EMSCRIPTEN
2+
3+
# include "utils.hpp"
4+
5+
# include <termcolor/termcolor.hpp>
6+
7+
# include "constants.hpp"
8+
9+
unsigned long get_request_timeout_ms()
10+
{
11+
double timeout_seconds = WASM_HTTP_TRANSPORT_TIMEOUT_DEFAULT;
12+
auto env_var = std::getenv(WASM_HTTP_TRANSPORT_TIMEOUT_NAME.data());
13+
if (env_var != nullptr)
14+
{
15+
try
16+
{
17+
auto value = std::stod(env_var);
18+
if (value <= 0)
19+
{
20+
throw std::runtime_error("negative or zero");
21+
}
22+
timeout_seconds = value;
23+
}
24+
catch (std::exception& e)
25+
{
26+
// Catch failures from (1) stod and (2) timeout <= 0.
27+
// Print warning and use default value.
28+
std::cout << termcolor::yellow << "Warning: environment variable "
29+
<< WASM_HTTP_TRANSPORT_TIMEOUT_NAME
30+
<< " must be a positive number of seconds, using default value of "
31+
<< WASM_HTTP_TRANSPORT_TIMEOUT_DEFAULT << " seconds instead." << termcolor::reset
32+
<< std::endl;
33+
}
34+
}
35+
return 1000 * timeout_seconds;
36+
}
37+
38+
#endif // EMSCRIPTEN

src/wasm/utils.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#pragma once
2+
3+
#ifdef EMSCRIPTEN
4+
5+
// Get wasm http request timeout in milliseconds from environment variable or default value.
6+
unsigned long get_request_timeout_ms();
7+
8+
#endif // EMSCRIPTEN

0 commit comments

Comments
 (0)