| 464 | |
| 465 | |
| 466 | void HTTPHandler::processQuery( |
| 467 | ContextMutablePtr context, |
| 468 | HTTPServerRequest & request, |
| 469 | HTMLForm & params, |
| 470 | HTTPServerResponse & response, |
| 471 | Output & used_output, |
| 472 | std::optional<CurrentThread::QueryScope> & query_scope) |
| 473 | { |
| 474 | using namespace Poco::Net; |
| 475 | |
| 476 | LOG_TRACE(log, "Request URI: {}", request.getURI()); |
| 477 | std::string tenant_id = params.getParsed<std::string>("tenant_id", ""); |
| 478 | std::string database = request.get("X-ClickHouse-Database", ""); |
| 479 | if (database.empty()) |
| 480 | database = params.getParsed<std::string>("database", ""); |
| 481 | |
| 482 | if (auto pos = database.find('`'); pos != String::npos) |
| 483 | { |
| 484 | //CNCH multi-tenant default database pattern from gateway client: {tenant_id}`{default_database} |
| 485 | //Even this is a GET request or with "readonly=1" setting, we force to apply the tenant_id setting change. |
| 486 | auto tenant_id_from_db = String(database.c_str(), pos); |
| 487 | if (tenant_id.empty()) |
| 488 | tenant_id = tenant_id_from_db; |
| 489 | else if (tenant_id != tenant_id_from_db && !tenant_id_from_db.empty()) |
| 490 | throw Exception("tenant id " + tenant_id + " from setting doesn't match tenant id from database " + tenant_id_from_db, ErrorCodes::UNKNOWN_USER); |
| 491 | |
| 492 | ///multi-tenant default database storage pattern: {tenant_id}.{database} |
| 493 | if (pos + 1 != database.size()) |
| 494 | { |
| 495 | auto sub_str = database.substr(pos + 1); |
| 496 | if (sub_str == "default" || sub_str == "system") |
| 497 | database = std::move(sub_str); |
| 498 | else |
| 499 | database[pos] = '.'; |
| 500 | } |
| 501 | else /// {tenant_id}` |
| 502 | database.clear(); |
| 503 | } |
| 504 | |
| 505 | if (!database.empty()) |
| 506 | context->setCurrentDatabase(database); |
| 507 | |
| 508 | if (!tenant_id.empty()) |
| 509 | { |
| 510 | context->setSetting("tenant_id", tenant_id); |
| 511 | context->setTenantId(tenant_id); |
| 512 | } |
| 513 | |
| 514 | if (!authenticateUser(context, request, params, response)) |
| 515 | return; // '401 Unauthorized' response with 'Negotiate' has been sent at this point. |
| 516 | |
| 517 | /// The user could specify session identifier and session timeout. |
| 518 | /// It allows to modify settings, create temporary tables and reuse them in subsequent requests. |
| 519 | |
| 520 | std::shared_ptr<NamedSession> session; |
| 521 | String session_id; |
| 522 | bool session_is_set = params.has("session_id"); |
| 523 | const auto & config = server.config(); |
nothing calls this directly
no test coverage detected