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

Reconstruct app url after a migration #5743

Merged
merged 26 commits into from
Sep 20, 2022
Merged

Conversation

michael-wb
Copy link
Contributor

@michael-wb michael-wb commented Aug 13, 2022

What, How & Why?

Updated Realm::App::do_request() to handle redirect (301) responses from the server to update the server url to the hostname provided in the "Location" header string.

This change required updating the callback argument for GenericNetworkTransport::send_request_to_server() to receive both the original Request and Response objects (SDK breaking change). The C-API was not affected since the completion_data pointer is now a struct that contains both the original Request and the callback function.

This change required numerous updates to the tests and all tests were passing before committing (on MacOS).

Added tests to verify redirect response handling.

☑️ ToDos

  • 📝 Changelog update
  • 🚦 Tests (or not relevant)
  • C-API, if public C++ API changed.

@michael-wb michael-wb self-assigned this Aug 13, 2022
@cla-bot cla-bot bot added the cla: yes label Aug 13, 2022
@michael-wb michael-wb linked an issue Aug 15, 2022 that may be closed by this pull request
@michael-wb michael-wb force-pushed the mwb/reconstruct-app-url branch from 4a4bab8 to 583c473 Compare August 15, 2022 16:43
@michael-wb michael-wb changed the title Handle redirect (301) server responses to update the server URL and resend the request to the new host Reconstruct app url after a migration Aug 15, 2022
Copy link
Contributor

@jbreams jbreams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First pass of comments. Looks like a good start!

src/realm/object-store/c_api/http.cpp Outdated Show resolved Hide resolved
src/realm/object-store/c_api/http.cpp Outdated Show resolved Hide resolved
src/realm/object-store/c_api/http.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
@michael-wb michael-wb force-pushed the mwb/reconstruct-app-url branch 2 times, most recently from d4e7fa8 to 72038c8 Compare August 24, 2022 14:30
@michael-wb michael-wb force-pushed the mwb/reconstruct-app-url branch from 72038c8 to 403b5bf Compare August 25, 2022 16:50
@michael-wb michael-wb requested a review from jbreams August 26, 2022 13:56
Copy link
Contributor

@jbreams jbreams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still looking through the tests, but here are some minor comments from a first pass. Good start!

src/realm/object-store/c_api/http.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/generic_network_transport.hpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/generic_network_transport.hpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/app_utils.cpp Outdated Show resolved Hide resolved
src/realm/object-store/sync/generic_network_transport.cpp Outdated Show resolved Hide resolved
@michael-wb michael-wb requested a review from jbreams September 12, 2022 21:02
Copy link
Contributor

@jbreams jbreams left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking good. Just a few more comments/questions/suggestions.

CHANGELOG.md Outdated
* Syncing of a Decimal128 with big significand could result in a crash. ([#5728](https://github.com/realm/realm-core/issues/5728))
* Recovery/discardLocal client reset modes will now wait for FLX sync realms to be fully synchronized before beginning recovery operations ([#5705](https://github.com/realm/realm-core/issues/5705))

### Breaking changes
* None.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you put this line back?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how it got deleted... must've done it by accident

/**
* A recursion counter to prevent too many redirects
*/
util::Optional<size_t> max_redirects;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rename this something like redirect_count? max_redirects sounds like this is the limit we're working towards rather than how many redirects we've processed so far.

also, i think this can just be a regular int rather than a util::Optional<size_t>, and we can set its default value to zero. a redirect count of zero seems to have the same semantic meaning as an empty counter (at least in my opinion).

sc_config.metadata_mode = realm::SyncManager::MetadataMode::NoEncryption;

// initialize app and sync client
std::shared_ptr<realm::app::App> redir_app = app::App::get_uncached_app(app_config, sc_config);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can just do auto redir_app = here.

util::try_make_dir(base_file_path);
SyncClientConfig sc_config;
sc_config.base_file_path = base_file_path;
sc_config.log_level = TEST_ENABLE_SYNC_LOGGING ? util::Logger::Level::all : util::Logger::Level::off;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use this define https://github.com/realm/realm-core/blob/master/test/object-store/util/test_file.hpp#L228 to setup the log level if you've included test_file.hpp already.

TEST_CASE("app: sync integration", "[sync][app]") {
auto logger = std::make_unique<util::StderrLogger>();
#if TEST_ENABLE_SYNC_LOGGING
logger->set_level_threshold(util::Logger::Level::all);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just use this define https://github.com/realm/realm-core/blob/master/test/object-store/util/test_file.hpp#L228 to setup the log level if you've included test_file.hpp already.

@@ -2062,7 +2241,7 @@ TEST_CASE("app: sync integration", "[sync][app]") {
// This assumes that we make an http request for the new token while
// already in the WaitingForAccessToken state.
bool seen_waiting_for_access_token = false;
transport->request_hook = [&](Request&) {
transport->request_hook = [&](Request&) -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you don't have to change this, but if a lambda returns a single type - i.e. you just add a return true to the end - you don't need to make the return type explicit.


update_hostname(m_sync_manager->app_metadata());
}
catch (const AppError&) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious what kind of AppError's we could catch here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parse and get functions throw an AppError with a JSONErrorCode if the operation fails. Since the only interface to the caller is a callback that takes a Response object, the failure will be determined (again) when the callback is run.

return completion(std::move(error)); // early return
}

if (request.max_redirects) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if max_redirects was just an int that defaults to zero, you could do

if (++request.redirect_count > max_http_redirects) {
   ... handle the error ...
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - I like that better

constexpr size_t https_len = std::char_traits<char>::length("https://");
auto new_url = location->second;
size_t split = new_url.find_first_of("/#?", https_len);
if (split != std::string::npos) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you could do

if (auto split = new_url.find_first_of("/#?", https_len); split != std::string::npos) {
    new_url.remove_suffix(new_url.size() - split);
}

});
// Update the metadata using the new location and replay the request with the updated hostname
// Trim off any trailing path/anchor/query string
constexpr size_t https_len = std::char_traits<char>::length("https://");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to make sure the URL starts with https:// before we use that? Maybe do:

std::string_view new_url = location->second;
if (auto scheme_end = new_url.find("://"); scheme_end != std::string_view::npos) {
    new_url.remove_prefix(scheme_end + std::char_traits<char>::length("://"));
}

Then new_url would be the url minus the initial scheme.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wanted to skip past the scheme and look for the first /, #, or ? after the hostname and trim just that part until the end.

@michael-wb michael-wb requested a review from jbreams September 16, 2022 13:10
@michael-wb michael-wb merged commit 53f292a into master Sep 20, 2022
@michael-wb michael-wb deleted the mwb/reconstruct-app-url branch September 20, 2022 20:04
@tgoyne tgoyne mentioned this pull request Sep 26, 2022
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 21, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Reconstruct app url after a migration
2 participants