| 230 | |
| 231 | |
| 232 | Try<URL> URL::parse(const string& urlString) |
| 233 | { |
| 234 | // TODO(tnachen): Consider using C++11 regex support instead. |
| 235 | |
| 236 | size_t schemePos = urlString.find("://"); |
| 237 | if (schemePos == string::npos) { |
| 238 | return Error("Missing scheme in url string"); |
| 239 | } |
| 240 | |
| 241 | const string scheme = strings::lower(urlString.substr(0, schemePos)); |
| 242 | const string urlPath = urlString.substr(schemePos + 3); |
| 243 | |
| 244 | size_t pathPos = urlPath.find_first_of('/'); |
| 245 | if (pathPos == 0) { |
| 246 | return Error("Host not found in url"); |
| 247 | } |
| 248 | |
| 249 | // If path is specified in the URL, try to capture the host and path |
| 250 | // separately. |
| 251 | string host = urlPath; |
| 252 | string path = "/"; |
| 253 | if (pathPos != string::npos) { |
| 254 | host = host.substr(0, pathPos); |
| 255 | path = urlPath.substr(pathPos); |
| 256 | } |
| 257 | |
| 258 | if (host.empty()) { |
| 259 | return Error("Host not found in url"); |
| 260 | } |
| 261 | |
| 262 | const vector<string> tokens = strings::tokenize(host, ":"); |
| 263 | |
| 264 | if (tokens[0].empty()) { |
| 265 | return Error("Host not found in url"); |
| 266 | } |
| 267 | |
| 268 | if (tokens.size() > 2) { |
| 269 | return Error("Found multiple ports in url"); |
| 270 | } |
| 271 | |
| 272 | Option<uint16_t> port; |
| 273 | if (tokens.size() == 2) { |
| 274 | Try<uint16_t> numifyPort = numify<uint16_t>(tokens[1]); |
| 275 | if (numifyPort.isError()) { |
| 276 | return Error("Failed to parse port: " + numifyPort.error()); |
| 277 | } |
| 278 | |
| 279 | port = numifyPort.get(); |
| 280 | } else { |
| 281 | // Attempt to resolve the port based on the URL scheme. |
| 282 | port = defaultPort(scheme); |
| 283 | } |
| 284 | |
| 285 | if (port.isNone()) { |
| 286 | return Error("Unable to determine port from url"); |
| 287 | } |
| 288 | |
| 289 | // TODO(tnachen): Support parsing query and fragment. |
nothing calls this directly
no test coverage detected