Cria um handler HTTP personalizado definido em SQL, sem editar o arquivo de configuração do servidor. Os handlers definidos em SQL são uma alternativa aos handlers de interface HTTP.
Cria um handler com o name especificado. O nome é usado para gerenciar handlers por meio de consultas SQL, em mensagens de diagnóstico e para ordená-los.
PROTOCOL — opcional. Se um nome de protocolo for especificado, o handler ficará ativo apenas para o protocolo componível indicado. Caso contrário, ficará ativo em todos os endpoints HTTP: as portas integradas http/https e todos os listeners de protocolo componível do tipo HTTP. PROTOCOL ANY seleciona explicitamente esse comportamento padrão; em ALTER HANDLER, remove uma restrição de protocolo definida anteriormente. Um protocolo chamado literalmente any pode ser referenciado com crases: PROTOCOL `any` .
URL — obrigatória. Pode ser uma URL exata, um URL PREFIX ou um URL REGEXP. Para URLs exatas e prefixos, a ambiguidade é verificada no momento da criação ou alteração, e uma exceção é lançada se houver ambiguidade. Para regexp, a ambiguidade não pode ser verificada. A URL é comparada sem a string de consulta ? nem o identificador de fragmento #. Um URL PREFIX é comparado como um caminho base, no limite de um segmento de caminho — com a mesma semântica da regra url_prefix dos handlers definidos na configuração: URL PREFIX '/api/v1' corresponde a /api/v1, /api/v1/ e /api/v1/write, mas não a /api/v1beta. A / final do prefixo é ignorada, portanto '/api/v1/' e '/api/v1' têm o mesmo comportamento.
METHODS — opcional. A lista de métodos HTTP permitidos. Por padrão, é apenas GET. Os métodos compatíveis são GET, POST, PUT e DELETE. Os métodos que modificam dados, POST, PUT e DELETE, podem executar consultas modificadoras; os métodos seguros, como GET e HEAD, são sempre executados no modo readonly. Consequentemente, um handler cuja consulta modifica dados (por exemplo, INSERT ou DDL) deve permitir pelo menos um método que modifica dados — criar esse handler apenas com métodos somente leitura (por exemplo, o GET padrão) lança uma exceção. Consultas cujos efeitos colaterais persistem no modo readonly são um caso especial: BACKUP e RESTORE têm efeitos colaterais duradouros; as instruções que alteram a sessão SET, SET ROLE, USE, BEGIN TRANSACTION, COMMIT, ROLLBACK e SET TRANSACTION SNAPSHOT alteram o estado da sessão ou da transação, que persiste entre solicitações quando session_id está em uso; e CREATE TEMPORARY TABLE / CREATE TEMPORARY VIEW criam um objeto que existe durante a sessão — ainda assim, o modo readonly dos métodos seguros não bloqueia nenhum deles. As mutações de uma tabela temporária existente também não são bloqueadas pelo modo readonly; por isso, consultas que possam ter uma tabela temporária como destino são tratadas da mesma forma: um INSERT cuja tabela de destino não seja qualificada com um banco de dados (um nome não qualificado pode ser resolvido como uma tabela temporária da sessão), um DROP TEMPORARY TABLE, um DROP TABLE / TRUNCATE TABLE de uma tabela não qualificada com um banco de dados e um ALTER de uma tabela não qualificada com um banco de dados (ALTER TEMPORARY TABLE é a mesma instrução). Um destino qualificado com banco de dados nunca pode ser uma tabela temporária; portanto, essas consultas não estão sujeitas a essa regra. O HTTP exige que os métodos seguros não tenham efeitos colaterais (um handler declarado para GET também atende a HEAD, no qual o corpo da resposta é suprimido e o efeito seria invisível). Portanto, um handler que execute esse tipo de consulta deve listar apenas métodos que modificam dados — criá-lo ou alterá-lo para incluir um método seguro lança uma exceção. As instruções compostas são analisadas internamente: para statement1 PARALLEL WITH statement2 ... e EXECUTE AS <user> <statement>, as regras acima se aplicam às instruções encapsuladas, pois são elas que são executadas (cada uma em uma cópia do contexto do handler, que mantém o modo readonly). Um EXECUTE AS <user> sem instrução faz com que toda a sessão seja executada como outro usuário; portanto, conta como uma alteração de sessão por si só. Além disso, qualquer handler EXECUTE AS — sem instrução ou encapsulando uma instrução — deve permitir pelo menos um método que modifica dados: a personificação exige o privilégio IMPERSONATE, que o modo readonly dos métodos seguros nega.
TYPE — opcional. Por enquanto, o único tipo compatível é query.
AS — a consulta SQL que será invocada por este manipulador. A consulta pode ser parametrizada. Sua correção sintática é verificada durante a criação ou alteração do manipulador, mas ela não é analisada semanticamente — por exemplo, as tabelas às quais a consulta faz referência podem não existir no momento da criação do manipulador. As cláusulas FORMAT e semelhantes pertencem à consulta, não à instrução CREATE/ALTER como um todo. A consulta pode ser colocada entre parênteses para eliminar ambiguidades. Uma consulta INSERT não pode conter dados inline após a cláusula VALUES ou FORMAT — a criação ou alteração desse manipulador lança uma exceção, pois o payload inline não pode ser preservado na definição do manipulador; espera-se que os dados sejam fornecidos no corpo da requisição HTTP (ou calculados por um INSERT ... SELECT). Uma requisição para um manipulador cuja consulta lê o corpo — um INSERT que recebe seus dados do corpo ou uma consulta que usa o parâmetro _request_body — deve declarar seu tamanho: uma requisição não fragmentada sem o cabeçalho Content-Length recebe a resposta 411 Length Required, pois, caso contrário, o corpo seria lido até o fim do fluxo, e uma conexão interrompida seria aceita como uma requisição completa. Todos os métodos desse manipulador também devem permitir corpo (POST, PUT ou DELETE) — criá-lo com um método seguro na cláusula METHODS (por exemplo, o GET padrão) lança uma exceção, pois um método seguro nunca fornece um corpo de requisição e a consulta leria silenciosamente um corpo vazio; um GET declarado também atende a HEAD, portanto misturar métodos seguros com métodos que permitem corpo manteria essas invocações acessíveis. Um INSERT ... SELECT não lê o corpo (seus dados vêm do SELECT), portanto não está sujeito a esses requisitos — exceto se o SELECT ler da função de tabela input, que é alimentada pelo corpo da requisição. Um INSERT que lê o corpo deve ser a própria consulta do manipulador: EXECUTE AS e PARALLEL WITH executam as instruções que encapsulam sem o corpo da requisição; portanto, encapsulá-lo em um deles é rejeitado na criação, em vez de descartar silenciosamente cada upload. Uma consulta que lê o corpo também não pode usar o parâmetro _request_body: há um único corpo de requisição, e a vinculação de _request_body o consome antes que a consulta leia seus dados de entrada; portanto, esse manipulador é rejeitado na criação, em vez de perder silenciosamente cada upload — use a entrada de corpo da própria consulta ou _request_body, mas não ambos. Manipuladores que não leem o corpo não têm esse requisito; o corpo de uma requisição para esse tipo de manipulador é ignorado e nunca é anexado à consulta do manipulador. O texto da consulta armazenada é analisado novamente pelo servidor com profundidade do analisador e número de retrocessos ilimitados sempre que o manipulador é recarregado ou invocado; assim, um manipulador criado em uma sessão com max_parser_depth / max_parser_backtracks elevados continua podendo ser carregado e invocado sob limites normais de sessão.
Os handlers definidos na configuração do servidor têm prioridade sobre os handlers definidos em SQL. Os handlers definidos em SQL são correspondidos em ordem lexicográfica pelos respectivos nomes.
Os parâmetros de consulta para consultas parametrizadas são fornecidos, assim como para handlers definidos na configuração, a partir de:
- parâmetros de URL HTTP na string de consulta, usando a convenção
param_<name> (por exemplo, ?param_id=42 associa {id:Type});
- grupos de captura nomeados em uma
URL REGEXP (por exemplo, URL REGEXP '/users/(?P<id>\d+)' associa {id:Type});
- campos de formulário do corpo da requisição, para um handler cuja consulta declara parâmetros: um corpo
application/x-www-form-urlencoded (por exemplo, curl -d 'param_id=42') e os campos de um corpo multipart/form-data associam parâmetros {name:Type} da mesma forma que os parâmetros de URL, nos métodos que aceitam corpo POST, PUT e DELETE. Um parâmetro presente tanto na URL quanto no corpo assume o valor da URL. Um corpo analisado como formulário é consumido pela camada do handler: ele não é enviado à consulta como dados de INSERT. Um handler cujo único uso do corpo é _request_body recebe o corpo bruto em vez de analisá-lo como formulário; um handler que declara _request_body junto com outros parâmetros recebe ambos — uma cópia do corpo bruto, não analisado, é preservada em _request_body (sujeita a http_max_request_param_data_size) antes que o corpo seja analisado como formulário.
Os cabeçalhos HTTP padrão do ClickHouse (como X-ClickHouse-Database, X-ClickHouse-User e X-ClickHouse-Key) são tratados normalmente ao invocar um handler.
As funções currentHandler e currentRequestURL podem ser usadas para personalizar o comportamento da consulta de acordo com o handler invocado e a URL da requisição.
CREATE HANDLER, DROP HANDLER e ALTER HANDLER exigem as permissões CREATE HANDLER, DROP HANDLER e ALTER HANDLER, respectivamente.
A leitura da tabela system.handlers exige a permissão SHOW HANDLERS. Os Secrets que podem estar embutidos na consulta de um handler são mascarados nessa tabela, a menos que o usuário também tenha permissão para visualizar Secrets (consulte system.handlers).
A invocação de um handler não exige uma permissão específica, mas as permissões são verificadas normalmente durante a execução da consulta, e a autenticação funciona como de costume. Para encapsular o acesso a determinadas consultas, crie uma VIEW com SQL SECURITY DEFINER e defina um handler que execute uma instrução SELECT nessa view.
Os handlers são armazenados em um armazenamento local ou no Keeper, de forma semelhante às named collections, configurado na seção query_rules_storage do arquivo de configuração:
Com o armazenamento Keeper, os handlers são automaticamente mantidos em sincronia em todas as réplicas. Portanto, uma cláusula ON CLUSTER explícita é redundante e faria com que cada réplica tentasse criar o mesmo handler. Habilite a configuração ignore_on_cluster_for_replicated_handler_queries para que CREATE, ALTER e DROP HANDLER ignorem ON CLUSTER quando o armazenamento for replicado, espelhando ignore_on_cluster_for_replicated_named_collections_queries.
Substitui o handler por outro. A consulta ALTER pode incluir apenas um subconjunto de cláusulas; por exemplo, pode ser usada para alterar somente a URL ou a consulta. As cláusulas não especificadas mantêm seus valores anteriores. PROTOCOL ANY remove uma restrição de protocolo existente, reativando o handler em todos os endpoints HTTP.
Remove o handler com o nome especificado.
A tabela system.handlers lista todos os handlers definidos em SQL. A tabela system.query_log registra, nas colunas http_handler_name e http_request_url, o nome do handler e o caminho da requisição HTTP (sem a string de consulta) de cada consulta.
Um handler parametrizado com uma URL Regexp:
CREATE HANDLER faz parte da família de instruções CREATE e está relacionado às instruções ALTER e DROP. Última modificação em 27 de agosto de 2026