Newer
Older
bremer-ios-app / Pods / Realm / core / realm-monorepo.xcframework / macos-x86_64_arm64 / Headers / realm / object-store / sync / generic_network_transport.hpp
////////////////////////////////////////////////////////////////////////////
//
// Copyright 2020 Realm Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or utilied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////

#ifndef REALM_GENERIC_NETWORK_TRANSPORT_HPP
#define REALM_GENERIC_NETWORK_TRANSPORT_HPP

#include <realm/exceptions.hpp>
#include <realm/util/functional.hpp>
#include <realm/util/optional.hpp>

#include <iosfwd>
#include <map>
#include <memory>
#include <string>
#include <vector>

namespace realm::app {

struct AppError : public RuntimeError {
    util::Optional<int> additional_status_code;

    std::string link_to_server_logs;

    AppError(ErrorCodes::Error error_code, std::string message, std::string link = "",
             util::Optional<int> additional_error_code = util::none);

    bool is_json_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::json_error);
    }

    bool is_service_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::service_error);
    }

    bool is_http_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::http_error);
    }

    bool is_custom_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::custom_error);
    }

    bool is_client_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::client_error);
    }

    bool is_websocket_error() const
    {
        return ErrorCodes::error_categories(code()).test(ErrorCategory::websocket_error);
    }
};

std::ostream& operator<<(std::ostream& os, AppError error);

/**
 * An HTTP method type.
 */
enum class HttpMethod { get, post, patch, put, del };

/**
 * Request/Response headers type
 */
using HttpHeaders = std::map<std::string, std::string>;

/**
 * An HTTP request that can be made to an arbitrary server.
 */
struct Request {
    /**
     * The HTTP method of this request.
     */
    HttpMethod method = HttpMethod::get;

    /**
     * The URL to which this request will be made.
     */
    std::string url;

    /**
     * The number of milliseconds that the underlying transport should spend on an HTTP round trip before failing with
     * an error.
     */
    uint64_t timeout_ms = 0;

    /**
     * The HTTP headers of this request - keys are case insensitive.
     */
    HttpHeaders headers;

    /**
     * The body of the request.
     */
    std::string body;

    /// Indicates if the request uses the refresh token or the access token
    bool uses_refresh_token = false;

    /**
     * A recursion counter to prevent too many redirects
     */
    int redirect_count = 0;
};

/**
 * The contents of an HTTP response.
 */
struct Response {
    /**
     * The status code of the HTTP response.
     */
    int http_status_code;

    /**
     * A custom status code provided by the language binding (SDK).
     */
    int custom_status_code;

    /**
     * The headers of the HTTP response - keys are case insensitive.
     */
    HttpHeaders headers;

    /**
     * The body of the HTTP response.
     */
    std::string body;

    /**
     * An error code used by the client to report http processing errors.
     */
    util::Optional<ErrorCodes::Error> client_error_code;
};

/// Generic network transport for foreign interfaces.
struct GenericNetworkTransport {
    virtual ~GenericNetworkTransport() = default;
    virtual void send_request_to_server(const Request& request,
                                        util::UniqueFunction<void(const Response&)>&& completion) = 0;

    void send_request_to_server(Request&& request,
                                util::UniqueFunction<void(Request&&, const Response&)>&& completion)
    {
        auto request_ptr = std::make_unique<Request>(std::move(request));
        const auto& request_ref = *request_ptr;
        send_request_to_server(request_ref, [request_ptr = std::move(request_ptr),
                                             completion = std::move(completion)](const Response& response) {
            completion(std::move(*request_ptr), response);
        });
    }
};

const char* httpmethod_to_string(HttpMethod method);

} // namespace realm::app

#endif /* REALM_GENERIC_NETWORK_TRANSPORT_HPP */