Aleph предоставляет данные из сети в виде потока Manifold, который можно легко преобразовать в канал java.io.InputStream
, канал core.async, последовательность Clojure или многие другие байтовые представления. Он предоставляет простые оболочки по умолчанию для HTTP, TCP и UDP, но обеспечивает доступ к полной производительности и гибкости базовой библиотеки Netty.
Лейнинген:
[aleph " 0.8.2 " ]
deps.edn:
aleph/aleph { :mvn/version " 0.8.2 " }
; ; alternatively
io.github.clj-commons/aleph { :git/sha " ... " }
Aleph полностью соответствует спецификации Ring и может заменить любой существующий сервер, совместимый с Ring. Однако это также позволяет функции-обработчику возвращать отложенный Manifold для представления возможного ответа. Эта функция может не очень хорошо работать с промежуточным программным обеспечением синхронного кольца, которое изменяет ответ, но это можно легко исправить, переопределив промежуточное программное обеспечение с помощью оператора Let-flow в Manifold. Помощник aleph.http/wrap-ring-async-handler
можно использовать для преобразования асинхронного 3-арного обработчика Ring в совместимый с 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
Тело ответа также может быть многообразным потоком, где каждое сообщение из потока отправляется как фрагмент, что позволяет точно контролировать потоковые ответы для событий, отправленных сервером, и других целей.
Для запросов клиента HTTP Aleph моделирует себя по образцу clj-http, за исключением того, что каждый запрос немедленно возвращает отложенный Manifold, представляющий ответ.
( 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 пытается полностью имитировать API и возможности clj-http. Он поддерживает запросы multipart/form-data, хранилища файлов cookie, прокси-серверы и проверку запросов с несколькими заметными отличиями:
Конфигурация прокси-сервера должна быть установлена для соединения при настройке пула соединений, настройка прокси-сервера для каждого запроса не разрешена.
Функциональность HTTP-прокси расширена за счет настроек туннелирования, дополнительных HTTP-заголовков и контроля времени ожидания соединения, см. все ключи конфигурации.
:proxy-ignore-hosts
не поддерживается
как промежуточное программное обеспечение файлов cookie, так и встроенные хранилища файлов cookie не поддерживают параметры файлов cookie, устаревшие с момента RFC2965: комментарий, URL-адрес комментария, отказ, версия (см. полную структуру файла cookie).
при использовании :debug
, :save-request?
и :debug-body?
опции, соответствующие запросы будут храниться в ключах :aleph/netty-request
, :aleph/request
, :aleph/request-body
карты ответов.
Опция :response-interceptor
не поддерживается.
Aleph представляет конфигурацию пула соединений :log-activity
для включения регистрации изменений состояния соединений, а также шестнадцатеричных дампов запросов/ответов.
Параметры :cache
и :cache-config
на данный момент не поддерживаются.
Клиент Aleph также поддерживает полностью асинхронный и настраиваемый преобразователь DNS.
Чтобы узнать больше, прочитайте пример кода.
Начиная с версии 0.7.0, Aleph поддерживает HTTP/2 как на клиенте, так и на сервере.
По большей части поддержка HTTP/2 в Aleph является полной заменой HTTP/1. Однако для обратной совместимости Aleph по умолчанию использует только HTTP/1. См. пример кода HTTP/2 для получения хорошего обзора начала работы с HTTP/2.
Что следует знать:
pipeline-transform
для изменения базового конвейера Netty, вам необходимо проверить его использование для HTTP/2. Под капотом новый код HTTP/2 использует настройку мультиплексного конвейера Netty с общим конвейером уровня соединения, который передает кадры, специфичные для потока, в N конвейеров, созданных для N отдельных потоков. (Стандартная пара HTTP-запрос/ответ отображается в один поток H2.) В любом HTTP-запросе, который имеет правильные заголовки Upgrade
, вы можете вызвать (aleph.http/websocket-connection req)
, который возвращает отложенный запрос, который дает дуплексный поток , который использует один поток для представления двунаправленной связи. Сообщения от клиента можно получать через take!
и отправляется клиенту через put!
. Тогда обработчик echo WebSocket будет состоять из:
( require '[manifold.stream :as s])
( defn echo-handler [req]
( let [s @( http/websocket-connection req)]
( s/connect s s)))
Это принимает все сообщения от клиента и передает их обратно в дуплексный сокет, возвращая их клиенту. Текстовые сообщения WebSocket будут отправляться в виде строк, а двоичные сообщения — в виде массивов байтов.
Клиенты WebSocket могут быть созданы через (aleph.http/websocket-client url)
, который возвращает отложенный поток, который дает дуплексный поток, который может отправлять и получать сообщения с сервера.
Чтобы узнать больше, прочитайте пример кода.
TCP-сервер аналогичен HTTP-серверу, за исключением того, что для каждого соединения обработчик принимает два аргумента: дуплексный поток и карту, содержащую информацию о клиенте. Поток будет генерировать массивы байтов, которые можно преобразовать в другие представления байтов с помощью библиотеки байтовых потоков. Поток будет принимать любые сообщения, которые можно привести к двоичному представлению.
Эхо-TCP-сервер очень похож на приведенный выше пример WebSocket:
( require '[aleph.tcp :as tcp])
( defn echo-handler [s info]
( s/connect s s))
( tcp/start-server echo-handler { :port 10001 })
TCP-клиент можно создать через (aleph.tcp/client {:host "example.com", :port 10001})
, который возвращает отложенный поток, который дает дуплексный поток.
Чтобы узнать больше, прочитайте пример кода.
Сокет UDP можно создать с помощью (aleph.udp/socket {:port 10001, :broadcast? false})
. Если указан :port
, будет создан дуплексный сокет, который можно использовать для отправки и получения сообщений, которые структурированы как карты со следующими данными:
{ :host " example.com "
:port 10001
:message ...}
Входящие пакеты будут иметь :message
, который представляет собой массив байтов, который можно преобразовать с помощью byte-streams
, а исходящие пакеты могут представлять собой любые данные, которые можно привести к двоичному представлению. Если :port
не указан, сокет можно использовать только для отправки сообщений.
Чтобы узнать больше, прочитайте пример кода.
Aleph использует Leiningen для управления зависимостями, запуска REPL и тестов, а также создания кода.
Минимальная поддержка tools.deps
доступна в виде файла deps.edn
, который создается из project.clj
. Его достаточно, чтобы можно было использовать Aleph в качестве зависимости git или :local/root
. При фиксации изменений в project.clj
запустите deps/lein-to-deps
и также зафиксируйте полученные изменения.
Copyright © 2010-2024 Закари Теллман
Распространяется по лицензии MIT.
Большое спасибо YourKit за поддержку Алефа. YourKit поддерживает проекты с открытым исходным кодом с помощью инновационных и интеллектуальных инструментов для мониторинга и профилирования приложений Java и .NET.
YourKit является создателем YourKit Java Profiler, YourKit .NET Profiler и YourKit YouMonitor.