> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

> Documentação de CREATE HANDLER

# CREATE HANDLER

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](/docs/pt-BR/concepts/features/interfaces/http).

<div id="syntax">
  ## Sintaxe
</div>

```sql theme={null}
CREATE HANDLER [IF NOT EXISTS] name [ON CLUSTER cluster]
[PROTOCOL protocol_name|ANY]
URL [PREFIX|REGEXP] '/path'
[METHODS (GET, POST)]
[TYPE query]
AS [SELECT|INSERT|...] ...
```

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.

<div id="clauses">
  ## Cláusulas
</div>

* `PROTOCOL` — opcional. Se um nome de protocolo for especificado, o handler ficará ativo apenas para o [protocolo componível](/docs/pt-BR/concepts/features/configuration/server-config/composable-protocols) indicado. Caso contrário, ficará ativo em todos os endpoints HTTP: as portas integradas `http`/`https` e todos os listeners de [protocolo componível](/docs/pt-BR/concepts/features/configuration/server-config/composable-protocols) 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](/docs/pt-BR/concepts/features/interfaces/http): `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.

<div id="priority">
  ## Priority
</div>

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.

<div id="parameters">
  ## Parâmetros
</div>

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`](/docs/pt-BR/reference/functions/regular-functions/other-functions#currentHandler) e [`currentRequestURL`](/docs/pt-BR/reference/functions/regular-functions/other-functions#currentRequestURL) podem ser usadas para personalizar o comportamento da consulta de acordo com o handler invocado e a URL da requisição.

<div id="access-control">
  ## Controle de acesso
</div>

`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`](/docs/pt-BR/reference/system-tables/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`](/docs/pt-BR/reference/system-tables/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`](/docs/pt-BR/reference/statements/create/view#sql_security) e defina um handler que execute uma instrução SELECT nessa view.

<div id="storage">
  ## Armazenamento
</div>

Os handlers são armazenados em um armazenamento local ou no Keeper, de forma semelhante às [named collections](/docs/pt-BR/concepts/features/configuration/server-config/named-collections), configurado na seção `query_rules_storage` do arquivo de configuração:

```xml theme={null}
<query_rules_storage>
    <type>local</type> <!-- or zookeeper -->
    <path>/var/lib/clickhouse/handlers/</path>
</query_rules_storage>
```

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`.

<div id="alter-handler">
  ## ALTER HANDLER
</div>

```sql theme={null}
ALTER HANDLER name
[PROTOCOL protocol_name|ANY]
[URL [PREFIX|REGEXP] '/path']
[METHODS (GET, POST)]
[TYPE query]
[AS SELECT ...]
```

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.

<div id="drop-handler">
  ## DROP HANDLER
</div>

```sql theme={null}
DROP HANDLER [IF EXISTS] name
```

Remove o handler com o nome especificado.

<div id="introspection">
  ## Introspecção
</div>

A tabela [`system.handlers`](/docs/pt-BR/reference/system-tables/handlers) lista todos os handlers definidos em SQL. A tabela [`system.query_log`](/docs/pt-BR/reference/system-tables/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.

<div id="example">
  ## Exemplo
</div>

```sql theme={null}
CREATE HANDLER my_handler URL '/my_handler' AS SELECT version();
```

```bash theme={null}
$ curl 'http://localhost:8123/my_handler'
```

Um handler parametrizado com uma URL Regexp:

```sql theme={null}
CREATE HANDLER get_user URL REGEXP '/users/(?P<id>\d+)' AS SELECT * FROM users WHERE id = {id:UInt64};
```

```bash theme={null}
$ curl 'http://localhost:8123/users/42'
```

<div id="related-statements">
  ## Instruções relacionadas
</div>

`CREATE HANDLER` faz parte da família de instruções `CREATE` e está relacionado às instruções `ALTER` e `DROP`.
