Aleph expõe dados da rede como um fluxo Manifold, que pode ser facilmente transformado em java.io.InputStream
, canal core.async, sequência Clojure ou muitas outras representações de bytes. Ele expõe wrappers padrão simples para HTTP, TCP e UDP, mas permite acesso ao desempenho total e à flexibilidade da biblioteca Netty subjacente.
Leiningen:
[aleph " 0.8.2 " ]
deps.edn:
aleph/aleph { :mvn/version " 0.8.2 " }
; ; alternatively
io.github.clj-commons/aleph { :git/sha " ... " }
Aleph segue totalmente as especificações do Ring e pode ser um substituto imediato para qualquer servidor compatível com Ring existente. No entanto, também permite que a função manipuladora retorne um Manifold adiado para representar uma resposta eventual. Esse recurso pode não funcionar bem com o middleware Ring síncrono, que modifica a resposta, mas isso pode ser facilmente corrigido reimplementando o middleware usando o operador let-flow do Manifold. O auxiliar aleph.http/wrap-ring-async-handler
pode ser usado para converter o manipulador de anel assíncrono de 3 aridades em compatível com Aleph.
( require '[aleph.http :as http])
( defn handler [req]
{ :status 200
:headers { " content-type " " text/plain " }
:body " hello! " })
( http/start-server handler { :port 8080 }) ; HTTP/1-only
; ; To support HTTP/2, do the following:
; ; (def my-ssl-context ...)
( http/start-server handler { :port 443
:http-versions [ :http2 :http1 ]
:ssl-context my-ssl-context})
; ; See aleph.examples.http2 for more details
O corpo da resposta também pode ser um fluxo múltiplo, onde cada mensagem do fluxo é enviada como um pedaço, permitindo controle preciso sobre as respostas transmitidas para eventos enviados pelo servidor e outros fins.
Para solicitações de clientes HTTP, Aleph se modela após clj-http, exceto que cada solicitação retorna imediatamente um Manifold adiado representando a resposta.
( require
'[aleph.http :as http]
'[manifold.deferred :as d]
'[clj-commons.byte-streams :as bs])
( -> @( http/get " https://google.com/ " )
:body
bs/to-string
prn)
( d/chain ( http/get " https://google.com " )
:body
bs/to-string
prn)
; ; To support HTTP/2, do the following:
( def conn-pool
( http/connection-pool { :connection-options { :http-versions [ :http2 :http1 ]}}))
@( http/get " https://google.com " { :pool conn-pool})
; ; See aleph.examples.http2 for more details
Aleph tenta imitar totalmente a API e os recursos clj-http. Ele suporta solicitações multipart/form-data, armazenamentos de cookies, servidores proxy e inspeção de solicitações com algumas diferenças notáveis:
a configuração de proxy deve ser definida para a conexão ao configurar um pool de conexões; configurações de proxy por solicitação não são permitidas
A funcionalidade do proxy HTTP é estendida com configurações de tunelamento, cabeçalhos HTTP opcionais e controle de tempo limite de conexão, veja todas as chaves de configuração
:proxy-ignore-hosts
não é suportado
tanto o middleware de cookies quanto os armazenamentos de cookies integrados não suportam parâmetros de cookies obsoletos desde RFC2965: comentário, URL de comentário, descarte, versão (veja a estrutura completa do cookie)
ao usar :debug
, :save-request?
e :debug-body?
opções, as solicitações correspondentes seriam armazenadas nas chaves :aleph/netty-request
, :aleph/request
, :aleph/request-body
do mapa de resposta
A opção :response-interceptor
não é suportada
Aleph apresenta a configuração do pool de conexões :log-activity
para ativar o registro das alterações de status das conexões, bem como despejos hexadecimais de solicitações/respostas
As opções :cache
e :cache-config
não são suportadas por enquanto
O cliente Aleph também suporta resolvedor DNS totalmente assíncrono e altamente personalizável.
Para saber mais, leia o código de exemplo.
A partir da versão 0.7.0, Aleph suporta HTTP/2 tanto no cliente quanto no servidor.
Na maior parte, o suporte HTTP/2 do Aleph é um substituto imediato para HTTP/1. Porém, para compatibilidade com versões anteriores, o padrão Aleph é apenas HTTP/1. Veja o exemplo de código HTTP/2 para uma boa visão geral sobre como começar a usar HTTP/2.
Coisas para estar ciente:
pipeline-transform
para alterar o pipeline Netty subjacente, você precisará verificar seu uso para HTTP/2. Nos bastidores, o novo código HTTP/2 usa a configuração de pipeline multiplexado do Netty, com um pipeline de nível de conexão compartilhado que alimenta quadros específicos de fluxo para N pipelines criados para N fluxos individuais. (Um par de solicitação/resposta HTTP padrão é mapeado para um único fluxo H2.) Em qualquer solicitação HTTP que tenha os cabeçalhos Upgrade
adequados, você pode chamar (aleph.http/websocket-connection req)
, que retorna um deferred que produz um duplex stream , que usa um único stream para representar a comunicação bidirecional. Mensagens do cliente podem ser recebidas via take!
, e enviado ao cliente via put!
. Um manipulador echo WebSocket, então, consistiria apenas em:
( require '[manifold.stream :as s])
( defn echo-handler [req]
( let [s @( http/websocket-connection req)]
( s/connect s s)))
Isso pega todas as mensagens do cliente e as devolve ao soquete duplex, retornando-as ao cliente. Mensagens de texto WebSocket serão emitidas como strings e mensagens binárias como matrizes de bytes.
Os clientes WebSocket podem ser criados via (aleph.http/websocket-client url)
, que retorna um adiado que produz um fluxo duplex que pode enviar e receber mensagens do servidor.
Para saber mais, leia o código de exemplo.
Um servidor TCP é semelhante a um servidor HTTP, exceto que para cada conexão o manipulador recebe dois argumentos: um fluxo duplex e um mapa contendo informações sobre o cliente. O fluxo emitirá matrizes de bytes, que podem ser forçadas a outras representações de bytes usando a biblioteca byte-streams. O fluxo aceitará quaisquer mensagens que possam ser coagidas a uma representação binária.
Um servidor echo TCP é muito semelhante ao exemplo de WebSocket acima:
( require '[aleph.tcp :as tcp])
( defn echo-handler [s info]
( s/connect s s))
( tcp/start-server echo-handler { :port 10001 })
Um cliente TCP pode ser criado via (aleph.tcp/client {:host "example.com", :port 10001})
, que retorna um adiado que produz um fluxo duplex.
Para saber mais, leia o código de exemplo.
Um soquete UDP pode ser gerado usando (aleph.udp/socket {:port 10001, :broadcast? false})
. Se :port
for especificado, produzirá um soquete duplex que pode ser usado para enviar e receber mensagens, que são estruturadas como mapas com os seguintes dados:
{ :host " example.com "
:port 10001
:message ...}
Onde os pacotes recebidos terão uma :message
que é uma matriz de bytes, que pode ser coagida usando byte-streams
, e os pacotes de saída podem ser quaisquer dados que possam ser coagidos para uma representação binária. Se nenhum :port
for especificado, o soquete só poderá ser usado para enviar mensagens.
Para saber mais, leia o código de exemplo.
Aleph usa Leiningen para gerenciar dependências, executar REPLs e testes e construir o código.
O suporte mínimo tools.deps
está disponível na forma de um arquivo deps.edn
que é gerado a partir de project.clj
. Ele fornece apenas o suficiente para poder usar Aleph como uma dependência git ou :local/root
. Ao confirmar alterações em project.clj
, execute deps/lein-to-deps
e confirme as alterações resultantes também.
Direitos autorais © 2010-2024 Zachary Tellman
Distribuído sob a licença MIT.
Muito obrigado ao YourKit por apoiar Aleph. YourKit oferece suporte a projetos de código aberto com ferramentas inovadoras e inteligentes para monitorar e criar perfis de aplicativos Java e .NET.
YourKit é o criador do YourKit Java Profiler, YourKit .NET Profiler e YourKit YouMonitor.