#ifndef SRC_NODE_URL_H_ #define SRC_NODE_URL_H_ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "node.h" #include namespace node { namespace url { #define PARSESTATES(XX) \ XX(kSchemeStart) \ XX(kScheme) \ XX(kNoScheme) \ XX(kSpecialRelativeOrAuthority) \ XX(kPathOrAuthority) \ XX(kRelative) \ XX(kRelativeSlash) \ XX(kSpecialAuthoritySlashes) \ XX(kSpecialAuthorityIgnoreSlashes) \ XX(kAuthority) \ XX(kHost) \ XX(kHostname) \ XX(kPort) \ XX(kFile) \ XX(kFileSlash) \ XX(kFileHost) \ XX(kPathStart) \ XX(kPath) \ XX(kCannotBeBase) \ XX(kQuery) \ XX(kFragment) #define FLAGS(XX) \ XX(URL_FLAGS_NONE, 0) \ XX(URL_FLAGS_FAILED, 0x01) \ XX(URL_FLAGS_CANNOT_BE_BASE, 0x02) \ XX(URL_FLAGS_INVALID_PARSE_STATE, 0x04) \ XX(URL_FLAGS_TERMINATED, 0x08) \ XX(URL_FLAGS_SPECIAL, 0x10) \ XX(URL_FLAGS_HAS_USERNAME, 0x20) \ XX(URL_FLAGS_HAS_PASSWORD, 0x40) \ XX(URL_FLAGS_HAS_HOST, 0x80) \ XX(URL_FLAGS_HAS_PATH, 0x100) \ XX(URL_FLAGS_HAS_QUERY, 0x200) \ XX(URL_FLAGS_HAS_FRAGMENT, 0x400) \ XX(URL_FLAGS_IS_DEFAULT_SCHEME_PORT, 0x800) \ enum url_parse_state { kUnknownState = -1, #define XX(name) name, PARSESTATES(XX) #undef XX }; enum url_flags { #define XX(name, val) name = val, FLAGS(XX) #undef XX }; struct url_data { int32_t flags = URL_FLAGS_NONE; int port = -1; std::string scheme; std::string username; std::string password; std::string host; std::string query; std::string fragment; std::vector path; }; class URL { public: static void Parse(const char* input, size_t len, enum url_parse_state state_override, struct url_data* url, bool has_url, const struct url_data* base, bool has_base); URL(const char* input, const size_t len) { Parse(input, len, kUnknownState, &context_, false, nullptr, false); } URL(const char* input, const size_t len, const URL* base) { if (base != nullptr) Parse(input, len, kUnknownState, &context_, false, &(base->context_), true); else Parse(input, len, kUnknownState, &context_, false, nullptr, false); } URL(const char* input, const size_t len, const char* base, const size_t baselen) { if (base != nullptr && baselen > 0) { URL _base(base, baselen); Parse(input, len, kUnknownState, &context_, false, &(_base.context_), true); } else { Parse(input, len, kUnknownState, &context_, false, nullptr, false); } } explicit URL(const std::string& input) : URL(input.c_str(), input.length()) {} URL(const std::string& input, const URL* base) : URL(input.c_str(), input.length(), base) {} URL(const std::string& input, const URL& base) : URL(input.c_str(), input.length(), &base) {} URL(const std::string& input, const std::string& base) : URL(input.c_str(), input.length(), base.c_str(), base.length()) {} int32_t flags() { return context_.flags; } int port() { return context_.port; } const std::string& protocol() const { return context_.scheme; } const std::string& username() const { return context_.username; } const std::string& password() const { return context_.password; } const std::string& host() const { return context_.host; } const std::string& query() const { return context_.query; } const std::string& fragment() const { return context_.fragment; } std::string path() const { std::string ret; for (const std::string& element : context_.path) { ret += '/' + element; } return ret; } // Get the path of the file: URL in a format consumable by native file system // APIs. Returns an empty string if something went wrong. std::string ToFilePath() const; // Get the file URL from native file system path. static URL FromFilePath(const std::string& file_path); v8::MaybeLocal ToObject(Environment* env) const; URL(const URL&) = default; URL& operator=(const URL&) = default; URL(URL&&) = default; URL& operator=(URL&&) = default; URL() : URL("") {} private: struct url_data context_; }; } // namespace url } // namespace node #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #endif // SRC_NODE_URL_H_